-
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
Promotion creates invalid constants that are never used in invalid ways #67534
Comments
Also see this Zulip thread. I am still not 100% of the soundness of this -- the UB in code like this relies on subtle and unstable details of current Stacked Borrows. In other words, assuming that what we currently do is sound makes some very strong statement about Rust semantics that @rust-lang/lang never signed off. How hard would it be to make rustc reject such (IMO) broken promoteds, and use crater to determine how widely this pattern is used? The examples you showed so far are all extremely niche. |
I think it would be fine, but I feel like the motivation to do so is weak. This is completely sane from a user perspective, and feels like the zero cost magic that Rust gives us. |
this is the more realistic example that I would expect to see out there. |
I can't see anything sane about this from any perspective.^^ "This seems fine" is how we got ourselves in lots of trouble with promotion...
The burden of motivation is on whoever writes an RFC to add support for this to rustc, IMO. That this didn't happen is an accident. |
I also don't think "this is unsound in all but our most complex Rust semantics" is a pretty strong motivation for not doing this. ;) |
This didn't happen by accident, this is entirely by design afaict (cc @eddyb). Though I'm not sure how much of that was RFCed. Implicit promotion is definitely not our proudest moment in RFCing and stabilizing. |
In that design, what was the soundness argument? Because as far as I can see, one can trivially break soundness of this scheme by doing some pointer arithmetic outside the bounds of the reference one gets. Yes, Stacked Borrows currently disallows this, but (a) Stacked Borrows didn't exist yet when this was designed, so that cannot have been the argument, and (b) this is one of the Stacked Borrows properties that people semi-regularly run into and complain about (e.g. here and here). |
What is being proposed, in terms of potentially breaking changes?
It's unreasonable to assume that you can access any other fields through the latter, so do we want to force people through that? I'm bringing this up because it's easy for us to treat them like equivalent, or a lot easier than the runtime indexing case, at least. I think the reason for the original behavior (before the runtime indexing special-case, and even before MIR) was that accessing a field always cleared "qualifications" that didn't apply to the field type, even if in the borrow itself - that is, AFAICT, this was kept during the move the MIR, and only slightly tweaked later. rust/src/librustc_mir/transform/promote_consts.rs Lines 323 to 341 in 117ceeb
|
Not sure which part of our semantics you are basing that on, other than Stacked Borrows. Not being able to access stuff "outside" of where the pointer points to is a frequent issue with raw pointers. |
@RalfJung "the latter" refers to |
Oh I see... because that evaluated |
Marking it as p-high based on the wg-prioritisation discussion |
I was doing such a good job of ignoring this issue, and now it's P-high 😆 We can't really write a forward compat lint for this, as the user may not be using the promoted in a |
Here's another horrible thing we could do: we could change the type of the promoted to replace all Or does this also work for custom struct constructors, not just with tuples like in the example? |
Yea this will also work for your own structs. We can wrap the entire thing in a |
That does nothing with |
FWIW, this code is currently not even accepted inside a function, I think? It only works inside another |
validate promoteds Turn on const-value validation for promoteds. This is made possible now that rust-lang#67534 is resolved. I don't think this is a breaking change. We don't promote any unsafe operation any more (since rust-lang#77526 landed). We *do* promote `const fn` calls under some circumstances (in `const`/`static` initializers), but union field access and similar operations are not allowed in `const fn`. So now is a perfect time to add this check. :D r? `@oli-obk` Fixes rust-lang#67465
Namely, we can have promoteds with interior mutable types but in an immutable allocation.
#67000 makes this explicit by introducing the
ignore_interior_mut_in_const_validation
field on the const interner.We should instead rewrite such promoteds to just contain the parts of the promoted that is accessed. So
currently produces
And we should be producing
This is definitely a nontrivial transformation, especially since it needs to be done on the generic promoted and not the computed final value (generic e.g. if we had
T::CELL_VALUE
instead ofCell::new(42)
).The reason it needs to be done on the MIR is that we also need to change the projection for obtaining the value of
x
, which we have no control over if we did it on the final constant.The text was updated successfully, but these errors were encountered: