Rollup merge of #131984 - dingxiangfei2009:stabilize-if-let-rescope, r=traviscross,lcnr

Stabilize if_let_rescope

Close #131154
Tracked by #124085
This commit is contained in:
Matthias Krüger 2024-10-29 18:38:57 +01:00 committed by GitHub
commit 5d6c49938e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 30 additions and 84 deletions

View File

@ -224,6 +224,8 @@ declare_features! (
(accepted, i128_type, "1.26.0", Some(35118)), (accepted, i128_type, "1.26.0", Some(35118)),
/// Allows the use of `if let` expressions. /// Allows the use of `if let` expressions.
(accepted, if_let, "1.0.0", None), (accepted, if_let, "1.0.0", None),
/// Rescoping temporaries in `if let` to align with Rust 2024.
(accepted, if_let_rescope, "CURRENT_RUSTC_VERSION", Some(124085)),
/// Allows top level or-patterns (`p | q`) in `if let` and `while let`. /// Allows top level or-patterns (`p | q`) in `if let` and `while let`.
(accepted, if_while_or_patterns, "1.33.0", Some(48215)), (accepted, if_while_or_patterns, "1.33.0", Some(48215)),
/// Allows lifetime elision in `impl` headers. For example: /// Allows lifetime elision in `impl` headers. For example:

View File

@ -505,8 +505,6 @@ declare_features! (
(unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)), (unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)),
/// Allows `if let` guard in match arms. /// Allows `if let` guard in match arms.
(unstable, if_let_guard, "1.47.0", Some(51114)), (unstable, if_let_guard, "1.47.0", Some(51114)),
/// Rescoping temporaries in `if let` to align with Rust 2024.
(unstable, if_let_rescope, "1.83.0", Some(124085)),
/// Allows `impl Trait` to be used inside associated types (RFC 2515). /// Allows `impl Trait` to be used inside associated types (RFC 2515).
(unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)), (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)),
/// Allows `impl Trait` as output type in `Fn` traits in return position of functions. /// Allows `impl Trait` as output type in `Fn` traits in return position of functions.

View File

@ -464,8 +464,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
hir::ExprKind::If(cond, then, Some(otherwise)) => { hir::ExprKind::If(cond, then, Some(otherwise)) => {
let expr_cx = visitor.cx; let expr_cx = visitor.cx;
let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope() let data = if expr.span.at_least_rust_2024() {
{
ScopeData::IfThenRescope ScopeData::IfThenRescope
} else { } else {
ScopeData::IfThen ScopeData::IfThen
@ -480,8 +479,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
hir::ExprKind::If(cond, then, None) => { hir::ExprKind::If(cond, then, None) => {
let expr_cx = visitor.cx; let expr_cx = visitor.cx;
let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope() let data = if expr.span.at_least_rust_2024() {
{
ScopeData::IfThenRescope ScopeData::IfThenRescope
} else { } else {
ScopeData::IfThen ScopeData::IfThen

View File

@ -24,7 +24,6 @@ declare_lint! {
/// ### Example /// ### Example
/// ///
/// ```rust,edition2021 /// ```rust,edition2021
/// #![feature(if_let_rescope)]
/// #![warn(if_let_rescope)] /// #![warn(if_let_rescope)]
/// #![allow(unused_variables)] /// #![allow(unused_variables)]
/// ///
@ -243,7 +242,7 @@ impl_lint_pass!(
impl<'tcx> LateLintPass<'tcx> for IfLetRescope { impl<'tcx> LateLintPass<'tcx> for IfLetRescope {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
if expr.span.edition().at_least_rust_2024() || !cx.tcx.features().if_let_rescope() { if expr.span.edition().at_least_rust_2024() {
return; return;
} }
if let (Level::Allow, _) = cx.tcx.lint_level_at_node(IF_LET_RESCOPE, expr.hir_id) { if let (Level::Allow, _) = cx.tcx.lint_level_at_node(IF_LET_RESCOPE, expr.hir_id) {

View File

@ -784,7 +784,7 @@ impl<'tcx> Cx<'tcx> {
if_then_scope: region::Scope { if_then_scope: region::Scope {
id: then.hir_id.local_id, id: then.hir_id.local_id,
data: { data: {
if expr.span.at_least_rust_2024() && tcx.features().if_let_rescope() { if expr.span.at_least_rust_2024() {
region::ScopeData::IfThenRescope region::ScopeData::IfThenRescope
} else { } else {
region::ScopeData::IfThen region::ScopeData::IfThen

View File

@ -4,8 +4,8 @@
//@ [edition2021] edition: 2021 //@ [edition2021] edition: 2021
//@ [edition2024] compile-flags: -Z unstable-options //@ [edition2024] compile-flags: -Z unstable-options
//@ [edition2024] edition: 2024 //@ [edition2024] edition: 2024
#![feature(let_chains)] #![feature(let_chains)]
#![cfg_attr(edition2024, feature(if_let_rescope))]
use std::cell::RefCell; use std::cell::RefCell;
use std::convert::TryInto; use std::convert::TryInto;

View File

@ -3,7 +3,6 @@
//@ compile-flags: -Z validate-mir -Zunstable-options //@ compile-flags: -Z validate-mir -Zunstable-options
#![feature(let_chains)] #![feature(let_chains)]
#![feature(if_let_rescope)]
use std::cell::RefCell; use std::cell::RefCell;
use std::convert::TryInto; use std::convert::TryInto;

View File

@ -1,7 +1,6 @@
//@ edition: 2024 //@ edition: 2024
//@ compile-flags: -Z validate-mir -Zunstable-options //@ compile-flags: -Z validate-mir -Zunstable-options
#![feature(if_let_rescope)]
#![deny(if_let_rescope)] #![deny(if_let_rescope)]
struct Droppy; struct Droppy;

View File

@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed error[E0716]: temporary value dropped while borrowed
--> $DIR/if-let-rescope-borrowck-suggestions.rs:22:39 --> $DIR/if-let-rescope-borrowck-suggestions.rs:21:39
| |
LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 });
| ^^^^^^ - temporary value is freed at the end of this statement | ^^^^^^ - temporary value is freed at the end of this statement
@ -7,7 +7,7 @@ LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0
| creates a temporary value which is freed while still in use | 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 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 --> $DIR/if-let-rescope-borrowck-suggestions.rs:21:64
| |
LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 });
| ^ | ^
@ -22,7 +22,7 @@ LL | do_something({ match Droppy.get_ref() { Some(value) => { value } _ =>
| ~~~~~~~ ++++++++++++++++ ~~~~ ++ | ~~~~~~~ ++++++++++++++++ ~~~~ ++
error[E0716]: temporary value dropped while borrowed error[E0716]: temporary value dropped while borrowed
--> $DIR/if-let-rescope-borrowck-suggestions.rs:24:39 --> $DIR/if-let-rescope-borrowck-suggestions.rs:23:39
| |
LL | do_something(if let Some(value) = Droppy.get_ref() { LL | do_something(if let Some(value) = Droppy.get_ref() {
| ^^^^^^ creates a temporary value which is freed while still in use | ^^^^^^ creates a temporary value which is freed while still in use
@ -31,7 +31,7 @@ LL | } else if let Some(value) = Droppy.get_ref() {
| - temporary value is freed at the end of this statement | - 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 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 --> $DIR/if-let-rescope-borrowck-suggestions.rs:26:5
| |
LL | } else if let Some(value) = Droppy.get_ref() { LL | } else if let Some(value) = Droppy.get_ref() {
| ^ | ^
@ -53,7 +53,7 @@ LL ~ }}});
| |
error[E0716]: temporary value dropped while borrowed error[E0716]: temporary value dropped while borrowed
--> $DIR/if-let-rescope-borrowck-suggestions.rs:27:33 --> $DIR/if-let-rescope-borrowck-suggestions.rs:26:33
| |
LL | } else if let Some(value) = Droppy.get_ref() { LL | } else if let Some(value) = Droppy.get_ref() {
| ^^^^^^ creates a temporary value which is freed while still in use | ^^^^^^ creates a temporary value which is freed while still in use
@ -62,7 +62,7 @@ LL | } else {
| - temporary value is freed at the end of this statement | - 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 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 --> $DIR/if-let-rescope-borrowck-suggestions.rs:29:5
| |
LL | } else { LL | } else {
| ^ | ^

View File

@ -1,13 +1,13 @@
// This test checks that the lint `if_let_rescope` only actions // This test checks that the lint `if_let_rescope` only actions
// when the feature gate is enabled. // when Edition 2021 or prior is targeted here because the lint should work especially
// Edition 2021 is used here because the lint should work especially // when edition migration towards 2024 is executed.
// when edition migration towards 2024 is run.
//@ revisions: with_feature_gate without_feature_gate //@ revisions: edition2021 edition2024
//@ [without_feature_gate] check-pass //@ [edition2021] edition: 2021
//@ edition: 2021 //@ [edition2024] edition: 2024
//@ [edition2024] compile-flags: -Zunstable-options
//@ [edition2024] check-pass
#![cfg_attr(with_feature_gate, feature(if_let_rescope))]
#![deny(if_let_rescope)] #![deny(if_let_rescope)]
#![allow(irrefutable_let_patterns)] #![allow(irrefutable_let_patterns)]
@ -25,10 +25,10 @@ impl Droppy {
fn main() { fn main() {
if let Some(_value) = Droppy.get() { if let Some(_value) = Droppy.get() {
//[with_feature_gate]~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //[edition2021]~^ 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 //[edition2021]~| 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 //[edition2021]~| WARN: this changes meaning in Rust 2024
} else { } else {
//[with_feature_gate]~^ HELP: the value is now dropped here in Edition 2024 //[edition2021]~^ HELP: the value is now dropped here in Edition 2024
} }
} }

View File

@ -4,7 +4,6 @@
//@ edition:2021 //@ edition:2021
//@ compile-flags: -Z unstable-options //@ compile-flags: -Z unstable-options
#![feature(if_let_rescope)]
#![deny(if_let_rescope)] #![deny(if_let_rescope)]
#![allow(irrefutable_let_patterns)] #![allow(irrefutable_let_patterns)]

View File

@ -1,5 +1,5 @@
error: `if let` assigns a shorter lifetime since Edition 2024 error: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/lint-if-let-rescope-with-macro.rs:13:12 --> $DIR/lint-if-let-rescope-with-macro.rs:12:12
| |
LL | if let $p = $e { $($conseq)* } else { $($alt)* } LL | if let $p = $e { $($conseq)* } else { $($alt)* }
| ^^^ | ^^^
@ -16,7 +16,7 @@ LL | | };
= warning: this changes meaning in Rust 2024 = warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> = 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 help: the value is now dropped here in Edition 2024
--> $DIR/lint-if-let-rescope-with-macro.rs:13:38 --> $DIR/lint-if-let-rescope-with-macro.rs:12:38
| |
LL | if let $p = $e { $($conseq)* } else { $($alt)* } LL | if let $p = $e { $($conseq)* } else { $($alt)* }
| ^ | ^
@ -29,7 +29,7 @@ LL | | {}
LL | | }; LL | | };
| |_____- in this macro invocation | |_____- in this macro invocation
note: the lint level is defined here note: the lint level is defined here
--> $DIR/lint-if-let-rescope-with-macro.rs:8:9 --> $DIR/lint-if-let-rescope-with-macro.rs:7:9
| |
LL | #![deny(if_let_rescope)] LL | #![deny(if_let_rescope)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^

View File

@ -1,7 +1,7 @@
//@ run-rustfix //@ run-rustfix
#![deny(if_let_rescope)] #![deny(if_let_rescope)]
#![feature(if_let_rescope, stmt_expr_attributes)] #![feature(stmt_expr_attributes)]
#![allow(irrefutable_let_patterns, unused_parens)] #![allow(irrefutable_let_patterns, unused_parens)]
fn droppy() -> Droppy { fn droppy() -> Droppy {

View File

@ -1,7 +1,7 @@
//@ run-rustfix //@ run-rustfix
#![deny(if_let_rescope)] #![deny(if_let_rescope)]
#![feature(if_let_rescope, stmt_expr_attributes)] #![feature(stmt_expr_attributes)]
#![allow(irrefutable_let_patterns, unused_parens)] #![allow(irrefutable_let_patterns, unused_parens)]
fn droppy() -> Droppy { fn droppy() -> Droppy {

View File

@ -1,27 +0,0 @@
// 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
};
}

View File

@ -1,18 +0,0 @@
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`.

View File

@ -8,7 +8,6 @@
// See `mir_drop_order.rs` for more information // See `mir_drop_order.rs` for more information
#![feature(let_chains)] #![feature(let_chains)]
#![cfg_attr(edition2024, feature(if_let_rescope))]
#![allow(irrefutable_let_patterns)] #![allow(irrefutable_let_patterns)]
use std::cell::RefCell; use std::cell::RefCell;

View File

@ -1,5 +1,5 @@
error[E0597]: `counter` does not live long enough error[E0597]: `counter` does not live long enough
--> $DIR/issue-54556-niconii.rs:30:20 --> $DIR/issue-54556-niconii.rs:28:20
| |
LL | let counter = Mutex; LL | let counter = Mutex;
| ------- binding `counter` declared here | ------- binding `counter` declared here

View File

@ -12,8 +12,6 @@
//@ [edition2024] compile-flags: -Z unstable-options //@ [edition2024] compile-flags: -Z unstable-options
//@ [edition2024] check-pass //@ [edition2024] check-pass
#![cfg_attr(edition2024, feature(if_let_rescope))]
struct Mutex; struct Mutex;
struct MutexGuard<'a>(&'a Mutex); struct MutexGuard<'a>(&'a Mutex);