-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #107251 - dingxiangfei2009:let-chain-rescope, r=jieyouxu
Rescope temp lifetime in if-let into IfElse with migration lint Tracking issue #124085 This PR shortens the temporary lifetime to cover only the pattern matching and consequent branch of a `if let`. At the expression location, means that the lifetime is shortened from previously the deepest enclosing block or statement in Edition 2021. This warrants an Edition change. Coming with the Edition change, this patch also implements an edition lint to warn about the change and a safe rewrite suggestion to preserve the 2021 semantics in most cases. Related to #103108. Related crater runs: #129466.
Showing
29 changed files
with
1,393 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
//@ run-pass | ||
//@ edition:2024 | ||
//@ compile-flags: -Z validate-mir -Zunstable-options | ||
|
||
#![feature(let_chains)] | ||
#![feature(if_let_rescope)] | ||
|
||
use std::cell::RefCell; | ||
use std::convert::TryInto; | ||
|
||
#[derive(Default)] | ||
struct DropOrderCollector(RefCell<Vec<u32>>); | ||
|
||
struct LoudDrop<'a>(&'a DropOrderCollector, u32); | ||
|
||
impl Drop for LoudDrop<'_> { | ||
fn drop(&mut self) { | ||
println!("{}", self.1); | ||
self.0.0.borrow_mut().push(self.1); | ||
} | ||
} | ||
|
||
impl DropOrderCollector { | ||
fn option_loud_drop(&self, n: u32) -> Option<LoudDrop> { | ||
Some(LoudDrop(self, n)) | ||
} | ||
|
||
fn print(&self, n: u32) { | ||
println!("{}", n); | ||
self.0.borrow_mut().push(n) | ||
} | ||
|
||
fn assert_sorted(self) { | ||
assert!( | ||
self.0 | ||
.into_inner() | ||
.into_iter() | ||
.enumerate() | ||
.all(|(idx, item)| idx + 1 == item.try_into().unwrap()) | ||
); | ||
} | ||
|
||
fn if_let(&self) { | ||
if let None = self.option_loud_drop(1) { | ||
unreachable!(); | ||
} else { | ||
self.print(2); | ||
} | ||
|
||
if let Some(_) = self.option_loud_drop(4) { | ||
self.print(3); | ||
} | ||
|
||
if let Some(_d) = self.option_loud_drop(6) { | ||
self.print(5); | ||
} | ||
} | ||
|
||
fn let_chain(&self) { | ||
// take the "then" branch | ||
if self.option_loud_drop(1).is_some() // 1 | ||
&& self.option_loud_drop(2).is_some() // 2 | ||
&& let Some(_d) = self.option_loud_drop(4) | ||
// 4 | ||
{ | ||
self.print(3); // 3 | ||
} | ||
|
||
// take the "else" branch | ||
if self.option_loud_drop(5).is_some() // 1 | ||
&& self.option_loud_drop(6).is_some() // 2 | ||
&& 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 | ||
{ | ||
self.print(16); // 3 | ||
} | ||
|
||
// let exprs last | ||
if self.option_loud_drop(19).is_some() // 1 | ||
&& self.option_loud_drop(20).is_some() // 2 | ||
&& let Some(_d) = self.option_loud_drop(23) // 5 | ||
&& let Some(_e) = self.option_loud_drop(22) | ||
// 4 | ||
{ | ||
self.print(21); // 3 | ||
} | ||
} | ||
} | ||
|
||
fn main() { | ||
println!("-- if let --"); | ||
let collector = DropOrderCollector::default(); | ||
collector.if_let(); | ||
collector.assert_sorted(); | ||
|
||
println!("-- let chain --"); | ||
let collector = DropOrderCollector::default(); | ||
collector.let_chain(); | ||
collector.assert_sorted(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
//@ edition: 2024 | ||
//@ compile-flags: -Z validate-mir -Zunstable-options | ||
|
||
#![feature(if_let_rescope)] | ||
#![deny(if_let_rescope)] | ||
|
||
struct Droppy; | ||
impl Drop for Droppy { | ||
fn drop(&mut self) { | ||
println!("dropped"); | ||
} | ||
} | ||
impl Droppy { | ||
fn get_ref(&self) -> Option<&u8> { | ||
None | ||
} | ||
} | ||
|
||
fn do_something<T>(_: &T) {} | ||
|
||
fn main() { | ||
do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); | ||
//~^ ERROR: temporary value dropped while borrowed | ||
do_something(if let Some(value) = Droppy.get_ref() { | ||
//~^ ERROR: temporary value dropped while borrowed | ||
value | ||
} else if let Some(value) = Droppy.get_ref() { | ||
//~^ ERROR: temporary value dropped while borrowed | ||
value | ||
} else { | ||
&0 | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
error[E0716]: temporary value dropped while borrowed | ||
--> $DIR/if-let-rescope-borrowck-suggestions.rs:22:39 | ||
| | ||
LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); | ||
| ^^^^^^ - temporary value is freed at the end of this statement | ||
| | | ||
| creates a temporary value which is freed while still in use | ||
| | ||
note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead | ||
--> $DIR/if-let-rescope-borrowck-suggestions.rs:22:64 | ||
| | ||
LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); | ||
| ^ | ||
help: consider using a `let` binding to create a longer lived value | ||
| | ||
LL ~ let binding = Droppy; | ||
LL ~ do_something(if let Some(value) = binding.get_ref() { value } else { &0 }); | ||
| | ||
help: consider rewriting the `if` into `match` which preserves the extended lifetime | ||
| | ||
LL | do_something({ match Droppy.get_ref() { Some(value) => { value } _ => { &0 }}}); | ||
| ~~~~~~~ ++++++++++++++++ ~~~~ ++ | ||
|
||
error[E0716]: temporary value dropped while borrowed | ||
--> $DIR/if-let-rescope-borrowck-suggestions.rs:24:39 | ||
| | ||
LL | do_something(if let Some(value) = Droppy.get_ref() { | ||
| ^^^^^^ creates a temporary value which is freed while still in use | ||
... | ||
LL | } else if let Some(value) = Droppy.get_ref() { | ||
| - temporary value is freed at the end of this statement | ||
| | ||
note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead | ||
--> $DIR/if-let-rescope-borrowck-suggestions.rs:27:5 | ||
| | ||
LL | } else if let Some(value) = Droppy.get_ref() { | ||
| ^ | ||
help: consider using a `let` binding to create a longer lived value | ||
| | ||
LL ~ let binding = Droppy; | ||
LL ~ do_something(if let Some(value) = binding.get_ref() { | ||
| | ||
help: consider rewriting the `if` into `match` which preserves the extended lifetime | ||
| | ||
LL ~ do_something({ match Droppy.get_ref() { Some(value) => { | ||
LL | | ||
LL | value | ||
LL ~ } _ => if let Some(value) = Droppy.get_ref() { | ||
LL | | ||
... | ||
LL | &0 | ||
LL ~ }}}); | ||
| | ||
|
||
error[E0716]: temporary value dropped while borrowed | ||
--> $DIR/if-let-rescope-borrowck-suggestions.rs:27:33 | ||
| | ||
LL | } else if let Some(value) = Droppy.get_ref() { | ||
| ^^^^^^ creates a temporary value which is freed while still in use | ||
... | ||
LL | } else { | ||
| - temporary value is freed at the end of this statement | ||
| | ||
note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead | ||
--> $DIR/if-let-rescope-borrowck-suggestions.rs:30:5 | ||
| | ||
LL | } else { | ||
| ^ | ||
help: consider using a `let` binding to create a longer lived value | ||
| | ||
LL ~ let binding = Droppy; | ||
LL ~ do_something(if let Some(value) = Droppy.get_ref() { | ||
LL | | ||
LL | value | ||
LL ~ } else if let Some(value) = binding.get_ref() { | ||
| | ||
help: consider rewriting the `if` into `match` which preserves the extended lifetime | ||
| | ||
LL ~ } else { match Droppy.get_ref() { Some(value) => { | ||
LL | | ||
LL | value | ||
LL ~ } _ => { | ||
LL | &0 | ||
LL ~ }}}); | ||
| | ||
|
||
error: aborting due to 3 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0716`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// This test checks that the lint `if_let_rescope` only actions | ||
// when the feature gate is enabled. | ||
// Edition 2021 is used here because the lint should work especially | ||
// when edition migration towards 2024 is run. | ||
|
||
//@ revisions: with_feature_gate without_feature_gate | ||
//@ [without_feature_gate] check-pass | ||
//@ edition: 2021 | ||
|
||
#![cfg_attr(with_feature_gate, feature(if_let_rescope))] | ||
#![deny(if_let_rescope)] | ||
#![allow(irrefutable_let_patterns)] | ||
|
||
struct Droppy; | ||
impl Drop for Droppy { | ||
fn drop(&mut self) { | ||
println!("dropped"); | ||
} | ||
} | ||
impl Droppy { | ||
fn get(&self) -> Option<u8> { | ||
None | ||
} | ||
} | ||
|
||
fn main() { | ||
if let Some(_value) = Droppy.get() { | ||
//[with_feature_gate]~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 | ||
//[with_feature_gate]~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
//[with_feature_gate]~| WARN: this changes meaning in Rust 2024 | ||
} else { | ||
//[with_feature_gate]~^ HELP: the value is now dropped here in Edition 2024 | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
error: `if let` assigns a shorter lifetime since Edition 2024 | ||
--> $DIR/lint-if-let-rescope-gated.rs:27:8 | ||
| | ||
LL | if let Some(_value) = Droppy.get() { | ||
| ^^^^^^^^^^^^^^^^^^^------^^^^^^ | ||
| | | ||
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion | ||
| | ||
= warning: this changes meaning in Rust 2024 | ||
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> | ||
help: the value is now dropped here in Edition 2024 | ||
--> $DIR/lint-if-let-rescope-gated.rs:31:5 | ||
| | ||
LL | } else { | ||
| ^ | ||
note: the lint level is defined here | ||
--> $DIR/lint-if-let-rescope-gated.rs:11:9 | ||
| | ||
LL | #![deny(if_let_rescope)] | ||
| ^^^^^^^^^^^^^^ | ||
help: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
| | ||
LL ~ match Droppy.get() { Some(_value) => { | ||
LL | | ||
LL | | ||
LL | | ||
LL ~ } _ => { | ||
LL | | ||
LL ~ }} | ||
| | ||
|
||
error: aborting due to 1 previous error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// This test ensures that no suggestion is emitted if the span originates from | ||
// an expansion that is probably not under a user's control. | ||
|
||
//@ edition:2021 | ||
//@ compile-flags: -Z unstable-options | ||
|
||
#![feature(if_let_rescope)] | ||
#![deny(if_let_rescope)] | ||
#![allow(irrefutable_let_patterns)] | ||
|
||
macro_rules! edition_2021_if_let { | ||
($p:pat, $e:expr, { $($conseq:tt)* } { $($alt:tt)* }) => { | ||
if let $p = $e { $($conseq)* } else { $($alt)* } | ||
//~^ ERROR `if let` assigns a shorter lifetime since Edition 2024 | ||
//~| WARN this changes meaning in Rust 2024 | ||
} | ||
} | ||
|
||
fn droppy() -> Droppy { | ||
Droppy | ||
} | ||
struct Droppy; | ||
impl Drop for Droppy { | ||
fn drop(&mut self) { | ||
println!("dropped"); | ||
} | ||
} | ||
impl Droppy { | ||
fn get(&self) -> Option<u8> { | ||
None | ||
} | ||
} | ||
|
||
fn main() { | ||
edition_2021_if_let! { | ||
Some(_value), | ||
droppy().get(), | ||
{} | ||
{} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
error: `if let` assigns a shorter lifetime since Edition 2024 | ||
--> $DIR/lint-if-let-rescope-with-macro.rs:13:12 | ||
| | ||
LL | if let $p = $e { $($conseq)* } else { $($alt)* } | ||
| ^^^ | ||
... | ||
LL | / edition_2021_if_let! { | ||
LL | | Some(_value), | ||
LL | | droppy().get(), | ||
| | -------- this value has a significant drop implementation which may observe a major change in drop order and requires your discretion | ||
LL | | {} | ||
LL | | {} | ||
LL | | }; | ||
| |_____- in this macro invocation | ||
| | ||
= warning: this changes meaning in Rust 2024 | ||
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> | ||
help: the value is now dropped here in Edition 2024 | ||
--> $DIR/lint-if-let-rescope-with-macro.rs:13:38 | ||
| | ||
LL | if let $p = $e { $($conseq)* } else { $($alt)* } | ||
| ^ | ||
... | ||
LL | / edition_2021_if_let! { | ||
LL | | Some(_value), | ||
LL | | droppy().get(), | ||
LL | | {} | ||
LL | | {} | ||
LL | | }; | ||
| |_____- in this macro invocation | ||
note: the lint level is defined here | ||
--> $DIR/lint-if-let-rescope-with-macro.rs:8:9 | ||
| | ||
LL | #![deny(if_let_rescope)] | ||
| ^^^^^^^^^^^^^^ | ||
= note: this error originates in the macro `edition_2021_if_let` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error: aborting due to 1 previous error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
//@ run-rustfix | ||
|
||
#![deny(if_let_rescope)] | ||
#![feature(if_let_rescope)] | ||
#![allow(irrefutable_let_patterns)] | ||
|
||
fn droppy() -> Droppy { | ||
Droppy | ||
} | ||
struct Droppy; | ||
impl Drop for Droppy { | ||
fn drop(&mut self) { | ||
println!("dropped"); | ||
} | ||
} | ||
impl Droppy { | ||
fn get(&self) -> Option<u8> { | ||
None | ||
} | ||
} | ||
|
||
fn main() { | ||
if let Some(_value) = droppy().get() { | ||
// Should not lint | ||
} | ||
|
||
match droppy().get() { Some(_value) => { | ||
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 | ||
//~| WARN: this changes meaning in Rust 2024 | ||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
// do something | ||
} _ => { | ||
//~^ HELP: the value is now dropped here in Edition 2024 | ||
// do something else | ||
}} | ||
|
||
match droppy().get() { Some(_value) => { | ||
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 | ||
//~| WARN: this changes meaning in Rust 2024 | ||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
// do something | ||
} _ => { match droppy().get() { Some(_value) => { | ||
//~^ HELP: the value is now dropped here in Edition 2024 | ||
// do something else | ||
} _ => {}}}} | ||
//~^ HELP: the value is now dropped here in Edition 2024 | ||
|
||
if droppy().get().is_some() { | ||
// Should not lint | ||
} else { match droppy().get() { Some(_value) => { | ||
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 | ||
//~| WARN: this changes meaning in Rust 2024 | ||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
} _ => if droppy().get().is_none() { | ||
//~^ HELP: the value is now dropped here in Edition 2024 | ||
}}} | ||
|
||
if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { | ||
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 | ||
//~| WARN: this changes meaning in Rust 2024 | ||
//~| HELP: the value is now dropped here in Edition 2024 | ||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
} | ||
|
||
if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } { | ||
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 | ||
//~| WARN: this changes meaning in Rust 2024 | ||
//~| HELP: the value is now dropped here in Edition 2024 | ||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
//@ run-rustfix | ||
|
||
#![deny(if_let_rescope)] | ||
#![feature(if_let_rescope)] | ||
#![allow(irrefutable_let_patterns)] | ||
|
||
fn droppy() -> Droppy { | ||
Droppy | ||
} | ||
struct Droppy; | ||
impl Drop for Droppy { | ||
fn drop(&mut self) { | ||
println!("dropped"); | ||
} | ||
} | ||
impl Droppy { | ||
fn get(&self) -> Option<u8> { | ||
None | ||
} | ||
} | ||
|
||
fn main() { | ||
if let Some(_value) = droppy().get() { | ||
// Should not lint | ||
} | ||
|
||
if let Some(_value) = droppy().get() { | ||
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 | ||
//~| WARN: this changes meaning in Rust 2024 | ||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
// do something | ||
} else { | ||
//~^ HELP: the value is now dropped here in Edition 2024 | ||
// do something else | ||
} | ||
|
||
if let Some(_value) = droppy().get() { | ||
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 | ||
//~| WARN: this changes meaning in Rust 2024 | ||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
// do something | ||
} else if let Some(_value) = droppy().get() { | ||
//~^ HELP: the value is now dropped here in Edition 2024 | ||
// do something else | ||
} | ||
//~^ HELP: the value is now dropped here in Edition 2024 | ||
|
||
if droppy().get().is_some() { | ||
// Should not lint | ||
} else if let Some(_value) = droppy().get() { | ||
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 | ||
//~| WARN: this changes meaning in Rust 2024 | ||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
} else if droppy().get().is_none() { | ||
//~^ HELP: the value is now dropped here in Edition 2024 | ||
} | ||
|
||
if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { | ||
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 | ||
//~| WARN: this changes meaning in Rust 2024 | ||
//~| HELP: the value is now dropped here in Edition 2024 | ||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
} | ||
|
||
if let () = { if let Some(_value) = Droppy.get() {} } { | ||
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 | ||
//~| WARN: this changes meaning in Rust 2024 | ||
//~| HELP: the value is now dropped here in Edition 2024 | ||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
error: `if let` assigns a shorter lifetime since Edition 2024 | ||
--> $DIR/lint-if-let-rescope.rs:27:8 | ||
| | ||
LL | if let Some(_value) = droppy().get() { | ||
| ^^^^^^^^^^^^^^^^^^^--------^^^^^^ | ||
| | | ||
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion | ||
| | ||
= warning: this changes meaning in Rust 2024 | ||
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> | ||
help: the value is now dropped here in Edition 2024 | ||
--> $DIR/lint-if-let-rescope.rs:32:5 | ||
| | ||
LL | } else { | ||
| ^ | ||
note: the lint level is defined here | ||
--> $DIR/lint-if-let-rescope.rs:3:9 | ||
| | ||
LL | #![deny(if_let_rescope)] | ||
| ^^^^^^^^^^^^^^ | ||
help: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
| | ||
LL ~ match droppy().get() { Some(_value) => { | ||
LL | | ||
... | ||
LL | // do something | ||
LL ~ } _ => { | ||
LL | | ||
LL | // do something else | ||
LL ~ }} | ||
| | ||
|
||
error: `if let` assigns a shorter lifetime since Edition 2024 | ||
--> $DIR/lint-if-let-rescope.rs:37:8 | ||
| | ||
LL | if let Some(_value) = droppy().get() { | ||
| ^^^^^^^^^^^^^^^^^^^--------^^^^^^ | ||
| | | ||
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion | ||
... | ||
LL | } else if let Some(_value) = droppy().get() { | ||
| -------- this value has a significant drop implementation which may observe a major change in drop order and requires your discretion | ||
| | ||
= warning: this changes meaning in Rust 2024 | ||
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> | ||
help: the value is now dropped here in Edition 2024 | ||
--> $DIR/lint-if-let-rescope.rs:42:5 | ||
| | ||
LL | } else if let Some(_value) = droppy().get() { | ||
| ^ | ||
help: the value is now dropped here in Edition 2024 | ||
--> $DIR/lint-if-let-rescope.rs:45:5 | ||
| | ||
LL | } | ||
| ^ | ||
help: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
| | ||
LL ~ match droppy().get() { Some(_value) => { | ||
LL | | ||
... | ||
LL | // do something | ||
LL ~ } _ => { match droppy().get() { Some(_value) => { | ||
LL | | ||
LL | // do something else | ||
LL ~ } _ => {}}}} | ||
| | ||
|
||
error: `if let` assigns a shorter lifetime since Edition 2024 | ||
--> $DIR/lint-if-let-rescope.rs:50:15 | ||
| | ||
LL | } else if let Some(_value) = droppy().get() { | ||
| ^^^^^^^^^^^^^^^^^^^--------^^^^^^ | ||
| | | ||
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion | ||
| | ||
= warning: this changes meaning in Rust 2024 | ||
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> | ||
help: the value is now dropped here in Edition 2024 | ||
--> $DIR/lint-if-let-rescope.rs:54:5 | ||
| | ||
LL | } else if droppy().get().is_none() { | ||
| ^ | ||
help: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
| | ||
LL ~ } else { match droppy().get() { Some(_value) => { | ||
LL | | ||
LL | | ||
LL | | ||
LL ~ } _ => if droppy().get().is_none() { | ||
LL | | ||
LL ~ }}} | ||
| | ||
|
||
error: `if let` assigns a shorter lifetime since Edition 2024 | ||
--> $DIR/lint-if-let-rescope.rs:58:27 | ||
| | ||
LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { | ||
| ^^^^^^^^^^^^^^^^^^^------^^^^^^ | ||
| | | ||
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion | ||
| | ||
= warning: this changes meaning in Rust 2024 | ||
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> | ||
help: the value is now dropped here in Edition 2024 | ||
--> $DIR/lint-if-let-rescope.rs:58:69 | ||
| | ||
LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { | ||
| ^ | ||
help: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
| | ||
LL | if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { | ||
| ~~~~~ +++++++++++++++++ ~~~~ + | ||
|
||
error: `if let` assigns a shorter lifetime since Edition 2024 | ||
--> $DIR/lint-if-let-rescope.rs:65:22 | ||
| | ||
LL | if let () = { if let Some(_value) = Droppy.get() {} } { | ||
| ^^^^^^^^^^^^^^^^^^^------^^^^^^ | ||
| | | ||
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion | ||
| | ||
= warning: this changes meaning in Rust 2024 | ||
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> | ||
help: the value is now dropped here in Edition 2024 | ||
--> $DIR/lint-if-let-rescope.rs:65:55 | ||
| | ||
LL | if let () = { if let Some(_value) = Droppy.get() {} } { | ||
| ^ | ||
help: a `match` with a single arm can preserve the drop order up to Edition 2021 | ||
| | ||
LL | if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } { | ||
| ~~~~~ +++++++++++++++++ ++++++++ | ||
|
||
error: aborting due to 5 previous errors | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// This test shows the code that could have been accepted by enabling #![feature(if_let_rescope)] | ||
|
||
struct A; | ||
struct B<'a, T>(&'a mut T); | ||
|
||
impl A { | ||
fn f(&mut self) -> Option<B<'_, Self>> { | ||
Some(B(self)) | ||
} | ||
} | ||
|
||
impl<'a, T> Drop for B<'a, T> { | ||
fn drop(&mut self) { | ||
// this is needed to keep NLL's hands off and to ensure | ||
// the inner mutable borrow stays alive | ||
} | ||
} | ||
|
||
fn main() { | ||
let mut a = A; | ||
if let None = a.f().as_ref() { | ||
unreachable!() | ||
} else { | ||
a.f().unwrap(); | ||
//~^ ERROR cannot borrow `a` as mutable more than once at a time | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
error[E0499]: cannot borrow `a` as mutable more than once at a time | ||
--> $DIR/feature-gate-if-let-rescope.rs:24:9 | ||
| | ||
LL | if let None = a.f().as_ref() { | ||
| ----- | ||
| | | ||
| first mutable borrow occurs here | ||
| a temporary with access to the first borrow is created here ... | ||
... | ||
LL | a.f().unwrap(); | ||
| ^ second mutable borrow occurs here | ||
LL | | ||
LL | }; | ||
| - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option<B<'_, A>>` | ||
|
||
error: aborting due to 1 previous error | ||
|
||
For more information about this error, try `rustc --explain E0499`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
tests/ui/nll/issue-54556-niconii.stderr → ...ll/issue-54556-niconii.edition2021.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters