-
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
Add SafeDeref/SafeDerefMut #1873
Conversation
What does "same" mean? Does it mean that the returned reference, if coerced to a pointer, stays at the same address? Is it the same as https://docs.rs/owning_ref/*/owning_ref/trait.StableAddress.html ? |
No, it's not about staying at the same memory location. It means that The consequence is that if an object doesn't provide any way (after initialization) to mutate one of its fields, then the value of that field in the object returned by |
and that writing a rogue implementation of `Deref` should always result in either a logic error or | ||
a panic because in the end we're only manipulating memory after all. | ||
|
||
- The prefix `Safe` is maybe not great. |
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.
Another alternative is to add a lint that checks Deref
impls and whether they either end up giving a static offset into the struct itself, or if the impl somehow generates an address from an unsafe pointer, whether there are any safe &mut self
functions that modify that pointer themselves or through other function calls.
After some time, make that lint a deny-by-default lint.
Not sure if all valid Deref
impls can be proven valid by such a lint, but I can't think off the top of my head of a good impl that is disallowed by such a lint.
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.
We have used the Trusted
prefix before, I think for TrustedExactSize
maybe?
Is this an issue for |
The issue that this RFC is trying to fix arises only in the situation described in the "motivation" example, and I think that in this situation |
|
||
```rust | ||
unsafe trait SafeDeref: Deref {} | ||
unsafe trait SafeDerefMut: SafeDeref + DerefMut {} |
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.
Is a separate SafeDerefMut
trait necessary? It seems like we don't necessarily need to distinguish since Deref
and DerefMut
impls that behave that differently also seems like a thing that we'd want to prohibit with such a trait.
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.
Good point!
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.
To be fair, the pattern violating this would be Cow
.
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.
Ah yeah, Cow
is a good counter-example.
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.
Is Cow
really different here from a Vec
that has been pushed/extended beyond its previous capacity between two Deref
calls?
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.
Impure DerefMut
.
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'm confused. Cow
does not satisfy DerefMut
and its Deref
method looks pure.
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.
Ah right, I forgot the types differ so it can't use DerefMut
- for some reason I thought it did.
I would rather call it |
Could we potentially have a general mechanism for this "trusted trait" thing (which has come up for other traits before, like I don't really want to encourage the use of these - as (I think it was @nikomatsakis?) put it back when "trusted |
Update: This comment can be ignored as it was based on my miss-understanding of the RFC. There is always a contract that an There is still no answer to whether this can be fixed with an inline directive, like :
In any case, I think one should not necessarily expect to solve optimization problems like this in the type system. We write If a judicious
In this case, I think Now if Addendum: Just to be clear, one could imagine a Edit: I've replaced |
If I understand correctly, it sounds like this RFC's use case actually hangs on these two
And I think their correctness actually hangs on the same issue of deref coercions not occurring inside In other words, if an attribute based solution fails here, then I think the extra trait approach proposed by this RFC should fail too, so one needs to either modify the |
Yes, but the stakes are 'merely correctness', not safety (UB), so
Yes.
No, it just raises the stakes of not satisfying them from incorrect behavior to UB. The idea is just that instead of introducing new You're right (if that's what you meant to say) that this wouldn't by itself be sufficient for the So it would be a two-part solution:
1. by itself is not enough because it doesn't let |
You mean the compiler should know that What do you mean by "raises the stakes" in general though? Could one write a bound |
Maybe I've been misunderstanding, but I think this RFC isn't about what the compiler/optimizer may assume, but about what someone writing |
You're right. I missunderstood the RFC. Oops! The RFC wants a bound Could this be done without any unsafety by combining trait fields with specialization?
As written, the trait field In any case, we want two Ain't clear if there is even a breaking change here. It'd makes implementing |
@burdges @tomaka Here is a crate which defines its own |
There are likely I wonder if all these traits should just be more explicit about the invariants that they require, while if you violate them then we judge that undefined behavior to be acceptable, or even intentional, as if you use a random number generator. |
So should I close this PR as a duplicate of #1646? |
I'll post a partial summary over there in case you do.
I'm sympathetic to @glaebhoerl idea that any trait could've an unsafe variant, but it'd kinda make
|
I appreciate the minimal nature of this RFC -- when I first opened it to read it, I was expecting something quite different. But I think overall I would be inclined to postpone it for now -- it seems like something that we can evolve a bit "in library land" (as, indeed, has already happened), perhaps as a I find @glaebhoerl's idea of a generalized concept of "unsafe trait" interesting, but it seems... well, let's just say it'd require a bit more elaboration too. In particular, it's not like the "unsafe contract" for a given trait is clear a priori, so I think I would not want to allow |
Thanks, @tomaka, for this RFC. FWIW, I agree entirely with @nikomatsakis's synopsis. I believe that @rfcbot fcp postpone |
Team member @aturon has proposed to postpone 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. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
There is now a crate on crates.io that provides |
The final comment period is now complete. |
Looks like not much new came up during the FCP, so closing. Thanks again though for the RFC @tomaka! |
Rendered
I'm not a fanatic of this change, but I think it is necessary. I'd understand if it was closed, but in my opinion this is the least bad thing to do.