-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Track the "static"-ness of slots in MIR and detect drops in constant initializers. #40036
Comments
I've done a crater run with the rule-enforcing side of this (i.e. non- In fact, it's the sort of thing we want to break ASAP (and is blocking |
Forward-compatibly deny drops in constants if they *could* actually run. This is part of #40036, specifically the checks for user-defined destructor invocations on locals which *may not* have been moved away, the motivating example being: ```rust const FOO: i32 = (HasDrop {...}, 0).1; ``` The evaluation of constant MIR will continue to create `'static` slots for more locals than is necessary (if `Storage{Live,Dead}` statements are ignored), but it shouldn't be misusable. r? @nikomatsakis
Forward-compatibly deny drops in constants if they *could* actually run. This is part of #40036, specifically the checks for user-defined destructor invocations on locals which *may not* have been moved away, the motivating example being: ```rust const FOO: i32 = (HasDrop {...}, 0).1; ``` The evaluation of constant MIR will continue to create `'static` slots for more locals than is necessary (if `Storage{Live,Dead}` statements are ignored), but it shouldn't be misusable. r? @nikomatsakis
As a data point, this did break some code of mine that isn't in crater, i.e. https://play.rust-lang.org/?gist=469a2c849813388f856bdacf55327d9e&version=nightly, but such is the risk of using unstable features. |
@aidanhs Breaking that kind of code was entirely intentional! You see, if you have: let FOOS: &[Foo] = &[foo(&S)]; Even with no For your code in particular, either replacing the |
Yeah I get that it's consistent with behavior within functions now, I have indeed replaced it with direct struct creation. |
cc @rust-lang/wg-const-eval Do we want to just close this issue? At this point it seems that " |
Sgtm, I didn't know this issue still existed since we are handling everything nicely with the storage statements |
cc @RalfJung |
I do not understand the context of the original post here, but I agree that what we do currently seems nicer than having two kinds of "MIR slots". |
Right now we distinguish between "constant initializer" (
static
,const
, promoted fragments) and "runtime" MIR, in that all locals in the former are'static
and drops on them are ignored.While this seems to work fine for the moment, it can't model, e.g. (mutable) local variables in "constant initializers" and may not be backwards-compatible with a model that can, if we stabilize any extensions.
Problematic example
If we accept rust-lang/rfcs#1817, the current implementation would allow both of these:
If we go by the rest of the language,
FOO
should drop the tuple after copying out its second field, whereasBAR
should borrow the tuple forever, and happen to be pointing at the second tuple (resulting in no drop).This is important even if we can't run destructors at compile-time, in order to error for
FOO
but notBAR
.So with the rules inferred above, we could desugar the two constants as follows:
The distinction between the
tmp
local slot and theTMP
static slot, and the lack of a drop for the latter, is what MIR is missing currently.Proposed solution
@nikomatsakis and I have mulled this over, and the resulting plan is roughly as follows:
&f(&g())
different scopes (with the inner one living only for the duration of the outer call), with the outermost scope of a constant initializer being special: no destructors run, and its lifetime is'static
const fn
uses, e.g.id(&0)
(recovered through rvalue promotion)'static
scopes, MIR building would use a different kind of "slot" and not emit a dropLocal
toSlot
'static
"slots" for all borrows, e.g.:'static
slot that was borrowed would overlap with the'static
borrow'static
slots to "escape" the constant initializer evaluation'static
slot:const S: &'static str = &X.to_string();
The text was updated successfully, but these errors were encountered: