--- /dev/null
+// from rfc2005 test suite
+
+#![feature(let_else)]
+
+// Verify the binding mode shifts - only when no `&` are auto-dereferenced is the
+// final default binding mode mutable.
+
+fn main() {
+ let Some(n): &mut Option<i32> = &&Some(5i32) else { return }; //~ ERROR mismatched types
+ *n += 1;
+ let _ = n;
+
+ let Some(n): &mut Option<i32> = &&mut Some(5i32) else { return }; //~ ERROR mismatched types
+ *n += 1;
+ let _ = n;
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/let-else-binding-explicit-mut-annotated.rs:9:37
+ |
+LL | let Some(n): &mut Option<i32> = &&Some(5i32) else { return };
+ | ^^^^^^^^^^^^ types differ in mutability
+ |
+ = note: expected mutable reference `&mut Option<i32>`
+ found reference `&&Option<i32>`
+
+error[E0308]: mismatched types
+ --> $DIR/let-else-binding-explicit-mut-annotated.rs:13:37
+ |
+LL | let Some(n): &mut Option<i32> = &&mut Some(5i32) else { return };
+ | ^^^^^^^^^^^^^^^^ types differ in mutability
+ |
+ = note: expected mutable reference `&mut Option<i32>`
+ found reference `&&mut Option<i32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+#![feature(let_else)]
+
+// Slightly different from explicit-mut-annotated -- this won't show an error until borrowck.
+// Should it show a type error instead?
+
+fn main() {
+ let Some(n): &mut Option<i32> = &mut &Some(5i32) else {
+ //~^ ERROR cannot borrow data in a `&` reference as mutable
+ return
+ };
+ *n += 1;
+ let _ = n;
+}
--- /dev/null
+error[E0596]: cannot borrow data in a `&` reference as mutable
+ --> $DIR/let-else-binding-explicit-mut-borrow.rs:7:37
+ |
+LL | let Some(n): &mut Option<i32> = &mut &Some(5i32) else {
+ | ^^^^^^^^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
--- /dev/null
+// check-pass
+
+#![feature(let_else)]
+
+fn main() {
+ let Some(n) = &mut &mut Some(5i32) else { return; };
+ *n += 1; // OK
+ let _ = n;
+
+ let Some(n): &mut Option<i32> = &mut &mut Some(5i32) else { return; };
+ *n += 1; // OK
+ let _ = n;
+}
--- /dev/null
+// from rfc2005 test suite
+
+#![feature(let_else)]
+
+// Verify the binding mode shifts - only when no `&` are auto-dereferenced is the
+// final default binding mode mutable.
+
+fn main() {
+ let Some(n) = &&Some(5i32) else { return };
+ *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
+ let _ = n;
+
+ let Some(n) = &mut &Some(5i32) else { return };
+ *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
+ let _ = n;
+
+ let Some(n) = &&mut Some(5i32) else { return };
+ *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
+ let _ = n;
+}
--- /dev/null
+error[E0594]: cannot assign to `*n`, which is behind a `&` reference
+ --> $DIR/let-else-binding-explicit-mut.rs:10:5
+ |
+LL | *n += 1;
+ | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*n`, which is behind a `&` reference
+ --> $DIR/let-else-binding-explicit-mut.rs:14:5
+ |
+LL | *n += 1;
+ | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*n`, which is behind a `&` reference
+ --> $DIR/let-else-binding-explicit-mut.rs:18:5
+ |
+LL | *n += 1;
+ | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
--- /dev/null
+// from rfc2005 test suite
+
+#![feature(let_else)]
+
+pub fn main() {
+ let Some(x) = &Some(3) else {
+ panic!();
+ };
+ *x += 1; //~ ERROR: cannot assign to `*x`, which is behind a `&` reference
+}
--- /dev/null
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
+ --> $DIR/let-else-binding-immutable.rs:9:5
+ |
+LL | *x += 1;
+ | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
--- /dev/null
+// run-pass
+// adapted from src/test/ui/binding/if-let.rs
+#![feature(let_else)]
+#![allow(dead_code)]
+
+fn none() -> bool {
+ let None = Some("test") else {
+ return true;
+ };
+ false
+}
+
+fn ok() -> bool {
+ let Ok(()) = Err::<(),&'static str>("test") else {
+ return true;
+ };
+ false
+}
+
+pub fn main() {
+ let x = Some(3);
+ let Some(y) = x else {
+ panic!("let-else panicked");
+ };
+ assert_eq!(y, 3);
+ let Some(_) = x else {
+ panic!("bad match");
+ };
+ assert!(none());
+ assert!(ok());
+
+ assert!((|| {
+ let 1 = 2 else {
+ return true;
+ };
+ false
+ })());
+
+ enum Foo {
+ One,
+ Two(usize),
+ Three(String, isize),
+ }
+
+ let foo = Foo::Three("three".to_string(), 42);
+ let one = || {
+ let Foo::One = foo else {
+ return true;
+ };
+ false
+ };
+ assert!(one());
+ let two = || {
+ let Foo::Two(_x) = foo else {
+ return true;
+ };
+ false
+ };
+ assert!(two());
+ let three = || {
+ let Foo::Three(s, _x) = foo else {
+ return false;
+ };
+ s == "three"
+ };
+ assert!(three());
+
+ let a@Foo::Two(_) = Foo::Two(42_usize) else {
+ panic!("bad match")
+ };
+ let Foo::Two(b) = a else {
+ panic!("panic in nested `if let`");
+ };
+ assert_eq!(b, 42_usize);
+}
--- /dev/null
+// from rfc2005 test suite
+
+#![feature(let_else)]
+
+// Without caching type lookups in FnCtxt.resolve_ty_and_def_ufcs
+// the error below would be reported twice (once when checking
+// for a non-ref pattern, once when processing the pattern).
+
+fn main() {
+ let foo = 22;
+ let u32::XXX = foo else { return }; //~ ERROR: no associated item named `XXX` found for type `u32` in the current scope [E0599]
+}
--- /dev/null
+error[E0599]: no associated item named `XXX` found for type `u32` in the current scope
+ --> $DIR/let-else-no-double-error.rs:11:14
+ |
+LL | let u32::XXX = foo else { return };
+ | ^^^ associated item not found in `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.