-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Drop temporaries created in a condition, even if it's a let chain #102998
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
// run-pass | ||
nathanwhit marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// compile-flags: -Z validate-mir | ||
#![feature(let_chains)] | ||
|
||
use std::cell::RefCell; | ||
use std::convert::TryInto; | ||
|
@@ -116,6 +118,58 @@ impl DropOrderCollector { | |
} | ||
} | ||
|
||
fn let_chain(&self) { | ||
// take the "then" branch | ||
if self.option_loud_drop(2).is_some() // 2 | ||
&& self.option_loud_drop(1).is_some() // 1 | ||
&& let Some(_d) = self.option_loud_drop(4) { // 4 | ||
self.print(3); // 3 | ||
} | ||
|
||
// take the "else" branch | ||
if self.option_loud_drop(6).is_some() // 2 | ||
&& self.option_loud_drop(5).is_some() // 1 | ||
&& let None = self.option_loud_drop(7) { // 3 | ||
unreachable!(); | ||
} else { | ||
self.print(8); // 4 | ||
} | ||
|
||
// let exprs interspersed | ||
if self.option_loud_drop(9).is_some() // 1 | ||
&& let Some(_d) = self.option_loud_drop(13) // 5 | ||
&& self.option_loud_drop(10).is_some() // 2 | ||
&& let Some(_e) = self.option_loud_drop(12) { // 4 | ||
self.print(11); // 3 | ||
} | ||
|
||
// let exprs first | ||
if let Some(_d) = self.option_loud_drop(18) // 5 | ||
&& let Some(_e) = self.option_loud_drop(17) // 4 | ||
&& self.option_loud_drop(14).is_some() // 1 | ||
&& self.option_loud_drop(15).is_some() { // 2 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The drop order is a bit surprising. IIUC, we start by dropping the first regular conditions in reverse source order, then other regular conditions in forward source order, then the block, then the let conditions. Why the forward/reverse mix? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah that's definitely a quirk. It's pretty much because for that condition we go from an AST like // Fake notation - the numbers correspond to the argument to `option_loud_drop`
Binary(And, Binary(And, Binary(And, Let(18), Let(17)), MethodCall(14)), MethodCall(15) to hir like Binary(And, Binary(And, Binary(And, Let(18), Let(17)), DropTemps(MethodCall(14))), DropTemps(MethodCall(15))) Ideally we could group self.option_loud_drop(14).is_some() // 1
&& self.option_loud_drop(15).is_some() // 2 into the same If the regular conditions come first, like self.option_loud_drop(14).is_some()
&& self.option_loud_drop(15).is_some()
&& let Some(_d) = self.option_loud_drop(18)
&& let Some(_e) = self.option_loud_drop(17) we can (and do) wrap them in the same There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FTR there is also pretty weird behaviour for vanilla non-let if chains. Drop behaviour is currently like:
Same goes if you put the expression into a A bit unrelated: Generally I think that dropping the temporaries of the if let expression after the |
||
self.print(16); // 3 | ||
} | ||
|
||
// let exprs last | ||
if self.option_loud_drop(20).is_some() // 2 | ||
&& self.option_loud_drop(19).is_some() // 1 | ||
&& let Some(_d) = self.option_loud_drop(23) // 5 | ||
&& let Some(_e) = self.option_loud_drop(22) { // 4 | ||
self.print(21); // 3 | ||
} | ||
} | ||
|
||
fn while_(&self) { | ||
let mut v = self.option_loud_drop(4); | ||
while let Some(_d) = v | ||
&& self.option_loud_drop(1).is_some() | ||
&& self.option_loud_drop(2).is_some() { | ||
self.print(3); | ||
v = None; | ||
} | ||
} | ||
|
||
fn assert_sorted(self) { | ||
assert!( | ||
self.0 | ||
|
@@ -142,4 +196,14 @@ fn main() { | |
let collector = DropOrderCollector::default(); | ||
collector.match_(); | ||
collector.assert_sorted(); | ||
|
||
println!("-- let chain --"); | ||
let collector = DropOrderCollector::default(); | ||
collector.let_chain(); | ||
collector.assert_sorted(); | ||
|
||
println!("-- while --"); | ||
let collector = DropOrderCollector::default(); | ||
collector.while_(); | ||
collector.assert_sorted(); | ||
} |
Uh oh!
There was an error while loading. Please reload this page.