Do not automatically DerefMut ManuallyDrop through union references#151920
Do not automatically DerefMut ManuallyDrop through union references#151920eggyal wants to merge 3 commits intorust-lang:mainfrom
Conversation
This comment has been minimized.
This comment has been minimized.
|
@rustbot author |
|
Reminder, once the PR becomes ready for a review, use |
|
Hm. Well, that build failure isn't wrong... the |
|
That said, reading the motivating Potential pitfalls around Not sure who needs to be brought in on resolving this? @RalfJung (as author of the RFC and current implementation), can you point me the right way or ping the relevant team? |
|
I lost all context for this.^^ Can you summarize what the problem is? |
This comment has been minimized.
This comment has been minimized.
|
I'm not sure I follow -- the assignment is unsafe either way precisely because the destructor gets called. Can you explain what smallvec does and why it triggers your version of the lint? |
This comment has been minimized.
This comment has been minimized.
|
I would say the general goal is to avoid accidentally calling drop glue without the user intending to do so. I don't think being inside an I will nominate the issue for t-lang discussion to get their take on this. |
|
It would be good to get an idea of the overall fallout of this via crater. Not sure what the best way to do that is when a rustc dependency fails to build.
|
|
Another idea might be to extend the |
b8ff466 to
1491027
Compare
This comment has been minimized.
This comment has been minimized.
1491027 to
c89f2c7
Compare
|
Thanks for the feedback, @RalfJung. I've added a comment and further tests as suggested.
Agh, of course you're right. I got myself in a twist from the starting point of it being safe to assign directly to a union variant (because they are never
Perhaps there is (or could be) a flag or environment variable that we'd use when building rustc; then disable this check if its presence is detected at runtime? Also quite hacky, but maybe acceptable to get a crater run going. I'm going to explore the |
This comment has been minimized.
This comment has been minimized.
|
The Miri subtree was changed cc @rust-lang/miri |
252b5d9 to
9d37cd8
Compare
This comment was marked as resolved.
This comment was marked as resolved.
|
Okay! I think that's now doing what we want: auto Shall we see what crater impact there is? |
|
@bors try |
This comment has been minimized.
This comment has been minimized.
…ough-union-ref, r=<try> Do not automatically DerefMut ManuallyDrop through union references
|
@craterbot check |
|
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
🎉 Experiment
Footnotes
|
|
The currently proposed error is surely too pessimistic. For example, take the failures in the divan crate—which are something like this: union EitherVec<A, B> {
vec_of_a: ManuallyDrop<Vec<A>>,
vec_of_b: ManuallyDrop<Vec<B>>,
}
impl<A, B> EitherVec<A, B> {
/// `Self` is either always a `Vec<A>` or always a `Vec<B>`. This indicates which.
const VARIANT_A: bool = is_variant_a();
pub fn bikeshed_mutate(&mut self) {
unsafe {
if Self::VARIANT_A {
self.vec_of_a.bikeshed_mutate(); //~ ERROR not automatically applying `DerefMut`
} else {
self.vec_of_b.bikeshed_mutate(); //~ ERROR not automatically applying `DerefMut`
}
}
}
}Even if impl<T> Vec<T> {
fn bikeshed_mutate(&mut self) {
*self = vec![];
}
}...why is that a problem? What exactly is the footgun that we're trying to prevent here? 🤔
I guess this needs refining. When is the calling of drop glue "accidental" / when does the user "intend to do so"? I think the footgun most like arises when writing an assignment expression where resolving the assignee place entails a deref coercion through a union field to a target that is not EDIT: What about |
|
r? @RalfJung |
|
|
Yes... but of course there could be such an assignment inside Thanks for doing the crater run! That should give us enough data to nominate the issue for t-lang discussion. |
| LangItem::BikeshedGuaranteedNoDrop, | ||
| DUMMY_SP, | ||
| ), | ||
| [adjustment.target], |
There was a problem hiding this comment.
Previously this checked source, now it checks adjustment.target... I don't know anything about this code so I can't say what the consequences of that are.
There was a problem hiding this comment.
Previously it was an error if source was a ManuallyDrop, irrespective of the type it contains; now it's an error if the expression dereferences to a target that doesn't implement BikeshedGuaranteedNoDrop - so ManuallyDrop<MaybeUninit<T>> is fine, because the target of dereferencing the ManuallyDrop is guaranteed not to have drop glue; but ManuallyDrop<Vec<T>> errors because Vec<T> obviously doesn't have that guarantee.
|
I have also found the code that I had in mind when I said we might be relying on the union drop check things somewhere: rust/compiler/rustc_mir_build/src/check_unsafety.rs Lines 643 to 650 in 9cc2924 So, this is a different check from what we are discussing here, and also it is guarded by an assertion. So I think we are indeed free to relax this check in any way we see fit. |
|
☔ The latest upstream changes (presumably #153217) made this pull request unmergeable. Please resolve the merge conflicts. |
View all comments
Extends #75584 to situations where the union itself is accessed through a reference.
Fixes #141621
r? compiler