Remove let_chains feature

This commit is contained in:
Cameron Steffen 2025-06-29 13:06:21 -05:00
parent ed2d759783
commit dc9879cb3d
39 changed files with 1053 additions and 1194 deletions

View file

@ -469,7 +469,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
"`if let` guards are experimental",
"you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`"
);
gate_all!(let_chains, "`let` expressions in this position are unstable");
gate_all!(
async_trait_bounds,
"`async` trait bounds are unstable",

View file

@ -265,6 +265,8 @@ declare_features! (
(accepted, keylocker_x86, "CURRENT_RUSTC_VERSION", Some(134813)),
/// Allows `'a: { break 'a; }`.
(accepted, label_break_value, "1.65.0", Some(48594)),
/// Allows `if/while p && let q = r && ...` chains.
(accepted, let_chains, "1.88.0", Some(53667)),
/// Allows `let...else` statements.
(accepted, let_else, "1.65.0", Some(87335)),
/// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.

View file

@ -552,8 +552,6 @@ declare_features! (
(unstable, large_assignments, "1.52.0", Some(83518)),
/// Allow to have type alias types for inter-crate use.
(incomplete, lazy_type_alias, "1.72.0", Some(112792)),
/// Allows `if/while p && let q = r && ...` chains.
(unstable, let_chains, "1.37.0", Some(53667)),
/// Allows using `#[link(kind = "link-arg", name = "...")]`
/// to pass custom arguments to the linker.
(unstable, link_arg_attribute, "1.76.0", Some(99427)),

View file

@ -512,6 +512,8 @@ parse_leading_underscore_unicode_escape_label = invalid start of unicode escape
parse_left_arrow_operator = unexpected token: `<-`
.suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-`
parse_let_chain_pre_2024 = let chains are only allowed in Rust 2024 or later
parse_lifetime_after_mut = lifetime must precede `mut`
.suggestion = place the lifetime before `mut`

View file

@ -1778,6 +1778,13 @@ pub(crate) struct AsyncBoundModifierIn2015 {
pub help: HelpUseLatestEdition,
}
#[derive(Diagnostic)]
#[diag(parse_let_chain_pre_2024)]
pub(crate) struct LetChainPre2024 {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_self_argument_pointer)]
pub(crate) struct SelfArgumentPointer {

View file

@ -4117,7 +4117,7 @@ impl MutVisitor for CondChecker<'_> {
LetChainsPolicy::AlwaysAllowed => (),
LetChainsPolicy::EditionDependent { current_edition } => {
if !current_edition.at_least_rust_2024() || !span.at_least_rust_2024() {
self.parser.psess.gated_spans.gate(sym::let_chains, span);
self.parser.dcx().emit_err(errors::LetChainPre2024 { span });
}
}
}

View file

@ -1,3 +1,5 @@
// rustfmt-edition: 2024
fn main() {
if let x = x && x {}

View file

@ -1,3 +1,5 @@
// rustfmt-edition: 2024
fn main() {
if let x = x
&& x

View file

@ -1,5 +1,5 @@
LL| |#![feature(coverage_attribute, let_chains)]
LL| |//@ edition: 2021
LL| |#![feature(coverage_attribute)]
LL| |//@ edition: 2024
LL| |//@ compile-flags: -Zcoverage-options=branch
LL| |//@ llvm-cov-flags: --show-branches=count
LL| |

View file

@ -1,5 +1,5 @@
#![feature(coverage_attribute, let_chains)]
//@ edition: 2021
#![feature(coverage_attribute)]
//@ edition: 2024
//@ compile-flags: -Zcoverage-options=branch
//@ llvm-cov-flags: --show-branches=count

View file

@ -0,0 +1,145 @@
// See drop-order-comparisons.rs
//@ edition: 2024
//@ run-pass
#![feature(if_let_guard)]
fn t_if_let_chains_then() {
let e = Events::new();
_ = if e.ok(1).is_ok()
&& let true = e.ok(9).is_ok()
&& let Ok(_v) = e.ok(8)
&& let Ok(_) = e.ok(7)
&& let Ok(_) = e.ok(6).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(5)
&& let Ok(_) = e.ok(4).as_ref() {
e.mark(3);
};
e.assert(9);
}
fn t_guard_if_let_chains_then() {
let e = Events::new();
_ = match () {
() if e.ok(1).is_ok()
&& let true = e.ok(9).is_ok()
&& let Ok(_v) = e.ok(8)
&& let Ok(_) = e.ok(7)
&& let Ok(_) = e.ok(6).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(5)
&& let Ok(_) = e.ok(4).as_ref() => {
e.mark(3);
}
_ => {}
};
e.assert(9);
}
fn t_if_let_chains_then_else() {
let e = Events::new();
_ = if e.ok(1).is_ok()
&& let true = e.ok(8).is_ok()
&& let Ok(_v) = e.ok(7)
&& let Ok(_) = e.ok(6)
&& let Ok(_) = e.ok(5).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(4)
&& let Ok(_) = e.err(3) {} else {
e.mark(9);
};
e.assert(9);
}
fn t_guard_if_let_chains_then_else() {
let e = Events::new();
_ = match () {
() if e.ok(1).is_ok()
&& let true = e.ok(8).is_ok()
&& let Ok(_v) = e.ok(7)
&& let Ok(_) = e.ok(6)
&& let Ok(_) = e.ok(5).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(4)
&& let Ok(_) = e.err(3) => {}
_ => {
e.mark(9);
}
};
e.assert(9);
}
fn main() {
t_if_let_chains_then();
t_guard_if_let_chains_then();
t_if_let_chains_then_else();
t_guard_if_let_chains_then_else();
}
// # Test scaffolding
use core::cell::RefCell;
use std::collections::HashSet;
/// A buffer to track the order of events.
///
/// First, numbered events are logged into this buffer.
///
/// Then, `assert` is called to verify that the correct number of
/// events were logged, and that they were logged in the expected
/// order.
struct Events(RefCell<Option<Vec<u64>>>);
impl Events {
const fn new() -> Self {
Self(RefCell::new(Some(Vec::new())))
}
#[track_caller]
fn assert(&self, max: u64) {
let buf = &self.0;
let v1 = buf.borrow().as_ref().unwrap().clone();
let mut v2 = buf.borrow().as_ref().unwrap().clone();
*buf.borrow_mut() = None;
v2.sort();
let uniq_len = v2.iter().collect::<HashSet<_>>().len();
// Check that the sequence is sorted.
assert_eq!(v1, v2);
// Check that there are no duplicates.
assert_eq!(v2.len(), uniq_len);
// Check that the length is the expected one.
assert_eq!(max, uniq_len as u64);
// Check that the last marker is the expected one.
assert_eq!(v2.last().unwrap(), &max);
}
/// Return an `Ok` value that logs its drop.
fn ok(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> {
Ok(LogDrop(self, m))
}
/// Return an `Err` value that logs its drop.
fn err(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> {
Err(LogDrop(self, m))
}
/// Log an event.
fn mark(&self, m: u64) {
self.0.borrow_mut().as_mut().unwrap().push(m);
}
}
impl Drop for Events {
fn drop(&mut self) {
if self.0.borrow().is_some() {
panic!("failed to call `Events::assert()`");
}
}
}
/// A type that logs its drop events.
struct LogDrop<'b>(&'b Events, u64);
impl<'b> Drop for LogDrop<'b> {
fn drop(&mut self) {
self.0.mark(self.1);
}
}

View file

@ -1,3 +1,6 @@
// N.B. drop-order-comparisons-let-chains.rs is part of this test.
// It is separate because let chains cannot be parsed before Rust 2024.
//
// This tests various aspects of the drop order with a focus on:
//
// - The lifetime of temporaries with the `if let` construct (and with
@ -25,7 +28,6 @@
//@ run-pass
#![feature(if_let_guard)]
#![cfg_attr(e2021, feature(let_chains))]
#![cfg_attr(e2021, warn(rust_2024_compatibility))]
fn t_bindings() {
@ -311,59 +313,6 @@ fn t_let_else_chained_then() {
e.assert(9);
}
#[cfg(e2021)]
#[rustfmt::skip]
fn t_if_let_chains_then() {
let e = Events::new();
_ = if e.ok(1).is_ok()
&& let true = e.ok(9).is_ok()
&& let Ok(_v) = e.ok(5)
&& let Ok(_) = e.ok(8)
&& let Ok(_) = e.ok(7).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(4)
&& let Ok(_) = e.ok(6).as_ref() {
e.mark(3);
};
e.assert(9);
}
#[cfg(e2024)]
#[rustfmt::skip]
fn t_if_let_chains_then() {
let e = Events::new();
_ = if e.ok(1).is_ok()
&& let true = e.ok(9).is_ok()
&& let Ok(_v) = e.ok(8)
&& let Ok(_) = e.ok(7)
&& let Ok(_) = e.ok(6).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(5)
&& let Ok(_) = e.ok(4).as_ref() {
e.mark(3);
};
e.assert(9);
}
#[rustfmt::skip]
fn t_guard_if_let_chains_then() {
let e = Events::new();
_ = match () {
() if e.ok(1).is_ok()
&& let true = e.ok(9).is_ok()
&& let Ok(_v) = e.ok(8)
&& let Ok(_) = e.ok(7)
&& let Ok(_) = e.ok(6).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(5)
&& let Ok(_) = e.ok(4).as_ref() => {
e.mark(3);
}
_ => {}
};
e.assert(9);
}
#[cfg(e2021)]
#[rustfmt::skip]
fn t_if_let_nested_else() {
@ -470,59 +419,6 @@ fn t_let_else_chained_then_else() {
e.assert(9);
}
#[cfg(e2021)]
#[rustfmt::skip]
fn t_if_let_chains_then_else() {
let e = Events::new();
_ = if e.ok(1).is_ok()
&& let true = e.ok(9).is_ok()
&& let Ok(_v) = e.ok(4)
&& let Ok(_) = e.ok(8)
&& let Ok(_) = e.ok(7).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(3)
&& let Ok(_) = e.err(6) {} else {
e.mark(5);
};
e.assert(9);
}
#[cfg(e2024)]
#[rustfmt::skip]
fn t_if_let_chains_then_else() {
let e = Events::new();
_ = if e.ok(1).is_ok()
&& let true = e.ok(8).is_ok()
&& let Ok(_v) = e.ok(7)
&& let Ok(_) = e.ok(6)
&& let Ok(_) = e.ok(5).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(4)
&& let Ok(_) = e.err(3) {} else {
e.mark(9);
};
e.assert(9);
}
#[rustfmt::skip]
fn t_guard_if_let_chains_then_else() {
let e = Events::new();
_ = match () {
() if e.ok(1).is_ok()
&& let true = e.ok(8).is_ok()
&& let Ok(_v) = e.ok(7)
&& let Ok(_) = e.ok(6)
&& let Ok(_) = e.ok(5).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(4)
&& let Ok(_) = e.err(3) => {}
_ => {
e.mark(9);
}
};
e.assert(9);
}
fn main() {
t_bindings();
t_tuples();
@ -540,13 +436,9 @@ fn main() {
t_if_let_else_tailexpr();
t_if_let_nested_then();
t_let_else_chained_then();
t_if_let_chains_then();
t_guard_if_let_chains_then();
t_if_let_nested_else();
t_if_let_nested_then_else();
t_let_else_chained_then_else();
t_if_let_chains_then_else();
t_guard_if_let_chains_then_else();
}
// # Test scaffolding

View file

@ -1,5 +1,5 @@
warning: relative drop order changing in Rust 2024
--> $DIR/drop-order-comparisons.rs:77:9
--> $DIR/drop-order-comparisons.rs:79:9
|
LL | _ = ({
| _________-
@ -29,35 +29,35 @@ LL | | }, e.mark(3), e.ok(4));
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
note: `#3` invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: `#1` invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: `_v` invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: `#2` invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
note: the lint level is defined here
--> $DIR/drop-order-comparisons.rs:29:25
--> $DIR/drop-order-comparisons.rs:31:25
|
LL | #![cfg_attr(e2021, warn(rust_2024_compatibility))]
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: `#[warn(tail_expr_drop_order)]` implied by `#[warn(rust_2024_compatibility)]`
warning: relative drop order changing in Rust 2024
--> $DIR/drop-order-comparisons.rs:101:45
--> $DIR/drop-order-comparisons.rs:103:45
|
LL | _ = ({
| _________-
@ -77,19 +77,19 @@ LL | | }, e.mark(1), e.ok(4));
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
note: `#2` invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: `#1` invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
warning: relative drop order changing in Rust 2024
--> $DIR/drop-order-comparisons.rs:101:19
--> $DIR/drop-order-comparisons.rs:103:19
|
LL | _ = ({
| _________-
@ -109,19 +109,19 @@ LL | | }, e.mark(1), e.ok(4));
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
note: `#2` invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: `#1` invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
warning: relative drop order changing in Rust 2024
--> $DIR/drop-order-comparisons.rs:222:24
--> $DIR/drop-order-comparisons.rs:224:24
|
LL | _ = ({
| _________-
@ -141,19 +141,19 @@ LL | | }, e.mark(2), e.ok(3));
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
note: `#2` invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: `#1` invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
warning: relative drop order changing in Rust 2024
--> $DIR/drop-order-comparisons.rs:248:24
--> $DIR/drop-order-comparisons.rs:250:24
|
LL | _ = ({
| _________-
@ -173,19 +173,19 @@ LL | | }, e.mark(2), e.ok(3));
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
note: `#2` invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: `#1` invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
warning: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/drop-order-comparisons.rs:124:13
--> $DIR/drop-order-comparisons.rs:126:13
|
LL | _ = (if let Ok(_) = e.ok(4).as_ref() {
| ^^^^^^^^^^^^-------^^^^^^^^^
@ -195,12 +195,12 @@ LL | _ = (if let Ok(_) = e.ok(4).as_ref() {
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
note: value invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the value is now dropped here in Edition 2024
--> $DIR/drop-order-comparisons.rs:128:5
--> $DIR/drop-order-comparisons.rs:130:5
|
LL | }, e.mark(2), e.ok(3));
| ^
@ -215,7 +215,7 @@ LL ~ } _ => {}}, e.mark(2), e.ok(3));
|
warning: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/drop-order-comparisons.rs:146:13
--> $DIR/drop-order-comparisons.rs:148:13
|
LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else {
| ^^^^^^^^^^^^--------^^^^^^^^^
@ -225,12 +225,12 @@ LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else {
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
note: value invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the value is now dropped here in Edition 2024
--> $DIR/drop-order-comparisons.rs:146:44
--> $DIR/drop-order-comparisons.rs:148:44
|
LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else {
| ^
@ -244,7 +244,7 @@ LL ~ }}, e.mark(2), e.ok(3));
|
warning: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/drop-order-comparisons.rs:248:12
--> $DIR/drop-order-comparisons.rs:250:12
|
LL | if let Ok(_) = e.err(4).as_ref() {} else {
| ^^^^^^^^^^^^--------^^^^^^^^^
@ -254,12 +254,12 @@ LL | if let Ok(_) = e.err(4).as_ref() {} else {
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
note: value invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the value is now dropped here in Edition 2024
--> $DIR/drop-order-comparisons.rs:248:43
--> $DIR/drop-order-comparisons.rs:250:43
|
LL | if let Ok(_) = e.err(4).as_ref() {} else {
| ^
@ -273,7 +273,7 @@ LL ~ }}
|
warning: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/drop-order-comparisons.rs:372:12
--> $DIR/drop-order-comparisons.rs:321:12
|
LL | if let true = e.err(9).is_ok() {} else {
| ^^^^^^^^^^^--------^^^^^^^^
@ -283,12 +283,12 @@ LL | if let true = e.err(9).is_ok() {} else {
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
note: value invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the value is now dropped here in Edition 2024
--> $DIR/drop-order-comparisons.rs:372:41
--> $DIR/drop-order-comparisons.rs:321:41
|
LL | if let true = e.err(9).is_ok() {} else {
| ^
@ -302,7 +302,7 @@ LL ~ }}}}}}}}};
|
warning: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/drop-order-comparisons.rs:375:12
--> $DIR/drop-order-comparisons.rs:324:12
|
LL | if let Ok(_v) = e.err(8) {} else {
| ^^^^^^^^^^^^^--------
@ -312,12 +312,12 @@ LL | if let Ok(_v) = e.err(8) {} else {
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
note: value invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the value is now dropped here in Edition 2024
--> $DIR/drop-order-comparisons.rs:375:35
--> $DIR/drop-order-comparisons.rs:324:35
|
LL | if let Ok(_v) = e.err(8) {} else {
| ^
@ -331,7 +331,7 @@ LL ~ }}}}}}}}};
|
warning: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/drop-order-comparisons.rs:378:12
--> $DIR/drop-order-comparisons.rs:327:12
|
LL | if let Ok(_) = e.err(7) {} else {
| ^^^^^^^^^^^^--------
@ -341,12 +341,12 @@ LL | if let Ok(_) = e.err(7) {} else {
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
note: value invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the value is now dropped here in Edition 2024
--> $DIR/drop-order-comparisons.rs:378:34
--> $DIR/drop-order-comparisons.rs:327:34
|
LL | if let Ok(_) = e.err(7) {} else {
| ^
@ -360,7 +360,7 @@ LL ~ }}}}}}}}};
|
warning: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/drop-order-comparisons.rs:381:12
--> $DIR/drop-order-comparisons.rs:330:12
|
LL | if let Ok(_) = e.err(6).as_ref() {} else {
| ^^^^^^^^^^^^--------^^^^^^^^^
@ -370,12 +370,12 @@ LL | if let Ok(_) = e.err(6).as_ref() {} else {
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
note: value invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the value is now dropped here in Edition 2024
--> $DIR/drop-order-comparisons.rs:381:43
--> $DIR/drop-order-comparisons.rs:330:43
|
LL | if let Ok(_) = e.err(6).as_ref() {} else {
| ^
@ -389,7 +389,7 @@ LL ~ }}}}}}}}};
|
warning: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/drop-order-comparisons.rs:385:12
--> $DIR/drop-order-comparisons.rs:334:12
|
LL | if let Ok(_v) = e.err(5) {} else {
| ^^^^^^^^^^^^^--------
@ -399,12 +399,12 @@ LL | if let Ok(_v) = e.err(5) {} else {
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
note: value invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the value is now dropped here in Edition 2024
--> $DIR/drop-order-comparisons.rs:385:35
--> $DIR/drop-order-comparisons.rs:334:35
|
LL | if let Ok(_v) = e.err(5) {} else {
| ^
@ -418,7 +418,7 @@ LL ~ }}}}}}}}};
|
warning: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/drop-order-comparisons.rs:388:12
--> $DIR/drop-order-comparisons.rs:337:12
|
LL | if let Ok(_) = e.err(4) {} else {
| ^^^^^^^^^^^^--------
@ -428,12 +428,12 @@ LL | if let Ok(_) = e.err(4) {} else {
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
note: value invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the value is now dropped here in Edition 2024
--> $DIR/drop-order-comparisons.rs:388:34
--> $DIR/drop-order-comparisons.rs:337:34
|
LL | if let Ok(_) = e.err(4) {} else {
| ^
@ -447,7 +447,7 @@ LL ~ }}}}}}}}};
|
warning: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/drop-order-comparisons.rs:424:12
--> $DIR/drop-order-comparisons.rs:373:12
|
LL | if let Ok(_) = e.err(4).as_ref() {} else {
| ^^^^^^^^^^^^--------^^^^^^^^^
@ -457,12 +457,12 @@ LL | if let Ok(_) = e.err(4).as_ref() {} else {
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
note: value invokes this custom destructor
--> $DIR/drop-order-comparisons.rs:612:1
--> $DIR/drop-order-comparisons.rs:504:1
|
LL | impl<'b> Drop for LogDrop<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the value is now dropped here in Edition 2024
--> $DIR/drop-order-comparisons.rs:424:43
--> $DIR/drop-order-comparisons.rs:373:43
|
LL | if let Ok(_) = e.err(4).as_ref() {} else {
| ^

View file

@ -1,3 +1,6 @@
// N.B. drop-order-comparisons-let-chains.rs is part of this test.
// It is separate because let chains cannot be parsed before Rust 2024.
//
// This tests various aspects of the drop order with a focus on:
//
// - The lifetime of temporaries with the `if let` construct (and with
@ -25,7 +28,6 @@
//@ run-pass
#![feature(if_let_guard)]
#![cfg_attr(e2021, feature(let_chains))]
#![cfg_attr(e2021, warn(rust_2024_compatibility))]
fn t_bindings() {
@ -311,59 +313,6 @@ fn t_let_else_chained_then() {
e.assert(9);
}
#[cfg(e2021)]
#[rustfmt::skip]
fn t_if_let_chains_then() {
let e = Events::new();
_ = if e.ok(1).is_ok()
&& let true = e.ok(9).is_ok()
&& let Ok(_v) = e.ok(5)
&& let Ok(_) = e.ok(8)
&& let Ok(_) = e.ok(7).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(4)
&& let Ok(_) = e.ok(6).as_ref() {
e.mark(3);
};
e.assert(9);
}
#[cfg(e2024)]
#[rustfmt::skip]
fn t_if_let_chains_then() {
let e = Events::new();
_ = if e.ok(1).is_ok()
&& let true = e.ok(9).is_ok()
&& let Ok(_v) = e.ok(8)
&& let Ok(_) = e.ok(7)
&& let Ok(_) = e.ok(6).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(5)
&& let Ok(_) = e.ok(4).as_ref() {
e.mark(3);
};
e.assert(9);
}
#[rustfmt::skip]
fn t_guard_if_let_chains_then() {
let e = Events::new();
_ = match () {
() if e.ok(1).is_ok()
&& let true = e.ok(9).is_ok()
&& let Ok(_v) = e.ok(8)
&& let Ok(_) = e.ok(7)
&& let Ok(_) = e.ok(6).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(5)
&& let Ok(_) = e.ok(4).as_ref() => {
e.mark(3);
}
_ => {}
};
e.assert(9);
}
#[cfg(e2021)]
#[rustfmt::skip]
fn t_if_let_nested_else() {
@ -470,59 +419,6 @@ fn t_let_else_chained_then_else() {
e.assert(9);
}
#[cfg(e2021)]
#[rustfmt::skip]
fn t_if_let_chains_then_else() {
let e = Events::new();
_ = if e.ok(1).is_ok()
&& let true = e.ok(9).is_ok()
&& let Ok(_v) = e.ok(4)
&& let Ok(_) = e.ok(8)
&& let Ok(_) = e.ok(7).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(3)
&& let Ok(_) = e.err(6) {} else {
e.mark(5);
};
e.assert(9);
}
#[cfg(e2024)]
#[rustfmt::skip]
fn t_if_let_chains_then_else() {
let e = Events::new();
_ = if e.ok(1).is_ok()
&& let true = e.ok(8).is_ok()
&& let Ok(_v) = e.ok(7)
&& let Ok(_) = e.ok(6)
&& let Ok(_) = e.ok(5).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(4)
&& let Ok(_) = e.err(3) {} else {
e.mark(9);
};
e.assert(9);
}
#[rustfmt::skip]
fn t_guard_if_let_chains_then_else() {
let e = Events::new();
_ = match () {
() if e.ok(1).is_ok()
&& let true = e.ok(8).is_ok()
&& let Ok(_v) = e.ok(7)
&& let Ok(_) = e.ok(6)
&& let Ok(_) = e.ok(5).as_ref()
&& e.ok(2).is_ok()
&& let Ok(_v) = e.ok(4)
&& let Ok(_) = e.err(3) => {}
_ => {
e.mark(9);
}
};
e.assert(9);
}
fn main() {
t_bindings();
t_tuples();
@ -540,13 +436,9 @@ fn main() {
t_if_let_else_tailexpr();
t_if_let_nested_then();
t_let_else_chained_then();
t_if_let_chains_then();
t_guard_if_let_chains_then();
t_if_let_nested_else();
t_if_let_nested_then_else();
t_let_else_chained_then_else();
t_if_let_chains_then_else();
t_guard_if_let_chains_then_else();
}
// # Test scaffolding

View file

@ -5,8 +5,6 @@
//@ [edition2024] compile-flags: -Z lint-mir
//@ [edition2024] edition: 2024
#![cfg_attr(edition2021, feature(let_chains))]
use std::cell::RefCell;
use std::convert::TryInto;
@ -210,68 +208,6 @@ impl DropOrderCollector {
}
}
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
}
#[cfg(edition2021)]
// 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(8) { // 4
unreachable!();
} else {
self.print(7); // 3
}
#[cfg(edition2024)]
// 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) { // 4
unreachable!();
} else {
self.print(8); // 3
}
// 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 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
@ -313,14 +249,4 @@ 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();
}

View file

@ -0,0 +1,103 @@
//@ run-pass
//@ compile-flags: -Z validate-mir
//@ edition: 2024
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 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) { // 4
unreachable!();
} else {
self.print(8); // 3
}
// 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 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
.into_inner()
.into_iter()
.enumerate()
.all(|(idx, item)| idx + 1 == item.try_into().unwrap())
);
}
}
fn main() {
println!("-- let chain --");
let collector = DropOrderCollector::default();
collector.let_chain();
collector.assert_sorted();
println!("-- while --");
let collector = DropOrderCollector::default();
collector.while_();
collector.assert_sorted();
}

View file

@ -1,11 +1,6 @@
//@ check-pass
//@ compile-flags: -Z validate-mir
//@ revisions: edition2021 edition2024
//@ [edition2021] edition: 2021
//@ [edition2024] compile-flags: -Z lint-mir
//@ [edition2024] edition: 2024
#![cfg_attr(edition2021, feature(let_chains))]
//@ compile-flags: -Z lint-mir -Z validate-mir
//@ edition: 2024
fn let_chains(entry: std::io::Result<std::fs::DirEntry>) {
if let Ok(entry) = entry

View file

@ -1,5 +1,5 @@
//@ run-pass
//@ edition:2021
//@ edition:2024
//@ compile-flags: --test
#![allow(incomplete_features)]
@ -10,7 +10,6 @@
#![feature(decl_macro)]
#![feature(explicit_tail_calls)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(more_qualified_paths)]
#![feature(never_patterns)]
#![feature(trait_alias)]

View file

@ -1,12 +1,9 @@
//@ run-pass
//@ needs-unwind
//@ revisions: edition2021 edition2024
//@ [edition2021] edition: 2021
//@ [edition2024] edition: 2024
//@ edition: 2024
// See `mir_drop_order.rs` for more information
#![cfg_attr(edition2021, feature(let_chains))]
#![allow(irrefutable_let_patterns)]
use std::cell::RefCell;
@ -64,9 +61,6 @@ fn main() {
d(10, None)
},
);
#[cfg(edition2021)]
assert_eq!(get(), vec![8, 7, 1, 3, 2]);
#[cfg(edition2024)]
assert_eq!(get(), vec![3, 2, 8, 7, 1]);
}
assert_eq!(get(), vec![0, 4, 6, 9, 5]);
@ -101,8 +95,5 @@ fn main() {
panic::panic_any(InjectedFailure),
);
});
#[cfg(edition2021)]
assert_eq!(get(), vec![20, 17, 15, 11, 19, 18, 16, 12, 14, 13]);
#[cfg(edition2024)]
assert_eq!(get(), vec![14, 13, 19, 18, 20, 17, 15, 11, 16, 12]);
}

View file

@ -1,4 +1,6 @@
#![feature(if_let_guard, let_chains)]
//@ edition: 2024
#![feature(if_let_guard)]
fn main() {
let mut x = Some(String::new());

View file

@ -1,5 +1,5 @@
error: cannot borrow value as mutable more than once at a time
--> $DIR/conflicting_bindings.rs:5:9
--> $DIR/conflicting_bindings.rs:7:9
|
LL | let ref mut y @ ref mut z = x;
| ^^^^^^^^^ --------- value is mutably borrowed by `z` here
@ -7,7 +7,7 @@ LL | let ref mut y @ ref mut z = x;
| value is mutably borrowed by `y` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/conflicting_bindings.rs:7:14
--> $DIR/conflicting_bindings.rs:9:14
|
LL | let Some(ref mut y @ ref mut z) = x else { return };
| ^^^^^^^^^ --------- value is mutably borrowed by `z` here
@ -15,7 +15,7 @@ LL | let Some(ref mut y @ ref mut z) = x else { return };
| value is mutably borrowed by `y` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/conflicting_bindings.rs:9:17
--> $DIR/conflicting_bindings.rs:11:17
|
LL | if let Some(ref mut y @ ref mut z) = x {}
| ^^^^^^^^^ --------- value is mutably borrowed by `z` here
@ -23,7 +23,7 @@ LL | if let Some(ref mut y @ ref mut z) = x {}
| value is mutably borrowed by `y` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/conflicting_bindings.rs:11:17
--> $DIR/conflicting_bindings.rs:13:17
|
LL | if let Some(ref mut y @ ref mut z) = x && true {}
| ^^^^^^^^^ --------- value is mutably borrowed by `z` here
@ -31,7 +31,7 @@ LL | if let Some(ref mut y @ ref mut z) = x && true {}
| value is mutably borrowed by `y` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/conflicting_bindings.rs:13:43
--> $DIR/conflicting_bindings.rs:15:43
|
LL | if let Some(_) = Some(()) && let Some(ref mut y @ ref mut z) = x && true {}
| ^^^^^^^^^ --------- value is mutably borrowed by `z` here
@ -39,7 +39,7 @@ LL | if let Some(_) = Some(()) && let Some(ref mut y @ ref mut z) = x && tru
| value is mutably borrowed by `y` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/conflicting_bindings.rs:15:20
--> $DIR/conflicting_bindings.rs:17:20
|
LL | while let Some(ref mut y @ ref mut z) = x {}
| ^^^^^^^^^ --------- value is mutably borrowed by `z` here
@ -47,7 +47,7 @@ LL | while let Some(ref mut y @ ref mut z) = x {}
| value is mutably borrowed by `y` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/conflicting_bindings.rs:17:20
--> $DIR/conflicting_bindings.rs:19:20
|
LL | while let Some(ref mut y @ ref mut z) = x && true {}
| ^^^^^^^^^ --------- value is mutably borrowed by `z` here
@ -55,7 +55,7 @@ LL | while let Some(ref mut y @ ref mut z) = x && true {}
| value is mutably borrowed by `y` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/conflicting_bindings.rs:20:9
--> $DIR/conflicting_bindings.rs:22:9
|
LL | ref mut y @ ref mut z => {}
| ^^^^^^^^^ --------- value is mutably borrowed by `z` here
@ -63,7 +63,7 @@ LL | ref mut y @ ref mut z => {}
| value is mutably borrowed by `y` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/conflicting_bindings.rs:23:24
--> $DIR/conflicting_bindings.rs:25:24
|
LL | () if let Some(ref mut y @ ref mut z) = x => {}
| ^^^^^^^^^ --------- value is mutably borrowed by `z` here

View file

@ -0,0 +1,57 @@
// Ensure that temporaries in if-let guards live for the arm
// regression test for #118593
//@ check-pass
//@ edition: 2024
#![feature(if_let_guard)]
fn get_temp() -> Option<String> {
None
}
fn let_let_chain_guard(num: u8) {
match num {
5 | 6
if let Some(ref a) = get_temp()
&& let Some(ref b) = get_temp() =>
{
let _x = a;
let _y = b;
}
_ => {}
}
match num {
7 | 8
if let Some(ref mut c) = get_temp()
&& let Some(ref mut d) = get_temp() =>
{
let _w = c;
let _z = d;
}
_ => {}
}
}
fn let_cond_chain_guard(num: u8) {
match num {
9 | 10
if let Some(ref a) = get_temp()
&& true =>
{
let _x = a;
}
_ => {}
}
match num {
11 | 12
if let Some(ref mut b) = get_temp()
&& true =>
{
let _w = b;
}
_ => {}
}
}
fn main() {}

View file

@ -4,7 +4,6 @@
//@ check-pass
#![feature(if_let_guard)]
#![feature(let_chains)]
fn get_temp() -> Option<String> {
None
@ -25,48 +24,4 @@ fn let_guard(num: u8) {
}
}
fn let_let_chain_guard(num: u8) {
match num {
5 | 6
if let Some(ref a) = get_temp()
&& let Some(ref b) = get_temp() =>
{
let _x = a;
let _y = b;
}
_ => {}
}
match num {
7 | 8
if let Some(ref mut c) = get_temp()
&& let Some(ref mut d) = get_temp() =>
{
let _w = c;
let _z = d;
}
_ => {}
}
}
fn let_cond_chain_guard(num: u8) {
match num {
9 | 10
if let Some(ref a) = get_temp()
&& true =>
{
let _x = a;
}
_ => {}
}
match num {
11 | 12
if let Some(ref mut b) = get_temp()
&& true =>
{
let _w = b;
}
_ => {}
}
}
fn main() {}

View file

@ -2,7 +2,6 @@
//@ check-pass
#![feature(if_let_guard)]
#![feature(let_chains)]
macro_rules! m {
(pattern $i:ident) => { Some($i) };

View file

@ -3,7 +3,6 @@
//@run-pass
#![feature(if_let_guard)]
#![feature(let_chains)]
#![allow(irrefutable_let_patterns)]
fn lhs_let(opt: Option<bool>) {

View file

@ -1,5 +1,7 @@
//@ revisions: no_feature feature nothing
//@ edition: 2021
//@ revisions: e2021 e2024 nothing
//@ [e2021] edition: 2021
//@ [e2024] edition: 2024
//@ [nothing] edition: 2024
// Here we test that `lowering` behaves correctly wrt. `let $pats = $expr` expressions.
//
// We want to make sure that `let` is banned in situations other than:
@ -19,9 +21,6 @@
//
// To that end, we check some positions which is not part of the language above.
// Avoid inflating `.stderr` with overzealous gates (or test what happens if you disable the gate)
#![cfg_attr(not(no_feature), feature(let_chains))]
#![allow(irrefutable_let_patterns)]
use std::ops::Range;
@ -50,8 +49,8 @@ fn _if() {
//~^ ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
//[no_feature]~| ERROR `let` expressions in this position are unstable
//[no_feature]~| ERROR `let` expressions in this position are unstable
//[e2021]~| ERROR let chains are only allowed in Rust 2024 or later
//[e2021]~| ERROR let chains are only allowed in Rust 2024 or later
}
#[cfg(not(nothing))]
@ -76,8 +75,8 @@ fn _while() {
//~^ ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
//[no_feature]~| ERROR `let` expressions in this position are unstable
//[no_feature]~| ERROR `let` expressions in this position are unstable
//[e2021]~| ERROR let chains are only allowed in Rust 2024 or later
//[e2021]~| ERROR let chains are only allowed in Rust 2024 or later
}
#[cfg(not(nothing))]
@ -89,13 +88,13 @@ fn _macros() {
}
}
use_expr!((let 0 = 1 && 0 == 0));
//[feature,no_feature]~^ ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR expected expression, found `let` statement
//[e2021,e2024]~^ ERROR expected expression, found `let` statement
//[e2021,e2024]~| ERROR expected expression, found `let` statement
//[e2021,e2024]~| ERROR expected expression, found `let` statement
use_expr!((let 0 = 1));
//[feature,no_feature]~^ ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR expected expression, found `let` statement
//[e2021,e2024]~^ ERROR expected expression, found `let` statement
//[e2021,e2024]~| ERROR expected expression, found `let` statement
//[e2021,e2024]~| ERROR expected expression, found `let` statement
}
#[cfg(not(nothing))]
@ -112,7 +111,7 @@ fn nested_within_if_expr() {
fn _check_try_binds_tighter() -> Result<(), ()> {
if let 0 = 0? {}
//[feature,no_feature]~^ ERROR the `?` operator can only be applied to values that implement `Try`
//[e2021,e2024]~^ ERROR the `?` operator can only be applied to values that implement `Try`
Ok(())
}
if (let 0 = 0)? {}
@ -133,7 +132,7 @@ fn nested_within_if_expr() {
if true..(let 0 = 0) {}
//~^ ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR mismatched types
//[e2021,e2024]~| ERROR mismatched types
if ..(let 0 = 0) {}
//~^ ERROR expected expression, found `let` statement
if (let 0 = 0).. {}
@ -142,22 +141,22 @@ fn nested_within_if_expr() {
// Binds as `(let ... = true)..true &&/|| false`.
if let Range { start: _, end: _ } = true..true && false {}
//~^ ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR mismatched types
//[e2021,e2024]~| ERROR mismatched types
if let Range { start: _, end: _ } = true..true || false {}
//~^ ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR mismatched types
//[e2021,e2024]~| ERROR mismatched types
// Binds as `(let Range { start: F, end } = F)..(|| true)`.
const F: fn() -> bool = || true;
if let Range { start: F, end } = F..|| true {}
//~^ ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR mismatched types
//[e2021,e2024]~| ERROR mismatched types
// Binds as `(let Range { start: true, end } = t)..(&&false)`.
let t = &&true;
if let Range { start: true, end } = t..&&false {}
//~^ ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR mismatched types
//[e2021,e2024]~| ERROR mismatched types
if let true = let true = true {}
//~^ ERROR expected expression, found `let` statement
@ -203,7 +202,7 @@ fn nested_within_while_expr() {
fn _check_try_binds_tighter() -> Result<(), ()> {
while let 0 = 0? {}
//[feature,no_feature]~^ ERROR the `?` operator can only be applied to values that implement `Try`
//[e2021,e2024]~^ ERROR the `?` operator can only be applied to values that implement `Try`
Ok(())
}
while (let 0 = 0)? {}
@ -224,7 +223,7 @@ fn nested_within_while_expr() {
while true..(let 0 = 0) {}
//~^ ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR mismatched types
//[e2021,e2024]~| ERROR mismatched types
while ..(let 0 = 0) {}
//~^ ERROR expected expression, found `let` statement
while (let 0 = 0).. {}
@ -233,22 +232,22 @@ fn nested_within_while_expr() {
// Binds as `(let ... = true)..true &&/|| false`.
while let Range { start: _, end: _ } = true..true && false {}
//~^ ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR mismatched types
//[e2021,e2024]~| ERROR mismatched types
while let Range { start: _, end: _ } = true..true || false {}
//~^ ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR mismatched types
//[e2021,e2024]~| ERROR mismatched types
// Binds as `(let Range { start: F, end } = F)..(|| true)`.
const F: fn() -> bool = || true;
while let Range { start: F, end } = F..|| true {}
//~^ ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR mismatched types
//[e2021,e2024]~| ERROR mismatched types
// Binds as `(let Range { start: true, end } = t)..(&&false)`.
let t = &&true;
while let Range { start: true, end } = t..&&false {}
//~^ ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR mismatched types
//[e2021,e2024]~| ERROR mismatched types
while let true = let true = true {}
//~^ ERROR expected expression, found `let` statement
@ -307,7 +306,7 @@ fn outside_if_and_while_expr() {
fn _check_try_binds_tighter() -> Result<(), ()> {
let 0 = 0?;
//[feature,no_feature]~^ ERROR the `?` operator can only be applied to values that implement `Try`
//[e2021,e2024]~^ ERROR the `?` operator can only be applied to values that implement `Try`
Ok(())
}
(let 0 = 0)?;
@ -333,7 +332,7 @@ fn outside_if_and_while_expr() {
(let Range { start: _, end: _ } = true..true || false);
//~^ ERROR expected expression, found `let` statement
//[feature,no_feature]~| ERROR mismatched types
//[e2021,e2024]~| ERROR mismatched types
(let true = let true = true);
//~^ ERROR expected expression, found `let` statement
@ -406,7 +405,7 @@ fn with_parenthesis() {
//~| ERROR expected expression, found `let` statement
}
if let Some(a) = opt && (true && true) {
//[no_feature]~^ ERROR `let` expressions in this position are unstable
//[e2021]~^ ERROR let chains are only allowed in Rust 2024 or later
}
if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
@ -422,18 +421,18 @@ fn with_parenthesis() {
}
if (true && (true)) && let Some(a) = opt {
//[no_feature]~^ ERROR `let` expressions in this position are unstable
//[e2021]~^ ERROR let chains are only allowed in Rust 2024 or later
}
if (true) && let Some(a) = opt {
//[no_feature]~^ ERROR `let` expressions in this position are unstable
//[e2021]~^ ERROR let chains are only allowed in Rust 2024 or later
}
if true && let Some(a) = opt {
//[no_feature]~^ ERROR `let` expressions in this position are unstable
//[e2021]~^ ERROR let chains are only allowed in Rust 2024 or later
}
let fun = || true;
if let true = (true && fun()) && (true) {
//[no_feature]~^ ERROR `let` expressions in this position are unstable
//[e2021]~^ ERROR let chains are only allowed in Rust 2024 or later
}
#[cfg(false)]

View file

@ -1,65 +1,42 @@
error[E0658]: `let` expressions in this position are unstable
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate-macro-error.rs:19:30
|
LL | macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate-macro-error.rs:19:52
|
LL | macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate-macro-error.rs:22:5
|
LL | macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: this error originates in the macro `macro_in_2021::make_if` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: `let` expressions in this position are unstable
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate-macro-error.rs:22:5
|
LL | macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: this error originates in the macro `macro_in_2021::make_if` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: `let` expressions in this position are unstable
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate-macro-error.rs:26:30
|
LL | macro_in_2024::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate-macro-error.rs:26:52
|
LL | macro_in_2024::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -1,45 +1,30 @@
error[E0658]: `let` expressions in this position are unstable
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate-macro-error.rs:19:30
|
LL | macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate-macro-error.rs:19:52
|
LL | macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate-macro-error.rs:22:5
|
LL | macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: this error originates in the macro `macro_in_2021::make_if` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: `let` expressions in this position are unstable
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate-macro-error.rs:22:5
|
LL | macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: this error originates in the macro `macro_in_2021::make_if` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -17,14 +17,14 @@ fn main() {
// No gating if both the `if` and the chain are from a 2024 macro
macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR `let` expressions in this position are unstable
//~^ ERROR let chains are only allowed in Rust 2024 or later
//~| ERROR let chains are only allowed in Rust 2024 or later
macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() });
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR `let` expressions in this position are unstable
//~^ ERROR let chains are only allowed in Rust 2024 or later
//~| ERROR let chains are only allowed in Rust 2024 or later
macro_in_2024::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
//[edition2021]~^ ERROR `let` expressions in this position are unstable
//[edition2021]~| ERROR `let` expressions in this position are unstable
//[edition2021]~^ ERROR let chains are only allowed in Rust 2024 or later
//[edition2021]~| ERROR let chains are only allowed in Rust 2024 or later
macro_in_2024::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() });
}

View file

@ -1,6 +1,4 @@
// gate-test-let_chains
// Here we test feature gating for ´let_chains`.
// Here we test Rust 2024 edition gating for ´let_chains`.
// See `disallowed-positions.rs` for the grammar
// defining the language for gated allowed positions.
@ -12,17 +10,17 @@ fn _if() {
if let 0 = 1 {} // Stable!
if true && let 0 = 1 {}
//~^ ERROR `let` expressions in this position are unstable [E0658]
//~^ ERROR let chains are only allowed in Rust 2024 or later
if let 0 = 1 && true {}
//~^ ERROR `let` expressions in this position are unstable [E0658]
//~^ ERROR let chains are only allowed in Rust 2024 or later
if let Range { start: _, end: _ } = (true..true) && false {}
//~^ ERROR `let` expressions in this position are unstable [E0658]
//~^ ERROR let chains are only allowed in Rust 2024 or later
if let 1 = 1 && let true = { true } && false {
//~^ ERROR `let` expressions in this position are unstable [E0658]
//~| ERROR `let` expressions in this position are unstable [E0658]
//~^ ERROR let chains are only allowed in Rust 2024 or later
//~| ERROR let chains are only allowed in Rust 2024 or later
}
}
@ -30,13 +28,13 @@ fn _while() {
while let 0 = 1 {} // Stable!
while true && let 0 = 1 {}
//~^ ERROR `let` expressions in this position are unstable [E0658]
//~^ ERROR let chains are only allowed in Rust 2024 or later
while let 0 = 1 && true {}
//~^ ERROR `let` expressions in this position are unstable [E0658]
//~^ ERROR let chains are only allowed in Rust 2024 or later
while let Range { start: _, end: _ } = (true..true) && false {}
//~^ ERROR `let` expressions in this position are unstable [E0658]
//~^ ERROR let chains are only allowed in Rust 2024 or later
}
fn _macros() {

View file

@ -0,0 +1,81 @@
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate.rs:12:16
|
LL | if true && let 0 = 1 {}
| ^^^^^^^^^
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate.rs:15:8
|
LL | if let 0 = 1 && true {}
| ^^^^^^^^^
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate.rs:18:8
|
LL | if let Range { start: _, end: _ } = (true..true) && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate.rs:21:8
|
LL | if let 1 = 1 && let true = { true } && false {
| ^^^^^^^^^
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate.rs:21:21
|
LL | if let 1 = 1 && let true = { true } && false {
| ^^^^^^^^^^^^^^^^^^^
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate.rs:30:19
|
LL | while true && let 0 = 1 {}
| ^^^^^^^^^
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate.rs:33:11
|
LL | while let 0 = 1 && true {}
| ^^^^^^^^^
error: let chains are only allowed in Rust 2024 or later
--> $DIR/edition-gate.rs:36:11
|
LL | while let Range { start: _, end: _ } = (true..true) && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: expected expression, found `let` statement
--> $DIR/edition-gate.rs:52:20
|
LL | #[cfg(false)] (let 0 = 1);
| ^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
error: expected expression, found `let` statement
--> $DIR/edition-gate.rs:43:17
|
LL | noop_expr!((let 0 = 1));
| ^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
error: no rules expected keyword `let`
--> $DIR/edition-gate.rs:54:15
|
LL | macro_rules! use_expr {
| --------------------- when calling this macro
...
LL | use_expr!(let 0 = 1);
| ^^^ no rules expected this token in macro call
|
note: while trying to match meta-variable `$e:expr`
--> $DIR/edition-gate.rs:47:10
|
LL | ($e:expr) => {
| ^^^^^^^
error: aborting due to 11 previous errors

View file

@ -1,114 +0,0 @@
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:54:20
|
LL | #[cfg(false)] (let 0 = 1);
| ^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:45:17
|
LL | noop_expr!((let 0 = 1));
| ^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
error: no rules expected keyword `let`
--> $DIR/feature-gate.rs:56:15
|
LL | macro_rules! use_expr {
| --------------------- when calling this macro
...
LL | use_expr!(let 0 = 1);
| ^^^ no rules expected this token in macro call
|
note: while trying to match meta-variable `$e:expr`
--> $DIR/feature-gate.rs:49:10
|
LL | ($e:expr) => {
| ^^^^^^^
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:14:16
|
LL | if true && let 0 = 1 {}
| ^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:17:8
|
LL | if let 0 = 1 && true {}
| ^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:20:8
|
LL | if let Range { start: _, end: _ } = (true..true) && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:23:8
|
LL | if let 1 = 1 && let true = { true } && false {
| ^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:23:21
|
LL | if let 1 = 1 && let true = { true } && false {
| ^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:32:19
|
LL | while true && let 0 = 1 {}
| ^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:35:11
|
LL | while let 0 = 1 && true {}
| ^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:38:11
|
LL | while let Range { start: _, end: _ } = (true..true) && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -1,4 +1,4 @@
#![feature(let_chains)]
//@ edition: 2024
fn main() {
let _opt = Some(1i32);

View file

@ -1,19 +1,19 @@
error: leading irrefutable pattern in let chain
--> $DIR/irrefutable-lets.rs:13:8
--> $DIR/irrefutable-lets.rs:14:8
|
LL | if let first = &opt && let Some(ref second) = first && let None = second.start {}
LL | if let first = &opt && let Some(second) = first && let None = second.start {}
| ^^^^^^^^^^^^^^^^
|
= note: this pattern will always match
= help: consider moving it outside of the construct
note: the lint level is defined here
--> $DIR/irrefutable-lets.rs:6:30
--> $DIR/irrefutable-lets.rs:7:30
|
LL | #![cfg_attr(disallowed, deny(irrefutable_let_patterns))]
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: irrefutable `if let` patterns
--> $DIR/irrefutable-lets.rs:19:8
--> $DIR/irrefutable-lets.rs:20:8
|
LL | if let first = &opt && let (a, b) = (1, 2) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -22,25 +22,25 @@ LL | if let first = &opt && let (a, b) = (1, 2) {}
= help: consider replacing the `if let` with a `let`
error: leading irrefutable pattern in let chain
--> $DIR/irrefutable-lets.rs:22:8
--> $DIR/irrefutable-lets.rs:23:8
|
LL | if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {}
LL | if let first = &opt && let Some(second) = first && let None = second.start && let v = 0 {}
| ^^^^^^^^^^^^^^^^
|
= note: this pattern will always match
= help: consider moving it outside of the construct
error: trailing irrefutable pattern in let chain
--> $DIR/irrefutable-lets.rs:22:87
--> $DIR/irrefutable-lets.rs:23:83
|
LL | if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {}
| ^^^^^^^^^
LL | if let first = &opt && let Some(second) = first && let None = second.start && let v = 0 {}
| ^^^^^^^^^
|
= note: this pattern will always match
= help: consider moving it into the body
error: trailing irrefutable patterns in let chain
--> $DIR/irrefutable-lets.rs:26:37
--> $DIR/irrefutable-lets.rs:27:37
|
LL | if let Some(ref first) = opt && let second = first && let _third = second {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -49,7 +49,7 @@ LL | if let Some(ref first) = opt && let second = first && let _third = seco
= help: consider moving them into the body
error: leading irrefutable pattern in let chain
--> $DIR/irrefutable-lets.rs:29:8
--> $DIR/irrefutable-lets.rs:30:8
|
LL | if let Range { start: local_start, end: _ } = (None..Some(1)) && let None = local_start {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -58,7 +58,7 @@ LL | if let Range { start: local_start, end: _ } = (None..Some(1)) && let No
= help: consider moving it outside of the construct
error: leading irrefutable pattern in let chain
--> $DIR/irrefutable-lets.rs:32:8
--> $DIR/irrefutable-lets.rs:33:8
|
LL | if let (a, b, c) = (Some(1), Some(1), Some(1)) && let None = Some(1) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -67,7 +67,7 @@ LL | if let (a, b, c) = (Some(1), Some(1), Some(1)) && let None = Some(1) {}
= help: consider moving it outside of the construct
error: leading irrefutable pattern in let chain
--> $DIR/irrefutable-lets.rs:35:8
--> $DIR/irrefutable-lets.rs:36:8
|
LL | if let first = &opt && let None = Some(1) {}
| ^^^^^^^^^^^^^^^^
@ -76,7 +76,7 @@ LL | if let first = &opt && let None = Some(1) {}
= help: consider moving it outside of the construct
error: irrefutable `if let` guard patterns
--> $DIR/irrefutable-lets.rs:44:28
--> $DIR/irrefutable-lets.rs:45:28
|
LL | Some(ref first) if let second = first && let _third = second && let v = 4 + 4 => {},
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -85,7 +85,7 @@ LL | Some(ref first) if let second = first && let _third = second && let
= help: consider removing the guard and adding a `let` inside the match arm
error: trailing irrefutable patterns in let chain
--> $DIR/irrefutable-lets.rs:59:16
--> $DIR/irrefutable-lets.rs:60:16
|
LL | && let v = local_end && let w = v => {},
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -94,7 +94,7 @@ LL | && let v = local_end && let w = v => {},
= help: consider moving them into the body
error: irrefutable `while let` patterns
--> $DIR/irrefutable-lets.rs:68:11
--> $DIR/irrefutable-lets.rs:69:11
|
LL | while let first = &opt && let (a, b) = (1, 2) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -103,7 +103,7 @@ LL | while let first = &opt && let (a, b) = (1, 2) {}
= help: consider instead using a `loop { ... }` with a `let` inside it
error: trailing irrefutable patterns in let chain
--> $DIR/irrefutable-lets.rs:71:40
--> $DIR/irrefutable-lets.rs:72:40
|
LL | while let Some(ref first) = opt && let second = first && let _third = second {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -112,7 +112,7 @@ LL | while let Some(ref first) = opt && let second = first && let _third = s
= help: consider moving them into the body
error: trailing irrefutable pattern in let chain
--> $DIR/irrefutable-lets.rs:87:12
--> $DIR/irrefutable-lets.rs:88:12
|
LL | && let x = &opt
| ^^^^^^^^^^^^
@ -121,7 +121,7 @@ LL | && let x = &opt
= help: consider moving it into the body
error: leading irrefutable pattern in let chain
--> $DIR/irrefutable-lets.rs:93:12
--> $DIR/irrefutable-lets.rs:94:12
|
LL | if let x = opt.clone().map(|_| 1)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,7 +1,8 @@
//@ revisions: allowed disallowed
//@[allowed] check-pass
//@ edition: 2024
#![feature(if_let_guard, let_chains)]
#![feature(if_let_guard)]
#![cfg_attr(allowed, allow(irrefutable_let_patterns))]
#![cfg_attr(disallowed, deny(irrefutable_let_patterns))]
@ -10,16 +11,16 @@ use std::ops::Range;
fn main() {
let opt = Some(None..Some(1));
if let first = &opt && let Some(ref second) = first && let None = second.start {}
if let first = &opt && let Some(second) = first && let None = second.start {}
//[disallowed]~^ ERROR leading irrefutable pattern in let chain
// No lint as the irrefutable pattern is surrounded by other stuff
if 4 * 2 == 0 && let first = &opt && let Some(ref second) = first && let None = second.start {}
if 4 * 2 == 0 && let first = &opt && let Some(second) = first && let None = second.start {}
if let first = &opt && let (a, b) = (1, 2) {}
//[disallowed]~^ ERROR irrefutable `if let` patterns
if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {}
if let first = &opt && let Some(second) = first && let None = second.start && let v = 0 {}
//[disallowed]~^ ERROR leading irrefutable pattern in let chain
//[disallowed]~^^ ERROR trailing irrefutable pattern in let chain
@ -63,7 +64,7 @@ fn main() {
// No error, despite the prefix being irrefutable: moving out could change the behaviour,
// due to possible side effects of the operation.
while let first = &opt && let Some(ref second) = first && let None = second.start {}
while let first = &opt && let Some(second) = first && let None = second.start {}
while let first = &opt && let (a, b) = (1, 2) {}
//[disallowed]~^ ERROR irrefutable `while let` patterns

View file

@ -1,6 +1,7 @@
//@ run-pass
//@ edition: 2024
#![feature(if_let_guard, let_chains)]
#![feature(if_let_guard)]
fn check_if_let(opt: Option<Option<Option<i32>>>, value: i32) -> bool {
if let Some(first) = opt