-
Notifications
You must be signed in to change notification settings - Fork 183
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
Fix soundness issue in Yoke::attach_to_cart() around implied bounds #2949
Conversation
d47aaae
to
4bab396
Compare
This comment was marked as outdated.
This comment was marked as outdated.
You can define an invariant marker using |
oh beautiful, thanks. Forgot you could do that. |
What are example call sites that work in option 1 but not option 2 and vice versa? |
Option 1 (force invariance):
Option 2:
|
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 see; I think we definitely want Yoke<T, &[u8]>
to have a covariant lifetime.
Is there a difference between Option 1 and Option 2 regarding the ability to borrow local variables, like you can apparently do now? |
In the At this point I'm heavily leaning towards Option 2 and I think we should just do that, I just need to update this PR. |
(PR description should be updated to state that option 2 is taken by the PR instead of option 1) |
Hmm, is the IsCovariant stuff even meaningful now? I don't think it enables anything |
@sffc are you fine with me removing IsCovariant? I can't remember why we added it, I think we wanted it for trait objects but we don't need it anymore |
This change doesn't break it but it breaks any meaningful tests of IsCovariant since it mostly useful for trait objects with nested borrows |
IsCovariant originated in #1041 to fix #760. The line of code using Alternatively, should we use |
I still think that carts with complex borrowing are probably a sign of bad design (especially nested yoking like we were doing there); and we should not aim to support them in our main We still support trait objects as carts, just not trait object carts where the borrowing is hidden behind the trait object, constructed via We may even be able to expose safe APIs for some of the use cases here, but I'd want to separate it from the primary attach_to_cart API either way.
That requires far more |
I removed IsCovariant. If the use case crops up again we can try to design for it more clearly, or just bring IsCovariant back (the rest of this PR does not break IsCovariant, it just makes it harder to write a useful example, and I'm a bit uncomfortable writing one without thinking a lot about soundness) |
Fixes #2926
The reasoning can be found in the safety docs added.
There are two potential fixes here. One is to force Yoke to always be invariant over any lifetimes found in the cart. This is unfortunate, since
Yoke<_, &[u8]>
is a useful cart and there's no actual safety reason for that to need to be invariant. Invariant lifetimes are annoying to work with. However, the safe functionattach_to_cart()
will support all carts, including ones with wacky borrowing.The alternative is to enforce
C::Target: 'static
inattach_to_cart()
. This will still allowYoke<_, &[u8]>
to be constructed with the method, but if there are borrows behind the deref, they will have to be constructed unsafely viareplace_cart()
. That's unfortunate but retains maximum flexibility for the user. I prefer this.The latter is what is implemented.