-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MaybeDangling #3336
MaybeDangling #3336
Conversation
Does Some naming alternativesOnly slightly tongue-in-cheek:
These names also have the advantage of not implying they only impact dangling/ I also find it somewhat amusing that this kind of ends up introducing a new pointer type. |
Oh... yeah that is not great. :/
This is still quite different from
I like those, they match the previous sentence about being "on hold".
Hm... yes maybe? No strong opinion here; I assumed it'd be |
This is a good observation, because the documentation of
Note that
As mentioned in the RFC, the difference between I also don't have a strong opinion here, but it seemed worthwhile to at least consider this for the decision for whether to implement |
To clarify, is |
Yes, it propagates all the auto traits and |
(@Pointerbender FWIW the "for smart pointers" wording has been considered for removal a few times before, and still is. The general consensus is more along the lines of "when |
A potential future possibility with this RFC is to use it to resolve the self-referential-generator-aliasing situation: these generators need to be pinned anyway, and if we define |
That's not fully sufficient by itself; you still need some way to do pin projection. Currently that's done with the |
Hm... yeah you are right, those |
Do the effects of |
A |
Perhaps making It makes sense to me that an object with dangling references is dropped manually, because user of that type already has to be careful about when it is dangling (e.g. drop order of fields in self-referential structs is important). In the worst case it should be possible to make a DIY |
The alternative is mentioned in the RFC. The RFC also has 2 use-cases for |
I have created an issue to track the experiment: rust-lang/rust#118166. Looking for someone to implement the type and its magic behavior now. :) |
Btw, the RFC could nowadays mention https://docs.rs/maybe-dangling as a third-party implementation thereof |
text/0000-maybe-dangling.md
Outdated
Notice that `UnsafeCell` acts "behind references" while `MaybeDangling`, like `MaybeUninit`, acts "around references": `MaybeDangling<&T>` vs `&UnsafeCell<T>`. | ||
|
||
There is a [crate](https://docs.rs/maybe-dangling) offering these semantics on stable Rust via `MaybeUninit`. | ||
(This is not "prior" art, it was published after this RFC came out. "Related work" would be more apt. Alas, the RFC template forces this structure on us.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extreme pedantry: arguably, "prior" in "prior art" as used by the RFC template means "prior to when this RFC is accepted." The history of past revisions of the RFC document is not part of the final product that gets FCPed and published in the RFC Book. So "prior art" is an accurate description of https://docs.rs/maybe-dangling, and the RFC template is perfectly innocent here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not how the term "prior art" is usually used in scientific context. When there is a causal dependency where A caused B, then B cannot be prior art of A, even if the publication of paper A happens after B becomes public. (There is often a significant delay between writing and submitting a paper, and having it published.) Here, as far as I can see, the RFC inspired that crate, so if anything the RFC is prior art for the crate, not vice versa.
Alas, I have several gripes with the strict form of the template, but not the patience to try and fix it.^^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way I see it, the initial draft of the RFC inspired the crate, which in turn inspired a subsequent draft. But that subsequent draft should be considered a distinct document from the initial draft. Published RFCs, unlike scientific papers, are considered as emanating from the team that approved them, and represent the perspective of that team at the time of FCP approval (the original author is not even listed in the RFC Book).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I disagree, but it doesn't seem useful to discuss this here.
text/0000-maybe-dangling.md
Outdated
# Reference-level explanation | ||
[reference-level-explanation]: #reference-level-explanation | ||
|
||
The standard library contains a type `MaybeDangling<P>` that is safely convertible with `P` (i.e., the safety invariant is the same), and that has all the same niches as `P`, but that does allow passing around dangling boxes and references within unsafe code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is it possible to have both (1) MaybeDangling<P>
and P
are safely convertible and (2) P
holds more guarantees than MaybeDangling<P>
? If they are convertible, one could safely pass say MaybeDangling<&'a mut T>
to a fn(&'a mut T, ...)
which itself is compiled with noalias assumption, and result in undefined behaviors. If P -> MaybeDangling<P>
is safe and MaybeDangling<P> -> P
is unsafe, then what's the difference between MaybeDangling
and MaybeUninit
?
I also disagree with the disagreement by @RalfJung 's #3336 (comment):
MaybeDangling as currently specified by the RFC does not change safety invariants, as it implements safe >> Deref conversion like ManuallyDrop does. I argue that this is likely undesirable, and MaybeDangling should instead make it unsafe to reactivate the wrapped type and its invariants.
I think that would make MaybeDangling mostly useless -- one can already use MaybeUninit for something like that. I consider not having to use unsafe code to get the inner data back out of the no-dangling wrapper to be a feature. For example, this would have avoided adding unsafe code in rust-lang/rust#102589.
No. It's intrinsically unsafe to have fn(SomeType<'some_life>)
where 'some_life
may ends in the middle of the function invocation depending on its logic. In that case (example 2 of this RFC), the validity is controlled by the runtime logic and is impossible to check at compile time (eg. cannot prevent you from "accidentally" swapping closure();
and control.signal_done();
), thus guarantees should be made by programmer, unsafe
is required, with or without MaybeDangling
. Then I don't really see the advantage of introducing another MaybeDangling
than MaybeUninit
.
The dereferenceability of ManuallyDrop
in example 1, I think, is a separate issue. It's a choice between UB on state observed and UB on state exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is it possible to have both (1) MaybeDangling<P> and P are safely convertible and (2) P holds more guarantees than MaybeDangling<P>?
There are validity invariants and safety invariants. The safety invariant of P
and MaybeDangling<P>
are identical, but the validity invariants are not.
Then I don't really see the advantage of introducing another MaybeDangling than MaybeUninit.
MaybeUninit
is a terrible solution for example 2 since one has to call drop
manually. That's fragile and error-prone. I think it is important that we have a way to not lose automatic drop but still pass around "opaque arbitrary data" without making extra claims about its memory validity.
Once we have implicit drop
, there's no reason to make into_inner
unsafe, since drop
will already implicitly convert to the inner type without unsafe code.
Around half a year ago, this was proposed to be merged so we can do experimentation. @joshtriplett @nikomatsakis @pnkfelix any chance you could tick your box? :) |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
text/0000-maybe-dangling.md
Outdated
To handle situations like this, Rust has a special type called `MaybeDangling<P>`: | ||
references and boxes in `P` do *not* have to be dereferenceable or follow aliasing guarantees. | ||
This applies inside nested references/boxes inside `P` as well. | ||
They still have to be non-null and aligned, and it has to at least be *possible* that there exists valid data behind that reference (i.e., `MaybeDangling<&!>` is still invalid). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MaybeDangling<&!>
is still invalid
Based on my current understanding of ref-to-never, this can change to "MaybeDangling<&!>
has an always-violated safety invariant"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
&!
has an impossible validity invariant according to the Reference, Miri, and MiniRust. So I don't think the text should change.
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
The FCP for RFC 3336 has completed. Let's prepare it to be merged.
The lang team has accepted this RFC and we've now merged it. Thanks to @RalfJung for pushing forward this important work, and thanks to all those who reviewed this and offered helpful feedback. For further updates, follow the tracking issue: |
@@ -3,7 +3,7 @@ | |||
- Feature Name: `maybe_dangling` | |||
- Start Date: 2022-09-30 | |||
- RFC PR: [rust-lang/rfcs#3336](https://github.com/rust-lang/rfcs/pull/3336) | |||
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) | |||
- Tracking Issue: [rust-lang/rust#118166](https://github.com/rust-lang/rust/issues/118166) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about also fixing the template which currently still reads "Rust Issue:" here
Declare that references and
Box
inside a newMaybeDangling
type do not need to satisfy any memory-dependent validity properties (such asdereferenceable
andnoalias
).Rendered
Thanks to @rust-lang/wg-unsafe-code-guidelines for a lot of helpful feedback :)
Tracking: