-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
dropck can be bypassed via a trait object method #26656
Comments
triage: I-nominated |
Hmm, so I don't think that the problem has to do with |
After thinking on this last night, I laid it out in my head this way. There is a properly very similar to variance, let's call it " For convenience, we also write Given some type declared like
In addition there are some ground rules:
Now the dropck can use these rules to decide when it should enforce stricter rules. In particular, if an lvalue of type The key point is that this property may access is independent from whether a value has a destructor. The intution is "if a destructor got ahold of a value of type |
Some implications of this, presuming this property is inferred in a similar fashion to variance:
|
Personally I think of the issue as being more related to liveness - every lifetime parameter to a function (or impl) is required to be alive when the function (that can access that impl) is called, but (because of dropck) type parameters passed to a function may not be alive. This is preserved by normal selection (as it can't dig into the dead type and find the dead lifetime), but trait objects (and equivalently, instantiations of generic functions) can "refer to" an impl that witnesses the liveness of the lifetime, and should be treated as such. |
@arielb1 I don't disagree with all that. It is certainly intentional that dropck allows access to "potentially dead data" in some cases. The original formulation did not, but we found it was very strict. The goal of the "may observe" relation I was discussing is to specify precisely when it is ok to allow access to potentially dead data, because we can be sure that the data will not be used. /me kind of misses the days when data with dtors was always |
Heh, dtors could always refer to dead types (with |
@arielb1 yes, they were only ever |
okay clearly the Sound Drop RFC needs some updating. The observation that parametricity is not a sufficient condition is important. I will try to incorporate the comments above into a PR on the rfcs repo (either a new RFC or an amendment to Sound Drop, depending on how bad the damage is). |
triage: P-high (soundness issue) |
The more I think about this, the more I would prefer to back away from the current (unsound, as demonstrated here) parametricity-based reasoning and lean on something simpler (e.g., an unsafe annotation), at least for the time being, if not forever. |
For the public record My opinion is that if bugs like this and #26657 were the only known issues with dropck, then I would prefer to try to improve the reasoning performed by dropck, rather than rely on user-provided annotations that are likely to be misunderstood and abused, yielding bugs that are hard to witness (i.e. that I expect naive testing to miss). However, given that there are also issues with the proposed specialization RFC, I am now investigating adding an unsafe annotation along the lines noted above. (Still, it would be nice if in parallel with paring back on dropck for the short term, if we also tried to be forward-thinking and not add features that will make it impossible to put back parametricity based reasoning in the future. Okay, that's enough out of me.) |
It took me a while to understand why trait objects even help in circumventing dropck... my current conclusion is that in EDIT: I also wonder how Rust chooses the lifetime for EDIT2: Coming back to my point above: Rust only assumes |
@RalfJung my go-to example when thinking about this is a struct that carries both some object and a callback on that object: struct S<T> { x: Option<T>, f: fn (T) } To my mind, The above properties are not violations of parametricity. (it is what I see as a celebration of parametricity: it allows one to make very strong statements about what clients can do with instances of With our current buggy dropck, however, one is allowed to pass the
|
@pnkfelix That's a great example, thanks a lot! I think I understand now. |
Right. And this can be fixed (after @nikomatsakis's patch) by making On the other hand, ordinary parametricity isn't really the important condition for dropck. Rust code is always perfectly parametric about lifetimes. One theoretical way to make dropck work with specialization is to change the "vtables" during destruction, C++-style, which is basically a gaping violating of parametricity. Even without that, you can safely:
|
/me has been officially nagged by @nikomatsakis to put up a PR for the implementation of RFC rust-lang/rfcs#1238 |
This is basically fixed, but we don't have a specific regression test. |
Nominating as this is a soundness bug that has yet to have a priority assigned. |
@bstrie this has been fixed, we're just waiting on a regression test. |
Long awaited regression test for dropck on trait object method. Fix #26656.
Hey, guys. I am trying to understand why parametricity is not enough for dropck. I'm not sure if code here could prove the point.
Sage insights are appreciated. |
STR
This fails the assertion. cc @pnkfelix. I think the problem here is that
Box<Trigger<B>+'static>
does not require thatB: 'static
(cc @nikomatsakis).The text was updated successfully, but these errors were encountered: