about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-04-11 21:55:58 +0000
committerbors <bors@rust-lang.org>2022-04-11 21:55:58 +0000
commitde392c7d31602ddf0fae1143c5ad822a1abe89df (patch)
tree5e44c98e2051ad629f9674394ddc01c0beac6b98
parent90ca44752a79dd414d9a0ccf7a74533a99080988 (diff)
parent070e8ed18da9263f3b9aa0950accad7059778ab7 (diff)
downloadrust-de392c7d31602ddf0fae1143c5ad822a1abe89df.tar.gz
rust-de392c7d31602ddf0fae1143c5ad822a1abe89df.zip
Auto merge of #95944 - Dylan-DPC:rollup-idggkrh, r=Dylan-DPC
Rollup of 7 pull requests

Successful merges:

 - #95008 ([`let_chains`] Forbid `let` inside parentheses)
 - #95801 (Replace RwLock by a futex based one on Linux)
 - #95864 (Fix miscompilation of inline assembly with outputs in cases where we emit an invoke instead of call instruction.)
 - #95894 (Fix formatting error in pin.rs docs)
 - #95895 (Clarify str::from_utf8_unchecked's invariants)
 - #95901 (Remove duplicate aliases for `check codegen_{cranelift,gcc}` and fix `build codegen_gcc`)
 - #95927 (CI: do not compile libcore twice when performing LLVM PGO)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs54
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs5
-rw-r--r--library/core/src/pin.rs2
-rw-r--r--library/core/src/str/converts.rs6
-rw-r--r--library/std/src/sys/unix/futex.rs20
-rw-r--r--library/std/src/sys/unix/locks/futex_rwlock.rs313
-rw-r--r--library/std/src/sys/unix/locks/mod.rs4
-rw-r--r--src/bootstrap/check.rs7
-rw-r--r--src/bootstrap/compile.rs2
-rwxr-xr-xsrc/ci/pgo.sh6
-rw-r--r--src/test/codegen/asm-may_unwind.rs17
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs102
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr781
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr1
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/feature-gate.rs50
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr236
16 files changed, 1104 insertions, 502 deletions
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index a7c600fff78..33727084ccf 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -120,12 +120,21 @@ impl<'a> AstValidator<'a> {
             let err = "`let` expressions are not supported here";
             let mut diag = sess.struct_span_err(expr.span, err);
             diag.note("only supported directly in conditions of `if` and `while` expressions");
-            diag.note("as well as when nested within `&&` and parentheses in those conditions");
-            if let ForbiddenLetReason::ForbiddenWithOr(span) = forbidden_let_reason {
-                diag.span_note(
-                    span,
-                    "`||` operators are not currently supported in let chain expressions",
-                );
+            match forbidden_let_reason {
+                ForbiddenLetReason::GenericForbidden => {}
+                ForbiddenLetReason::NotSupportedOr(span) => {
+                    diag.span_note(
+                        span,
+                        "`||` operators are not supported in let chain expressions",
+                    );
+                }
+                ForbiddenLetReason::NotSupportedParentheses(span) => {
+                    diag.span_note(
+                        span,
+                        "`let`s wrapped in parentheses are not supported in a context with let \
+                        chains",
+                    );
+                }
             }
             diag.emit();
         } else {
@@ -1009,9 +1018,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         self.with_let_management(Some(ForbiddenLetReason::GenericForbidden), |this, forbidden_let_reason| {
             match &expr.kind {
                 ExprKind::Binary(Spanned { node: BinOpKind::Or, span }, lhs, rhs) => {
-                    let forbidden_let_reason = Some(ForbiddenLetReason::ForbiddenWithOr(*span));
-                    this.with_let_management(forbidden_let_reason, |this, _| this.visit_expr(lhs));
-                    this.with_let_management(forbidden_let_reason, |this, _| this.visit_expr(rhs));
+                    let local_reason = Some(ForbiddenLetReason::NotSupportedOr(*span));
+                    this.with_let_management(local_reason, |this, _| this.visit_expr(lhs));
+                    this.with_let_management(local_reason, |this, _| this.visit_expr(rhs));
                 }
                 ExprKind::If(cond, then, opt_else) => {
                     this.visit_block(then);
@@ -1036,7 +1045,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         }
                     }
                 }
-                ExprKind::Paren(_) | ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => {
+                ExprKind::Paren(local_expr) => {
+                    fn has_let_expr(expr: &Expr) -> bool {
+                        match expr.kind {
+                            ExprKind::Binary(_, ref lhs, ref rhs) => has_let_expr(lhs) || has_let_expr(rhs),
+                            ExprKind::Let(..) => true,
+                            _ => false,
+                        }
+                    }
+                    let local_reason = if has_let_expr(local_expr) {
+                        Some(ForbiddenLetReason::NotSupportedParentheses(local_expr.span))
+                    }
+                    else {
+                        forbidden_let_reason
+                    };
+                    this.with_let_management(local_reason, |this, _| this.visit_expr(local_expr));
+                }
+                ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => {
                     this.with_let_management(forbidden_let_reason, |this, _| visit::walk_expr(this, expr));
                     return;
                 }
@@ -1810,8 +1835,13 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
 /// Used to forbid `let` expressions in certain syntactic locations.
 #[derive(Clone, Copy)]
 enum ForbiddenLetReason {
-    /// A let chain with the `||` operator
-    ForbiddenWithOr(Span),
     /// `let` is not valid and the source environment is not important
     GenericForbidden,
+    /// A let chain with the `||` operator
+    NotSupportedOr(Span),
+    /// A let chain with invalid parentheses
+    ///
+    /// For exemple, `let 1 = 1 && (expr && expr)` is allowed
+    /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
+    NotSupportedParentheses(Span),
 }
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 03c390b4bd4..91d132eb343 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -290,6 +290,11 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
         }
         attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs });
 
+        // Switch to the 'normal' basic block if we did an `invoke` instead of a `call`
+        if let Some((dest, _, _)) = dest_catch_funclet {
+            self.switch_to_block(dest);
+        }
+
         // Write results to outputs
         for (idx, op) in operands.iter().enumerate() {
             if let InlineAsmOperandRef::Out { reg, place: Some(place), .. }
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index cef6a68b4d3..720317b05e0 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -175,7 +175,7 @@
 //! relies on pinning requires unsafe code, but be aware that deciding to make
 //! use of pinning in your type (for example by implementing some operation on
 //! <code>[Pin]<[&]Self></code> or <code>[Pin]<[&mut] Self></code>) has consequences for your
-//! [`Drop`][Drop]implementation as well: if an element of your type could have been pinned,
+//! [`Drop`][Drop] implementation as well: if an element of your type could have been pinned,
 //! you must treat [`Drop`][Drop] as implicitly taking <code>[Pin]<[&mut] Self></code>.
 //!
 //! For example, you could implement [`Drop`][Drop] as follows:
diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs
index ef26cbfb640..81b1db4ac6f 100644
--- a/library/core/src/str/converts.rs
+++ b/library/core/src/str/converts.rs
@@ -144,11 +144,7 @@ pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
 ///
 /// # Safety
 ///
-/// This function is unsafe because it does not check that the bytes passed to
-/// it are valid UTF-8. If this constraint is violated, undefined behavior
-/// results, as the rest of Rust assumes that [`&str`]s are valid UTF-8.
-///
-/// [`&str`]: str
+/// The bytes passed in must be valid UTF-8.
 ///
 /// # Examples
 ///
diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs
index c61d948fb60..b45d1c0149c 100644
--- a/library/std/src/sys/unix/futex.rs
+++ b/library/std/src/sys/unix/futex.rs
@@ -7,6 +7,11 @@
 use crate::sync::atomic::AtomicI32;
 use crate::time::Duration;
 
+/// Wait for a futex_wake operation to wake us.
+///
+/// Returns directly if the futex doesn't hold the expected value.
+///
+/// Returns false on timeout, and true in all other cases.
 #[cfg(any(target_os = "linux", target_os = "android"))]
 pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) -> bool {
     use super::time::Timespec;
@@ -68,18 +73,23 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) {
     }
 }
 
+/// Wake up one thread that's blocked on futex_wait on this futex.
+///
+/// Returns true if this actually woke up such a thread,
+/// or false if no thread was waiting on this futex.
 #[cfg(any(target_os = "linux", target_os = "android"))]
-pub fn futex_wake(futex: &AtomicI32) {
+pub fn futex_wake(futex: &AtomicI32) -> bool {
     unsafe {
         libc::syscall(
             libc::SYS_futex,
             futex as *const AtomicI32,
             libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG,
             1,
-        );
+        ) > 0
     }
 }
 
+/// Wake up all threads that are waiting on futex_wait on this futex.
 #[cfg(any(target_os = "linux", target_os = "android"))]
 pub fn futex_wake_all(futex: &AtomicI32) {
     unsafe {
@@ -93,12 +103,10 @@ pub fn futex_wake_all(futex: &AtomicI32) {
 }
 
 #[cfg(target_os = "emscripten")]
-pub fn futex_wake(futex: &AtomicI32) {
+pub fn futex_wake(futex: &AtomicI32) -> bool {
     extern "C" {
         fn emscripten_futex_wake(addr: *const AtomicI32, count: libc::c_int) -> libc::c_int;
     }
 
-    unsafe {
-        emscripten_futex_wake(futex as *const AtomicI32, 1);
-    }
+    unsafe { emscripten_futex_wake(futex as *const AtomicI32, 1) > 0 }
 }
diff --git a/library/std/src/sys/unix/locks/futex_rwlock.rs b/library/std/src/sys/unix/locks/futex_rwlock.rs
new file mode 100644
index 00000000000..aa16da97e4c
--- /dev/null
+++ b/library/std/src/sys/unix/locks/futex_rwlock.rs
@@ -0,0 +1,313 @@
+use crate::sync::atomic::{
+    AtomicI32,
+    Ordering::{Acquire, Relaxed, Release},
+};
+use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all};
+
+pub type MovableRwLock = RwLock;
+
+pub struct RwLock {
+    // The state consists of a 30-bit reader counter, a 'readers waiting' flag, and a 'writers waiting' flag.
+    // Bits 0..30:
+    //   0: Unlocked
+    //   1..=0x3FFF_FFFE: Locked by N readers
+    //   0x3FFF_FFFF: Write locked
+    // Bit 30: Readers are waiting on this futex.
+    // Bit 31: Writers are waiting on the writer_notify futex.
+    state: AtomicI32,
+    // The 'condition variable' to notify writers through.
+    // Incremented on every signal.
+    writer_notify: AtomicI32,
+}
+
+const READ_LOCKED: i32 = 1;
+const MASK: i32 = (1 << 30) - 1;
+const WRITE_LOCKED: i32 = MASK;
+const MAX_READERS: i32 = MASK - 1;
+const READERS_WAITING: i32 = 1 << 30;
+const WRITERS_WAITING: i32 = 1 << 31;
+
+fn is_unlocked(state: i32) -> bool {
+    state & MASK == 0
+}
+
+fn is_write_locked(state: i32) -> bool {
+    state & MASK == WRITE_LOCKED
+}
+
+fn has_readers_waiting(state: i32) -> bool {
+    state & READERS_WAITING != 0
+}
+
+fn has_writers_waiting(state: i32) -> bool {
+    state & WRITERS_WAITING != 0
+}
+
+fn is_read_lockable(state: i32) -> bool {
+    // This also returns false if the counter could overflow if we tried to read lock it.
+    //
+    // We don't allow read-locking if there's readers waiting, even if the lock is unlocked
+    // and there's no writers waiting. The only situation when this happens is after unlocking,
+    // at which point the unlocking thread might be waking up writers, which have priority over readers.
+    // The unlocking thread will clear the readers waiting bit and wake up readers, if necssary.
+    state & MASK < MAX_READERS && !has_readers_waiting(state) && !has_writers_waiting(state)
+}
+
+fn has_reached_max_readers(state: i32) -> bool {
+    state & MASK == MAX_READERS
+}
+
+impl RwLock {
+    #[inline]
+    pub const fn new() -> Self {
+        Self { state: AtomicI32::new(0), writer_notify: AtomicI32::new(0) }
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {}
+
+    #[inline]
+    pub unsafe fn try_read(&self) -> bool {
+        self.state
+            .fetch_update(Acquire, Relaxed, |s| is_read_lockable(s).then(|| s + READ_LOCKED))
+            .is_ok()
+    }
+
+    #[inline]
+    pub unsafe fn read(&self) {
+        let state = self.state.load(Relaxed);
+        if !is_read_lockable(state)
+            || self
+                .state
+                .compare_exchange_weak(state, state + READ_LOCKED, Acquire, Relaxed)
+                .is_err()
+        {
+            self.read_contended();
+        }
+    }
+
+    #[inline]
+    pub unsafe fn read_unlock(&self) {
+        let state = self.state.fetch_sub(READ_LOCKED, Release) - READ_LOCKED;
+
+        // It's impossible for a reader to be waiting on a read-locked RwLock,
+        // except if there is also a writer waiting.
+        debug_assert!(!has_readers_waiting(state) || has_writers_waiting(state));
+
+        // Wake up a writer if we were the last reader and there's a writer waiting.
+        if is_unlocked(state) && has_writers_waiting(state) {
+            self.wake_writer_or_readers(state);
+        }
+    }
+
+    #[cold]
+    fn read_contended(&self) {
+        let mut state = self.spin_read();
+
+        loop {
+            // If we can lock it, lock it.
+            if is_read_lockable(state) {
+                match self.state.compare_exchange_weak(state, state + READ_LOCKED, Acquire, Relaxed)
+                {
+                    Ok(_) => return, // Locked!
+                    Err(s) => {
+                        state = s;
+                        continue;
+                    }
+                }
+            }
+
+            // Check for overflow.
+            if has_reached_max_readers(state) {
+                panic!("too many active read locks on RwLock");
+            }
+
+            // Make sure the readers waiting bit is set before we go to sleep.
+            if !has_readers_waiting(state) {
+                if let Err(s) =
+                    self.state.compare_exchange(state, state | READERS_WAITING, Relaxed, Relaxed)
+                {
+                    state = s;
+                    continue;
+                }
+            }
+
+            // Wait for the state to change.
+            futex_wait(&self.state, state | READERS_WAITING, None);
+
+            // Spin again after waking up.
+            state = self.spin_read();
+        }
+    }
+
+    #[inline]
+    pub unsafe fn try_write(&self) -> bool {
+        self.state
+            .fetch_update(Acquire, Relaxed, |s| is_unlocked(s).then(|| s + WRITE_LOCKED))
+            .is_ok()
+    }
+
+    #[inline]
+    pub unsafe fn write(&self) {
+        if self.state.compare_exchange_weak(0, WRITE_LOCKED, Acquire, Relaxed).is_err() {
+            self.write_contended();
+        }
+    }
+
+    #[inline]
+    pub unsafe fn write_unlock(&self) {
+        let state = self.state.fetch_sub(WRITE_LOCKED, Release) - WRITE_LOCKED;
+
+        debug_assert!(is_unlocked(state));
+
+        if has_writers_waiting(state) || has_readers_waiting(state) {
+            self.wake_writer_or_readers(state);
+        }
+    }
+
+    #[cold]
+    fn write_contended(&self) {
+        let mut state = self.spin_write();
+
+        let mut other_writers_waiting = 0;
+
+        loop {
+            // If it's unlocked, we try to lock it.
+            if is_unlocked(state) {
+                match self.state.compare_exchange_weak(
+                    state,
+                    state | WRITE_LOCKED | other_writers_waiting,
+                    Acquire,
+                    Relaxed,
+                ) {
+                    Ok(_) => return, // Locked!
+                    Err(s) => {
+                        state = s;
+                        continue;
+                    }
+                }
+            }
+
+            // Set the waiting bit indicating that we're waiting on it.
+            if !has_writers_waiting(state) {
+                if let Err(s) =
+                    self.state.compare_exchange(state, state | WRITERS_WAITING, Relaxed, Relaxed)
+                {
+                    state = s;
+                    continue;
+                }
+            }
+
+            // Other writers might be waiting now too, so we should make sure
+            // we keep that bit on once we manage lock it.
+            other_writers_waiting = WRITERS_WAITING;
+
+            // Examine the notification counter before we check if `state` has changed,
+            // to make sure we don't miss any notifications.
+            let seq = self.writer_notify.load(Acquire);
+
+            // Don't go to sleep if the lock has become available,
+            // or if the writers waiting bit is no longer set.
+            let s = self.state.load(Relaxed);
+            if is_unlocked(state) || !has_writers_waiting(s) {
+                state = s;
+                continue;
+            }
+
+            // Wait for the state to change.
+            futex_wait(&self.writer_notify, seq, None);
+
+            // Spin again after waking up.
+            state = self.spin_write();
+        }
+    }
+
+    /// Wake up waiting threads after unlocking.
+    ///
+    /// If both are waiting, this will wake up only one writer, but will fall
+    /// back to waking up readers if there was no writer to wake up.
+    #[cold]
+    fn wake_writer_or_readers(&self, mut state: i32) {
+        assert!(is_unlocked(state));
+
+        // The readers waiting bit might be turned on at any point now,
+        // since readers will block when there's anything waiting.
+        // Writers will just lock the lock though, regardless of the waiting bits,
+        // so we don't have to worry about the writer waiting bit.
+        //
+        // If the lock gets locked in the meantime, we don't have to do
+        // anything, because then the thread that locked the lock will take
+        // care of waking up waiters when it unlocks.
+
+        // If only writers are waiting, wake one of them up.
+        if state == WRITERS_WAITING {
+            match self.state.compare_exchange(state, 0, Relaxed, Relaxed) {
+                Ok(_) => {
+                    self.wake_writer();
+                    return;
+                }
+                Err(s) => {
+                    // Maybe some readers are now waiting too. So, continue to the next `if`.
+                    state = s;
+                }
+            }
+        }
+
+        // If both writers and readers are waiting, leave the readers waiting
+        // and only wake up one writer.
+        if state == READERS_WAITING + WRITERS_WAITING {
+            if self.state.compare_exchange(state, READERS_WAITING, Relaxed, Relaxed).is_err() {
+                // The lock got locked. Not our problem anymore.
+                return;
+            }
+            if self.wake_writer() {
+                return;
+            }
+            // No writers were actually blocked on futex_wait, so we continue
+            // to wake up readers instead, since we can't be sure if we notified a writer.
+            state = READERS_WAITING;
+        }
+
+        // If readers are waiting, wake them all up.
+        if state == READERS_WAITING {
+            if self.state.compare_exchange(state, 0, Relaxed, Relaxed).is_ok() {
+                futex_wake_all(&self.state);
+            }
+        }
+    }
+
+    /// This wakes one writer and returns true if we woke up a writer that was
+    /// blocked on futex_wait.
+    ///
+    /// If this returns false, it might still be the case that we notified a
+    /// writer that was about to go to sleep.
+    fn wake_writer(&self) -> bool {
+        self.writer_notify.fetch_add(1, Release);
+        futex_wake(&self.writer_notify)
+    }
+
+    /// Spin for a while, but stop directly at the given condition.
+    fn spin_until(&self, f: impl Fn(i32) -> bool) -> i32 {
+        let mut spin = 100; // Chosen by fair dice roll.
+        loop {
+            let state = self.state.load(Relaxed);
+            if f(state) || spin == 0 {
+                return state;
+            }
+            crate::hint::spin_loop();
+            spin -= 1;
+        }
+    }
+
+    fn spin_write(&self) -> i32 {
+        // Stop spinning when it's unlocked or when there's waiting writers, to keep things somewhat fair.
+        self.spin_until(|state| is_unlocked(state) || has_writers_waiting(state))
+    }
+
+    fn spin_read(&self) -> i32 {
+        // Stop spinning when it's unlocked or read locked, or when there's waiting threads.
+        self.spin_until(|state| {
+            !is_write_locked(state) || has_readers_waiting(state) || has_writers_waiting(state)
+        })
+    }
+}
diff --git a/library/std/src/sys/unix/locks/mod.rs b/library/std/src/sys/unix/locks/mod.rs
index 2b8dd168068..85afc939d2e 100644
--- a/library/std/src/sys/unix/locks/mod.rs
+++ b/library/std/src/sys/unix/locks/mod.rs
@@ -4,13 +4,13 @@ cfg_if::cfg_if! {
         target_os = "android",
     ))] {
         mod futex;
+        mod futex_rwlock;
         #[allow(dead_code)]
         mod pthread_mutex; // Only used for PthreadMutexAttr, needed by pthread_remutex.
         mod pthread_remutex; // FIXME: Implement this using a futex
-        mod pthread_rwlock; // FIXME: Implement this using a futex
         pub use futex::{Mutex, MovableMutex, Condvar, MovableCondvar};
         pub use pthread_remutex::ReentrantMutex;
-        pub use pthread_rwlock::{RwLock, MovableRwLock};
+        pub use futex_rwlock::{RwLock, MovableRwLock};
     } else {
         mod pthread_mutex;
         mod pthread_remutex;
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 28e7f1fdca7..432a6c34ed5 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -243,12 +243,7 @@ impl Step for CodegenBackend {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.paths(&[
-            "compiler/rustc_codegen_cranelift",
-            "rustc_codegen_cranelift",
-            "compiler/rustc_codegen_gcc",
-            "rustc_codegen_gcc",
-        ])
+        run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
     }
 
     fn make_run(run: RunConfig<'_>) {
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index afc333b5048..45991381dc0 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -795,7 +795,7 @@ impl Step for CodegenBackend {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("compiler/rustc_codegen_cranelift")
+        run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
     }
 
     fn make_run(run: RunConfig<'_>) {
diff --git a/src/ci/pgo.sh b/src/ci/pgo.sh
index 689e6a11d61..691d1282cf4 100755
--- a/src/ci/pgo.sh
+++ b/src/ci/pgo.sh
@@ -47,12 +47,6 @@ python3 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \
     --stage 2 library/std \
     --llvm-profile-generate
 
-# Profile libcore compilation in opt-level=0 and opt-level=3
-RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc \
-    --edition=2021 --crate-type=lib ../library/core/src/lib.rs
-RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc \
-    --edition=2021 --crate-type=lib -Copt-level=3 ../library/core/src/lib.rs
-
 # Compile rustc perf
 cp -r /tmp/rustc-perf ./
 chown -R $(whoami): ./rustc-perf
diff --git a/src/test/codegen/asm-may_unwind.rs b/src/test/codegen/asm-may_unwind.rs
index 3b34d79c3a9..bf4202764a7 100644
--- a/src/test/codegen/asm-may_unwind.rs
+++ b/src/test/codegen/asm-may_unwind.rs
@@ -18,10 +18,23 @@ impl Drop for Foo {
     }
 }
 
-// CHECK-LABEL: @may_unwind
+// CHECK-LABEL: @asm_may_unwind
 #[no_mangle]
-pub unsafe fn may_unwind() {
+pub unsafe fn asm_may_unwind() {
     let _m = Foo;
     // CHECK: invoke void asm sideeffect alignstack inteldialect unwind ""
     asm!("", options(may_unwind));
 }
+
+// CHECK-LABEL: @asm_with_result_may_unwind
+#[no_mangle]
+pub unsafe fn asm_with_result_may_unwind() -> u64 {
+    let _m = Foo;
+    let res: u64;
+    // CHECK: [[RES:%[0-9]+]] = invoke i64 asm sideeffect alignstack inteldialect unwind
+    // CHECK-NEXT: to label %[[NORMALBB:[a-b0-9]+]]
+    asm!("mov {}, 1", out(reg) res, options(may_unwind));
+    // CHECK: [[NORMALBB]]:
+    // CHECK: ret i64 [[RES:%[0-9]+]]
+    res
+}
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs
index 5b2693d07a7..1bd8b74240e 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs
@@ -25,6 +25,67 @@ use std::ops::Range;
 
 fn main() {}
 
+fn _if() {
+    if (let 0 = 1) {}
+    //~^ ERROR `let` expressions are not supported here
+
+    if (((let 0 = 1))) {}
+    //~^ ERROR `let` expressions are not supported here
+
+    if (let 0 = 1) && true {}
+    //~^ ERROR `let` expressions are not supported here
+
+    if true && (let 0 = 1) {}
+    //~^ ERROR `let` expressions are not supported here
+
+    if (let 0 = 1) && (let 0 = 1) {}
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
+
+    if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
+}
+
+fn _while() {
+    while (let 0 = 1) {}
+    //~^ ERROR `let` expressions are not supported here
+
+    while (((let 0 = 1))) {}
+    //~^ ERROR `let` expressions are not supported here
+
+    while (let 0 = 1) && true {}
+    //~^ ERROR `let` expressions are not supported here
+
+    while true && (let 0 = 1) {}
+    //~^ ERROR `let` expressions are not supported here
+
+    while (let 0 = 1) && (let 0 = 1) {}
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
+
+    while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
+}
+
+fn _macros() {
+    macro_rules! use_expr {
+        ($e:expr) => {
+            if $e {}
+            while $e {}
+        }
+    }
+    use_expr!((let 0 = 1 && 0 == 0));
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
+    use_expr!((let 0 = 1));
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
+}
+
 fn nested_within_if_expr() {
     if &let 0 = 0 {} //~ ERROR `let` expressions are not supported here
     //~^ ERROR mismatched types
@@ -234,3 +295,44 @@ fn inside_const_generic_arguments() {
         //~| ERROR  expressions must be enclosed in braces
     >::O == 5 {}
 }
+
+fn with_parenthesis() {
+    let opt = Some(Some(1i32));
+
+    if (let Some(a) = opt && true) {
+    //~^ ERROR `let` expressions are not supported here
+    }
+
+    if (let Some(a) = opt) && true {
+    //~^ ERROR `let` expressions are not supported here
+    }
+    if (let Some(a) = opt) && (let Some(b) = a) {
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
+    }
+    if let Some(a) = opt && (true && true) {
+    }
+
+    if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
+    }
+    if (let Some(a) = opt && (let Some(b) = a)) && true {
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
+    }
+    if (let Some(a) = opt && (true)) && true {
+    //~^ ERROR `let` expressions are not supported here
+    }
+
+    if (true && (true)) && let Some(a) = opt {
+    }
+    if (true) && let Some(a) = opt {
+    }
+    if true && let Some(a) = opt {
+    }
+
+    let fun = || true;
+    if let true = (true && fun()) && (true) {
+    }
+}
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
index 34f059248b6..00da9d26057 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -1,5 +1,5 @@
 error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/disallowed-positions.rs:232:9
+  --> $DIR/disallowed-positions.rs:293:9
    |
 LL |         true && let 1 = 1
    |         ^^^^^^^^^^^^^^^^^
@@ -12,555 +12,968 @@ LL |         { true && let 1 = 1 }
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:29:9
    |
+LL |     if (let 0 = 1) {}
+   |         ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:29:9
+   |
+LL |     if (let 0 = 1) {}
+   |         ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:32:11
+   |
+LL |     if (((let 0 = 1))) {}
+   |           ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:32:11
+   |
+LL |     if (((let 0 = 1))) {}
+   |           ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:35:9
+   |
+LL |     if (let 0 = 1) && true {}
+   |         ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:35:9
+   |
+LL |     if (let 0 = 1) && true {}
+   |         ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:38:17
+   |
+LL |     if true && (let 0 = 1) {}
+   |                 ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:38:17
+   |
+LL |     if true && (let 0 = 1) {}
+   |                 ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:41:9
+   |
+LL |     if (let 0 = 1) && (let 0 = 1) {}
+   |         ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:41:9
+   |
+LL |     if (let 0 = 1) && (let 0 = 1) {}
+   |         ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:41:24
+   |
+LL |     if (let 0 = 1) && (let 0 = 1) {}
+   |                        ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:41:24
+   |
+LL |     if (let 0 = 1) && (let 0 = 1) {}
+   |                        ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:45:35
+   |
+LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                   ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:45:35
+   |
+LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:45:48
+   |
+LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:45:35
+   |
+LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:45:61
+   |
+LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                                             ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:45:35
+   |
+LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:52:12
+   |
+LL |     while (let 0 = 1) {}
+   |            ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:52:12
+   |
+LL |     while (let 0 = 1) {}
+   |            ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:55:14
+   |
+LL |     while (((let 0 = 1))) {}
+   |              ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:55:14
+   |
+LL |     while (((let 0 = 1))) {}
+   |              ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:58:12
+   |
+LL |     while (let 0 = 1) && true {}
+   |            ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:58:12
+   |
+LL |     while (let 0 = 1) && true {}
+   |            ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:61:20
+   |
+LL |     while true && (let 0 = 1) {}
+   |                    ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:61:20
+   |
+LL |     while true && (let 0 = 1) {}
+   |                    ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:64:12
+   |
+LL |     while (let 0 = 1) && (let 0 = 1) {}
+   |            ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:64:12
+   |
+LL |     while (let 0 = 1) && (let 0 = 1) {}
+   |            ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:64:27
+   |
+LL |     while (let 0 = 1) && (let 0 = 1) {}
+   |                           ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:64:27
+   |
+LL |     while (let 0 = 1) && (let 0 = 1) {}
+   |                           ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:68:38
+   |
+LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                      ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:68:38
+   |
+LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:68:51
+   |
+LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                                   ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:68:38
+   |
+LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:68:64
+   |
+LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                                                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:68:38
+   |
+LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:81:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:81:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:81:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:81:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:84:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:84:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:84:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:84:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:90:9
+   |
 LL |     if &let 0 = 0 {}
    |         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:32:9
+  --> $DIR/disallowed-positions.rs:93:9
    |
 LL |     if !let 0 = 0 {}
    |         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:33:9
+  --> $DIR/disallowed-positions.rs:94:9
    |
 LL |     if *let 0 = 0 {}
    |         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:35:9
+  --> $DIR/disallowed-positions.rs:96:9
    |
 LL |     if -let 0 = 0 {}
    |         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:43:9
+  --> $DIR/disallowed-positions.rs:104:9
    |
 LL |     if (let 0 = 0)? {}
    |         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:104:9
+   |
+LL |     if (let 0 = 0)? {}
+   |         ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:47:16
+  --> $DIR/disallowed-positions.rs:108:16
    |
 LL |     if true || let 0 = 0 {}
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not currently supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:47:13
+note: `||` operators are not supported in let chain expressions
+  --> $DIR/disallowed-positions.rs:108:13
    |
 LL |     if true || let 0 = 0 {}
    |             ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:48:17
+  --> $DIR/disallowed-positions.rs:109:17
    |
 LL |     if (true || let 0 = 0) {}
    |                 ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not currently supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:48:14
+note: `||` operators are not supported in let chain expressions
+  --> $DIR/disallowed-positions.rs:109:14
    |
 LL |     if (true || let 0 = 0) {}
    |              ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:49:25
+  --> $DIR/disallowed-positions.rs:110:25
    |
 LL |     if true && (true || let 0 = 0) {}
    |                         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not currently supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:49:22
+note: `||` operators are not supported in let chain expressions
+  --> $DIR/disallowed-positions.rs:110:22
    |
 LL |     if true && (true || let 0 = 0) {}
    |                      ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:50:25
+  --> $DIR/disallowed-positions.rs:111:25
    |
 LL |     if true || (true && let 0 = 0) {}
    |                         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not currently supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:50:13
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:111:17
    |
 LL |     if true || (true && let 0 = 0) {}
-   |             ^^
+   |                 ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:53:12
+  --> $DIR/disallowed-positions.rs:114:12
    |
 LL |     if x = let 0 = 0 {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:56:15
+  --> $DIR/disallowed-positions.rs:117:15
    |
 LL |     if true..(let 0 = 0) {}
    |               ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:117:15
+   |
+LL |     if true..(let 0 = 0) {}
+   |               ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:58:11
+  --> $DIR/disallowed-positions.rs:119:11
    |
 LL |     if ..(let 0 = 0) {}
    |           ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:119:11
+   |
+LL |     if ..(let 0 = 0) {}
+   |           ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:60:9
+  --> $DIR/disallowed-positions.rs:121:9
    |
 LL |     if (let 0 = 0).. {}
    |         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:121:9
+   |
+LL |     if (let 0 = 0).. {}
+   |         ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:64:8
+  --> $DIR/disallowed-positions.rs:125:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:68:8
+  --> $DIR/disallowed-positions.rs:129:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:75:8
+  --> $DIR/disallowed-positions.rs:136:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:83:8
+  --> $DIR/disallowed-positions.rs:144:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:89:19
+  --> $DIR/disallowed-positions.rs:150:19
    |
 LL |     if let true = let true = true {}
    |                   ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:93:12
+  --> $DIR/disallowed-positions.rs:154:12
    |
 LL |     while &let 0 = 0 {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:96:12
+  --> $DIR/disallowed-positions.rs:157:12
    |
 LL |     while !let 0 = 0 {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:97:12
+  --> $DIR/disallowed-positions.rs:158:12
    |
 LL |     while *let 0 = 0 {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:99:12
+  --> $DIR/disallowed-positions.rs:160:12
    |
 LL |     while -let 0 = 0 {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:107:12
+  --> $DIR/disallowed-positions.rs:168:12
    |
 LL |     while (let 0 = 0)? {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:168:12
+   |
+LL |     while (let 0 = 0)? {}
+   |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:111:19
+  --> $DIR/disallowed-positions.rs:172:19
    |
 LL |     while true || let 0 = 0 {}
    |                   ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not currently supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:111:16
+note: `||` operators are not supported in let chain expressions
+  --> $DIR/disallowed-positions.rs:172:16
    |
 LL |     while true || let 0 = 0 {}
    |                ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:112:20
+  --> $DIR/disallowed-positions.rs:173:20
    |
 LL |     while (true || let 0 = 0) {}
    |                    ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not currently supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:112:17
+note: `||` operators are not supported in let chain expressions
+  --> $DIR/disallowed-positions.rs:173:17
    |
 LL |     while (true || let 0 = 0) {}
    |                 ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:113:28
+  --> $DIR/disallowed-positions.rs:174:28
    |
 LL |     while true && (true || let 0 = 0) {}
    |                            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not currently supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:113:25
+note: `||` operators are not supported in let chain expressions
+  --> $DIR/disallowed-positions.rs:174:25
    |
 LL |     while true && (true || let 0 = 0) {}
    |                         ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:114:28
+  --> $DIR/disallowed-positions.rs:175:28
    |
 LL |     while true || (true && let 0 = 0) {}
    |                            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not currently supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:114:16
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:175:20
    |
 LL |     while true || (true && let 0 = 0) {}
-   |                ^^
+   |                    ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:117:15
+  --> $DIR/disallowed-positions.rs:178:15
    |
 LL |     while x = let 0 = 0 {}
    |               ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:120:18
+  --> $DIR/disallowed-positions.rs:181:18
    |
 LL |     while true..(let 0 = 0) {}
    |                  ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:181:18
+   |
+LL |     while true..(let 0 = 0) {}
+   |                  ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:122:14
+  --> $DIR/disallowed-positions.rs:183:14
    |
 LL |     while ..(let 0 = 0) {}
    |              ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:183:14
+   |
+LL |     while ..(let 0 = 0) {}
+   |              ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:124:12
+  --> $DIR/disallowed-positions.rs:185:12
    |
 LL |     while (let 0 = 0).. {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:185:12
+   |
+LL |     while (let 0 = 0).. {}
+   |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:128:11
+  --> $DIR/disallowed-positions.rs:189:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:132:11
+  --> $DIR/disallowed-positions.rs:193:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:139:11
+  --> $DIR/disallowed-positions.rs:200:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:147:11
+  --> $DIR/disallowed-positions.rs:208:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:153:22
+  --> $DIR/disallowed-positions.rs:214:22
    |
 LL |     while let true = let true = true {}
    |                      ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:167:6
+  --> $DIR/disallowed-positions.rs:228:6
    |
 LL |     &let 0 = 0;
    |      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:169:6
+  --> $DIR/disallowed-positions.rs:230:6
    |
 LL |     !let 0 = 0;
    |      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:170:6
+  --> $DIR/disallowed-positions.rs:231:6
    |
 LL |     *let 0 = 0;
    |      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:172:6
+  --> $DIR/disallowed-positions.rs:233:6
    |
 LL |     -let 0 = 0;
    |      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:180:6
+  --> $DIR/disallowed-positions.rs:241:6
    |
 LL |     (let 0 = 0)?;
    |      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:241:6
+   |
+LL |     (let 0 = 0)?;
+   |      ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:184:13
+  --> $DIR/disallowed-positions.rs:245:13
    |
 LL |     true || let 0 = 0;
    |             ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not currently supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:184:10
+note: `||` operators are not supported in let chain expressions
+  --> $DIR/disallowed-positions.rs:245:10
    |
 LL |     true || let 0 = 0;
    |          ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:185:14
+  --> $DIR/disallowed-positions.rs:246:14
    |
 LL |     (true || let 0 = 0);
    |              ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not currently supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:185:11
+note: `||` operators are not supported in let chain expressions
+  --> $DIR/disallowed-positions.rs:246:11
    |
 LL |     (true || let 0 = 0);
    |           ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:186:22
+  --> $DIR/disallowed-positions.rs:247:22
    |
 LL |     true && (true || let 0 = 0);
    |                      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not currently supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:186:19
+note: `||` operators are not supported in let chain expressions
+  --> $DIR/disallowed-positions.rs:247:19
    |
 LL |     true && (true || let 0 = 0);
    |                   ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:189:9
+  --> $DIR/disallowed-positions.rs:250:9
    |
 LL |     x = let 0 = 0;
    |         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:191:12
+  --> $DIR/disallowed-positions.rs:252:12
    |
 LL |     true..(let 0 = 0);
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:252:12
+   |
+LL |     true..(let 0 = 0);
+   |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:192:8
+  --> $DIR/disallowed-positions.rs:253:8
    |
 LL |     ..(let 0 = 0);
    |        ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:253:8
+   |
+LL |     ..(let 0 = 0);
+   |        ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:193:6
+  --> $DIR/disallowed-positions.rs:254:6
    |
 LL |     (let 0 = 0)..;
    |      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:254:6
+   |
+LL |     (let 0 = 0)..;
+   |      ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:195:6
+  --> $DIR/disallowed-positions.rs:256:6
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:199:6
+  --> $DIR/disallowed-positions.rs:260:6
    |
 LL |     (let true = let true = true);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:260:6
+   |
+LL |     (let true = let true = true);
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:203:6
+  --> $DIR/disallowed-positions.rs:264:6
    |
 LL |     &let 0 = 0
    |      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:214:17
+  --> $DIR/disallowed-positions.rs:275:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:218:17
+  --> $DIR/disallowed-positions.rs:279:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:222:17
+  --> $DIR/disallowed-positions.rs:283:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:232:17
+  --> $DIR/disallowed-positions.rs:293:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:302:9
+   |
+LL |     if (let Some(a) = opt && true) {
+   |         ^^^^^^^^^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:302:9
+   |
+LL |     if (let Some(a) = opt && true) {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:306:9
+   |
+LL |     if (let Some(a) = opt) && true {
+   |         ^^^^^^^^^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:306:9
+   |
+LL |     if (let Some(a) = opt) && true {
+   |         ^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:309:9
+   |
+LL |     if (let Some(a) = opt) && (let Some(b) = a) {
+   |         ^^^^^^^^^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:309:9
+   |
+LL |     if (let Some(a) = opt) && (let Some(b) = a) {
+   |         ^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:309:32
+   |
+LL |     if (let Some(a) = opt) && (let Some(b) = a) {
+   |                                ^^^^^^^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:309:32
+   |
+LL |     if (let Some(a) = opt) && (let Some(b) = a) {
+   |                                ^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:316:9
+   |
+LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+   |         ^^^^^^^^^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:316:9
+   |
+LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:316:31
+   |
+LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+   |                               ^^^^^^^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:316:31
+   |
+LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+   |                               ^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:320:9
+   |
+LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
+   |         ^^^^^^^^^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:320:9
+   |
+LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:320:31
+   |
+LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
+   |                               ^^^^^^^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:320:31
+   |
+LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
+   |                               ^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/disallowed-positions.rs:324:9
+   |
+LL |     if (let Some(a) = opt && (true)) && true {
+   |         ^^^^^^^^^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/disallowed-positions.rs:324:9
+   |
+LL |     if (let Some(a) = opt && (true)) && true {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:29:8
+  --> $DIR/disallowed-positions.rs:90:8
    |
 LL |     if &let 0 = 0 {}
    |        ^^^^^^^^^^ expected `bool`, found `&bool`
@@ -572,19 +985,19 @@ LL +     if let 0 = 0 {}
    | 
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:33:8
+  --> $DIR/disallowed-positions.rs:94:8
    |
 LL |     if *let 0 = 0 {}
    |        ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:35:8
+  --> $DIR/disallowed-positions.rs:96:8
    |
 LL |     if -let 0 = 0 {}
    |        ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:43:8
+  --> $DIR/disallowed-positions.rs:104:8
    |
 LL |     if (let 0 = 0)? {}
    |        ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -592,7 +1005,7 @@ LL |     if (let 0 = 0)? {}
    = help: the trait `Try` is not implemented for `bool`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:43:19
+  --> $DIR/disallowed-positions.rs:104:19
    |
 LL | / fn nested_within_if_expr() {
 LL | |     if &let 0 = 0 {}
@@ -609,7 +1022,7 @@ LL | | }
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:53:8
+  --> $DIR/disallowed-positions.rs:114:8
    |
 LL |     if x = let 0 = 0 {}
    |        ^^^^^^^^^^^^^ expected `bool`, found `()`
@@ -620,7 +1033,7 @@ LL |     if x == let 0 = 0 {}
    |          ~~
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:56:8
+  --> $DIR/disallowed-positions.rs:117:8
    |
 LL |     if true..(let 0 = 0) {}
    |        ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -629,7 +1042,7 @@ LL |     if true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:58:8
+  --> $DIR/disallowed-positions.rs:119:8
    |
 LL |     if ..(let 0 = 0) {}
    |        ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
@@ -638,7 +1051,7 @@ LL |     if ..(let 0 = 0) {}
             found struct `RangeTo<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:60:8
+  --> $DIR/disallowed-positions.rs:121:8
    |
 LL |     if (let 0 = 0).. {}
    |        ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
@@ -647,7 +1060,7 @@ LL |     if (let 0 = 0).. {}
             found struct `RangeFrom<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:64:12
+  --> $DIR/disallowed-positions.rs:125:12
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -658,7 +1071,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:64:8
+  --> $DIR/disallowed-positions.rs:125:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -667,7 +1080,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:68:12
+  --> $DIR/disallowed-positions.rs:129:12
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -678,7 +1091,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:68:8
+  --> $DIR/disallowed-positions.rs:129:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -687,7 +1100,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:75:12
+  --> $DIR/disallowed-positions.rs:136:12
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
@@ -698,16 +1111,16 @@ LL |     if let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:75:41
+  --> $DIR/disallowed-positions.rs:136:41
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |                                         ^^^^^^^ expected `bool`, found closure
    |
    = note: expected type `bool`
-           found closure `[closure@$DIR/disallowed-positions.rs:75:41: 75:48]`
+           found closure `[closure@$DIR/disallowed-positions.rs:136:41: 136:48]`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:75:8
+  --> $DIR/disallowed-positions.rs:136:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -716,7 +1129,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:83:12
+  --> $DIR/disallowed-positions.rs:144:12
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -727,7 +1140,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:83:44
+  --> $DIR/disallowed-positions.rs:144:44
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |                                            ^^^^^^^ expected `bool`, found `&&bool`
@@ -739,7 +1152,7 @@ LL +     if let Range { start: true, end } = t..false {}
    | 
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:83:8
+  --> $DIR/disallowed-positions.rs:144:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -748,7 +1161,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<bool>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:39:20
+  --> $DIR/disallowed-positions.rs:100:20
    |
 LL |         if let 0 = 0? {}
    |                    ^^ the `?` operator cannot be applied to type `{integer}`
@@ -756,7 +1169,7 @@ LL |         if let 0 = 0? {}
    = help: the trait `Try` is not implemented for `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:93:11
+  --> $DIR/disallowed-positions.rs:154:11
    |
 LL |     while &let 0 = 0 {}
    |           ^^^^^^^^^^ expected `bool`, found `&bool`
@@ -768,19 +1181,19 @@ LL +     while let 0 = 0 {}
    | 
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:97:11
+  --> $DIR/disallowed-positions.rs:158:11
    |
 LL |     while *let 0 = 0 {}
    |           ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:99:11
+  --> $DIR/disallowed-positions.rs:160:11
    |
 LL |     while -let 0 = 0 {}
    |           ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:107:11
+  --> $DIR/disallowed-positions.rs:168:11
    |
 LL |     while (let 0 = 0)? {}
    |           ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -788,7 +1201,7 @@ LL |     while (let 0 = 0)? {}
    = help: the trait `Try` is not implemented for `bool`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:107:22
+  --> $DIR/disallowed-positions.rs:168:22
    |
 LL | / fn nested_within_while_expr() {
 LL | |     while &let 0 = 0 {}
@@ -805,7 +1218,7 @@ LL | | }
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:117:11
+  --> $DIR/disallowed-positions.rs:178:11
    |
 LL |     while x = let 0 = 0 {}
    |           ^^^^^^^^^^^^^ expected `bool`, found `()`
@@ -816,7 +1229,7 @@ LL |     while x == let 0 = 0 {}
    |             ~~
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:120:11
+  --> $DIR/disallowed-positions.rs:181:11
    |
 LL |     while true..(let 0 = 0) {}
    |           ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -825,7 +1238,7 @@ LL |     while true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:122:11
+  --> $DIR/disallowed-positions.rs:183:11
    |
 LL |     while ..(let 0 = 0) {}
    |           ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
@@ -834,7 +1247,7 @@ LL |     while ..(let 0 = 0) {}
             found struct `RangeTo<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:124:11
+  --> $DIR/disallowed-positions.rs:185:11
    |
 LL |     while (let 0 = 0).. {}
    |           ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
@@ -843,7 +1256,7 @@ LL |     while (let 0 = 0).. {}
             found struct `RangeFrom<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:128:15
+  --> $DIR/disallowed-positions.rs:189:15
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -854,7 +1267,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:128:11
+  --> $DIR/disallowed-positions.rs:189:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -863,7 +1276,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:132:15
+  --> $DIR/disallowed-positions.rs:193:15
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -874,7 +1287,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:132:11
+  --> $DIR/disallowed-positions.rs:193:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -883,7 +1296,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:139:15
+  --> $DIR/disallowed-positions.rs:200:15
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
@@ -894,16 +1307,16 @@ LL |     while let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:139:44
+  --> $DIR/disallowed-positions.rs:200:44
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |                                            ^^^^^^^ expected `bool`, found closure
    |
    = note: expected type `bool`
-           found closure `[closure@$DIR/disallowed-positions.rs:139:44: 139:51]`
+           found closure `[closure@$DIR/disallowed-positions.rs:200:44: 200:51]`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:139:11
+  --> $DIR/disallowed-positions.rs:200:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -912,7 +1325,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:147:15
+  --> $DIR/disallowed-positions.rs:208:15
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -923,7 +1336,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:147:47
+  --> $DIR/disallowed-positions.rs:208:47
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |                                               ^^^^^^^ expected `bool`, found `&&bool`
@@ -935,7 +1348,7 @@ LL +     while let Range { start: true, end } = t..false {}
    | 
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:147:11
+  --> $DIR/disallowed-positions.rs:208:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -944,7 +1357,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<bool>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:103:23
+  --> $DIR/disallowed-positions.rs:164:23
    |
 LL |         while let 0 = 0? {}
    |                       ^^ the `?` operator cannot be applied to type `{integer}`
@@ -952,19 +1365,19 @@ LL |         while let 0 = 0? {}
    = help: the trait `Try` is not implemented for `{integer}`
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:170:5
+  --> $DIR/disallowed-positions.rs:231:5
    |
 LL |     *let 0 = 0;
    |     ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:172:5
+  --> $DIR/disallowed-positions.rs:233:5
    |
 LL |     -let 0 = 0;
    |     ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:180:5
+  --> $DIR/disallowed-positions.rs:241:5
    |
 LL |     (let 0 = 0)?;
    |     ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -972,7 +1385,7 @@ LL |     (let 0 = 0)?;
    = help: the trait `Try` is not implemented for `bool`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:180:16
+  --> $DIR/disallowed-positions.rs:241:16
    |
 LL | / fn outside_if_and_while_expr() {
 LL | |     &let 0 = 0;
@@ -989,7 +1402,7 @@ LL | | }
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:195:10
+  --> $DIR/disallowed-positions.rs:256:10
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1000,7 +1413,7 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:203:5
+  --> $DIR/disallowed-positions.rs:264:5
    |
 LL | fn outside_if_and_while_expr() {
    |                                - help: try adding a return type: `-> &bool`
@@ -1009,14 +1422,14 @@ LL |     &let 0 = 0
    |     ^^^^^^^^^^ expected `()`, found `&bool`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:176:17
+  --> $DIR/disallowed-positions.rs:237:17
    |
 LL |         let 0 = 0?;
    |                 ^^ the `?` operator cannot be applied to type `{integer}`
    |
    = help: the trait `Try` is not implemented for `{integer}`
 
-error: aborting due to 103 previous errors
+error: aborting due to 134 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0600, E0614.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
index 992c34eb402..aebfc1a72b7 100644
--- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
@@ -72,7 +72,6 @@ LL |     let Some(n) = opt && let another = n else {
    |                          ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
-   = note: as well as when nested within `&&` and parentheses in those conditions
 
 error[E0308]: mismatched types
   --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19
diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
index 53fec8316e7..ac60bc7e57f 100644
--- a/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
@@ -11,35 +11,12 @@ use std::ops::Range;
 fn _if() {
     if let 0 = 1 {} // Stable!
 
-    if (let 0 = 1) {}
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
-
-    if (((let 0 = 1))) {}
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
-
     if true && let 0 = 1 {}
     //~^ ERROR `let` expressions in this position are unstable [E0658]
 
     if let 0 = 1 && true {}
     //~^ ERROR `let` expressions in this position are unstable [E0658]
 
-    if (let 0 = 1) && true {}
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
-
-    if true && (let 0 = 1) {}
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
-
-    if (let 0 = 1) && (let 0 = 1) {}
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
-    //~| ERROR `let` expressions in this position are unstable [E0658]
-
-    if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
-    //~| ERROR `let` expressions in this position are unstable [E0658]
-    //~| ERROR `let` expressions in this position are unstable [E0658]
-    //~| ERROR `let` expressions in this position are unstable [E0658]
-    //~| ERROR `let` expressions in this position are unstable [E0658]
-
     if let Range { start: _, end: _ } = (true..true) && false {}
     //~^ ERROR `let` expressions in this position are unstable [E0658]
 }
@@ -47,35 +24,12 @@ fn _if() {
 fn _while() {
     while let 0 = 1 {} // Stable!
 
-    while (let 0 = 1) {}
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
-
-    while (((let 0 = 1))) {}
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
-
     while true && let 0 = 1 {}
     //~^ ERROR `let` expressions in this position are unstable [E0658]
 
     while let 0 = 1 && true {}
     //~^ ERROR `let` expressions in this position are unstable [E0658]
 
-    while (let 0 = 1) && true {}
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
-
-    while true && (let 0 = 1) {}
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
-
-    while (let 0 = 1) && (let 0 = 1) {}
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
-    //~| ERROR `let` expressions in this position are unstable [E0658]
-
-    while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
-    //~| ERROR `let` expressions in this position are unstable [E0658]
-    //~| ERROR `let` expressions in this position are unstable [E0658]
-    //~| ERROR `let` expressions in this position are unstable [E0658]
-    //~| ERROR `let` expressions in this position are unstable [E0658]
-
     while let Range { start: _, end: _ } = (true..true) && false {}
     //~^ ERROR `let` expressions in this position are unstable [E0658]
 }
@@ -92,10 +46,6 @@ fn _macros() {
             while $e {}
         }
     }
-    use_expr!((let 0 = 1 && 0 == 0));
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
-    use_expr!((let 0 = 1));
-    //~^ ERROR `let` expressions in this position are unstable [E0658]
     #[cfg(FALSE)] (let 0 = 1);
     //~^ ERROR `let` expressions in this position are unstable [E0658]
     use_expr!(let 0 = 1);
diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
index 458826498fe..1eabee47c64 100644
--- a/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
@@ -1,5 +1,5 @@
 error: no rules expected the token `let`
-  --> $DIR/feature-gate.rs:101:15
+  --> $DIR/feature-gate.rs:51:15
    |
 LL |     macro_rules! use_expr {
    |     --------------------- when calling this macro
@@ -8,25 +8,7 @@ LL |     use_expr!(let 0 = 1);
    |               ^^^ no rules expected this token in macro call
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:14:9
-   |
-LL |     if (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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:17:11
-   |
-LL |     if (((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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:20:16
+  --> $DIR/feature-gate.rs:14:16
    |
 LL |     if true && let 0 = 1 {}
    |                ^^^^^^^^^
@@ -35,7 +17,7 @@ LL |     if true && let 0 = 1 {}
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:23:8
+  --> $DIR/feature-gate.rs:17:8
    |
 LL |     if let 0 = 1 && true {}
    |        ^^^^^^^^^
@@ -44,88 +26,7 @@ LL |     if let 0 = 1 && true {}
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:26:9
-   |
-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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:29:17
-   |
-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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:32:9
-   |
-LL |     if (let 0 = 1) && (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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:32:24
-   |
-LL |     if (let 0 = 1) && (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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:36:8
-   |
-LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
-   |        ^^^^^^^^^
-   |
-   = 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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:36:21
-   |
-LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
-   |                     ^^^^^^^^^
-   |
-   = 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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:36:35
-   |
-LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
-   |                                   ^^^^^^^^^
-   |
-   = 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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:36:48
-   |
-LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
-   |                                                ^^^^^^^^^
-   |
-   = 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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:36:61
-   |
-LL |     if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
-   |                                                             ^^^^^^^^^
-   |
-   = 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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:43:8
+  --> $DIR/feature-gate.rs:20:8
    |
 LL |     if let Range { start: _, end: _ } = (true..true) && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -134,25 +35,7 @@ LL |     if let Range { start: _, end: _ } = (true..true) && false {}
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:50:12
-   |
-LL |     while (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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:53:14
-   |
-LL |     while (((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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:56:19
+  --> $DIR/feature-gate.rs:27:19
    |
 LL |     while true && let 0 = 1 {}
    |                   ^^^^^^^^^
@@ -161,7 +44,7 @@ LL |     while true && let 0 = 1 {}
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:59:11
+  --> $DIR/feature-gate.rs:30:11
    |
 LL |     while let 0 = 1 && true {}
    |           ^^^^^^^^^
@@ -170,88 +53,7 @@ LL |     while let 0 = 1 && true {}
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:62:12
-   |
-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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:65:20
-   |
-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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:68:12
-   |
-LL |     while (let 0 = 1) && (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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:68:27
-   |
-LL |     while (let 0 = 1) && (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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:72:11
-   |
-LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
-   |           ^^^^^^^^^
-   |
-   = 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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:72:24
-   |
-LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
-   |                        ^^^^^^^^^
-   |
-   = 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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:72:38
-   |
-LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
-   |                                      ^^^^^^^^^
-   |
-   = 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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:72:51
-   |
-LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
-   |                                                   ^^^^^^^^^
-   |
-   = 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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:72:64
-   |
-LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
-   |                                                                ^^^^^^^^^
-   |
-   = 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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:79:11
+  --> $DIR/feature-gate.rs:33:11
    |
 LL |     while let Range { start: _, end: _ } = (true..true) && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -260,7 +62,7 @@ LL |     while let Range { start: _, end: _ } = (true..true) && false {}
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:99:20
+  --> $DIR/feature-gate.rs:49:20
    |
 LL |     #[cfg(FALSE)] (let 0 = 1);
    |                    ^^^^^^^^^
@@ -269,7 +71,7 @@ LL |     #[cfg(FALSE)] (let 0 = 1);
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:86:17
+  --> $DIR/feature-gate.rs:40:17
    |
 LL |     noop_expr!((let 0 = 1));
    |                 ^^^^^^^^^
@@ -277,24 +79,6 @@ LL |     noop_expr!((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
 
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:95:16
-   |
-LL |     use_expr!((let 0 = 1 && 0 == 0));
-   |                ^^^^^^^^^
-   |
-   = 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
-
-error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:97:16
-   |
-LL |     use_expr!((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
-
-error: aborting due to 33 previous errors
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0658`.