Skip to content

Tracking issue for Rc::into_raw, Rc::from_raw, Arc::into_raw, Arc::from_raw #37197

Closed

Description

@cristicbz

Methods being added in #37192.

Activity

  1. added a commit that references this issue on Nov 8, 2016
  2. cristicbz commented on Dec 21, 2016

    @cristicbz
    ContributorAuthor

    @alexcrichton shouldn't this have a B-unstable label? Don't know if it matters, but I figured I'd check.

  3. alexcrichton commented on Dec 21, 2016

    @alexcrichton
    Member

    Oops, indeed!

  4. added
    B-unstableBlocker: Implemented in the nightly compiler and unstable.
    T-libs-api[DEPRECATED; DO NOT USE]
    on Dec 21, 2016
  5. alexcrichton commented on Dec 21, 2016

    @alexcrichton
    Member

    And while we're at it, I'd like to stabilize this!

    @rfcbot fcp merge

  6. rfcbot commented on Dec 21, 2016

    @rfcbot

    Team member @alexcrichton has proposed to merge this. The next step is review by the rest of the tagged teams:

    No concerns currently listed.

    Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

    See this document for info about what commands tagged team members can give me.

  7. Amanieu commented on Dec 26, 2016

    @Amanieu
    Member

    Is there any chance of putting from_raw and into_raw into a trait or would that be a breaking change for Box?

  8. Amanieu commented on Dec 26, 2016

    @Amanieu
    Member

    Also I think from_raw and into_raw for Rc and Arc should accept unsized types, just like the implementations for Box.

  9. alexcrichton commented on Dec 26, 2016

    @alexcrichton
    Member

    @Amanieu could you elaborate on why you'd like to see these as a trait? I do think that'd be a breaking change to remove the inherent methods on Box (unless we add the trait to the prelude), but that doesn't meant we could also add a unifying trait later. We've just tended to avoid premature abstraction in libstd with extra traits.

    Also on a technical level is accepting unsized types possible? Consider something like going from Rc<Trait> to *mut Trait. The vtable for *mut Trait has to come from somewhere, and the only one we have is the vtable for Rc<Trait>. Those methods expect the pointer being passed into them is *mut RcBox<T>, not *mut T. In that sense I don't think we could support unsized types?

  10. Amanieu commented on Dec 27, 2016

    @Amanieu
    Member

    @alexcrichton I'm building a safe interface for intrusive-collections, which works by having a collection "take ownership" of an owned pointer. This is done by calling into_raw before inserting an object into a collection, and calling from_raw when an object is removed from a collection. I currently define an IntrusivePointer trait myself which does this, so I guess a trait in the standard library isn't really needed.

    Regarding vtables, I was under the impression that the vtable pointer in *mut RcBox<Trait> pointed to the same vtable as *mut Trait since the fat part of the point is only associated with the unsized part of a struct (Trait). This means that the compiler will first extract a pointer to the Trait before passing it to the vtable methods. On the other hand I am not very familiar with how vtables work in Rust, so I may be wrong here.

  11. alexcrichton commented on Dec 28, 2016

    @alexcrichton
    Member

    Hm yeah it's true I'm not entirely sure what the vtable would look like. Would be good to clarify before we support the functionality!

  12. Amanieu commented on Dec 28, 2016

    @Amanieu
    Member

    &RcBox<Trait> and &Trait have the same vtable pointer: https://is.gd/QNfAIo

  13. ishitatsuyuki commented on Dec 29, 2016

    @ishitatsuyuki
    Contributor

    I'm looking forward to have something like std::shared_from_this(C++), thus constructing a new Arc from a reference (probably &self).

  14. cristicbz commented on Dec 29, 2016

    @cristicbz
    ContributorAuthor
  15. 27 remaining items

  16. rkjnsn commented on Feb 15, 2017

    @rkjnsn
    Contributor

    As I understand it (forgive me if I am mistaken in here somewhere), Shared holds a *const T, so it is covariant if T is. Thus it would be trivial to get a *mut T with a different lifetime just by coercing a Shared instance before calling deref. Since Shared is copy, it is trivial to store a value through pointer with a shorter lifetime and read it back out via the the pointer with a longer lifetime. This is bad! (Yes, this requires unsafe code, but it's a serious footgun, and I believe preventing this type of footgun is the reason *mut is considered by the compiler to be invariant.)

    Further, since Shared is Copy (because it is designed to be shared), that means, like Rc itself, the data pointed to should not be considered mutable except for parts contained in an UnsafeCell.

    Finally, neither Rc nor Arc have any need for Shared to hand out *mut pointers during active usage, since the counts themselves are already contained in UnsafeCell (as they must be for soundness, with Rc using Cell and Arc using AtomicUsize)

    It seems to me, then, that Shared should also definitely be handing out *const and not *mut pointers. The data pointed to is meant to be shared and thus shouldn't be considered mutable; Shared is covariant, making handing out *mut pointers even more dangerous; and neither Rc nor Arc need *mut for their shared operations because they only mutate through UnsafeCell.

    If I had to speculate, I would guess that Shared returns a *mut pointer because when the last reference is destroyed, Rc and Arc need a mutable pointer to execute drop. However, I think a cast from *const to *mut should be necessary here as a way to assert, "I know I am currently the sole owner of this data."

    EDIT: Rather, I would speculate that Shared returns a *mut because it was replacing NonZero<*mut RcBox>, and that that was originally *mut because that's what Box::into_raw returns and because that's what drop needs. That is to say, it seems like a historical accident, and I would argue that both Shared::deref and Rc::into_raw should return *const

  17. alexcrichton commented on Feb 15, 2017

    @alexcrichton
    Member

    That seems like a reasonable explanation to me, and if we change Shared as well I think it makes sense to change Rc at the same time.

    @brson do you have other specific thoughts here?

  18. Amanieu commented on Feb 15, 2017

    @Amanieu
    Member

    So what is the consensus regarding support for DSTs? We could start by only implementing into_raw and from_raw for sized types, and later extend them to DSTs.

  19. brson commented on Feb 15, 2017

    @brson
    Contributor

    I'm not very enthusiastic about stabilizing this with so much confusion about the proper type.

    The questions about variance worry me too. If there are variance concerns here let's add tests for them. This all feels risky.

  20. cristicbz commented on Feb 15, 2017

    @cristicbz
    ContributorAuthor

    So #29110 added Shared specifically to make Rc and Arc covariant; looking at that PR it seems that @rkjnsn is right about *mut being due to it replacing a pointer obtained via Box::into_raw.

    @brson What sort of tests would you like added? For the variance of Rc and Arc (define some noop fn-s like I did in the above playground link)? I can't think of any way to test it specifically around the new {into,from}_raw methods.

    @Amanieu DST-wise yeah I thought that's sort-of where we left it. For DST-s it's a slightly bigger can of worms (see #37197 (comment)) and I'd be too worried about potential UB without an offsetof built into the compiler. Like you said, it will be trivially backwards compatible to extend this to DST-s when we're happy.

  21. rfcbot commented on Feb 23, 2017

    @rfcbot

    The final comment period is now complete.

  22. cristicbz commented on Feb 23, 2017

    @cristicbz
    ContributorAuthor

    Since the FCP is over, I'll sum up where I stand:

    1. I'm not worried about variance here: since Rc is covariant, I feel like you can't end up being over-permissive.
    2. I prefer *const T, but I don't massively care. Mutating the data behind the pointer obtained through into_raw is generally UB. If T is a cell, the as_ptr method on the cell is the correct way to get a mutable pointer.
    3. I'd punt on DST-s until there's a built-in offsetof. They're easy to add later backwards-compatibly.
  23. rkjnsn commented on Feb 25, 2017

    @rkjnsn
    Contributor

    My summary:

    1. I agree that *const being covariant isn't an issue given that Rc is.
    2. I am strongly opposed *mut here and think *const is clearly the way to go. *mut is dangerous both because Rc's covariance would make it too easy to get mut pointers to the same data with different lifetimes and because muting shared data without UnsafeCell is in violation of Rust‘s guarantees and likely to result in unsound behavior. In cases where it is guaranteed that ownership is exclusive, it's easy enough to cast to *mut (with a comment explaining why it's sound in that instance).
    3. I agree that it makes sense to get this in for Sized types and then figure out DSTs.
  24. alexcrichton commented on Feb 25, 2017

    @alexcrichton
    Member

    Ah so to clarify the FCP ending here is just the standard one week period. In reality it'll "end" a week before the end of the cycle when we merge this.

    I'm leaning towards changing to const, pending input from @brson.

  25. alexcrichton commented on Feb 28, 2017

    @alexcrichton
    Member

    Discussed during @rust-lang/libs triage today, the conclusion was to go with *const with these APIs and update Shared at the same time. If no one else gets around to it sooner I'll update when I do the blanket "stabilize everything" PR

  26. added a commit that references this issue on Mar 17, 2017
    c2d2c2d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    B-unstableBlocker: Implemented in the nightly compiler and unstable.T-libs-api[DEPRECATED; DO NOT USE]final-comment-periodIn the final comment period and will be merged soon unless new substantive objections are raised.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions