stabilize if_let_rescope
This commit is contained in:
parent
be01dabfef
commit
6d569f769c
@ -224,6 +224,8 @@ macro_rules! 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:
|
||||||
|
@ -482,8 +482,6 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
|||||||
(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.
|
||||||
|
@ -466,8 +466,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
|
||||||
@ -482,8 +481,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
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
/// ### 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 @@ fn probe_if_cascade<'tcx>(&mut self, cx: &LateContext<'tcx>, mut expr: &'tcx hir
|
|||||||
|
|
||||||
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) {
|
||||||
|
@ -777,7 +777,7 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
| ^
|
| ^
|
||||||
|
@ -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 @@ fn get(&self) -> Option<u8> {
|
|||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)]
|
||||||
|
|
||||||
|
@ -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)]
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
|
||||||
};
|
|
||||||
}
|
|
@ -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`.
|
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user