-
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
Constant operands are dropped in an unusual order #90762
Comments
To be clear, the 'evaluation' of the |
FWIW I would have expected the order to be consistent with calling a function that returns the struct Print(&'static str);
impl Drop for Print {
fn drop(&mut self) {
println!("{}", self.0);
}
}
fn a() -> Print { Print("a") }
fn b() -> Print { Print("b") }
fn main() {
loop {
std::mem::forget(({a()}, b(), Print("c"), break));
}
} this prints
Which is right-to-left, so "last variable dropped first", which I guess makes sense. Cc @rust-lang/wg-const-eval, though this is more about MIR generation that const evaluation (but not sure whom to ping for that). |
hmm... this is a weird situation, but I agree that the behaviour is wrong and should be like with the function calls. The main problem is that the tuple's MIR would be |
So there is some pre-drop-elaboration pass which assumes that |
The general assumption is that On the other hand, a lot of MIR and codegen would get more complex if we didn't have constants in operands as we'd end up with lots and lots of short lived locals |
And this is true once we are done generating the MIR. But before drop elaboration, MIR is not done building yet. Things can have 'side-effects' in the sense of affecting how the final (post-drop-elab) MIR will look. So many of the assumptions one might make about MIR simply do not hold. |
Yea that makes sense. So there are four ways forward:
|
There might be a room for some middle ground solution, where temporaries are introduced only if a type actually needs to be dropped. Constants that need to be dropped are rather uncommon. |
That sounds like the proper solution to me? In fact this is required anyway in case any of these operands is a function call that might not return. So I am probably misunderstanding what you mean by "operand" here -- are you using this as a surface Rust term or as a MIR term? In MIR there are no diverging operands though... confused |
it's the same solution as the locals solution, just requiring us to have imaginary locals and figuring it all out in separate logic. MIR can have diverging operands by having an uninhabited local and using that as in an |
Okay so it's not the operand that is diverging, but the code that would initialize the local diverges. |
For example:
The text was updated successfully, but these errors were encountered: