let-else: add match-ergonomics tests adapted from rfc2005 · rust-lang/rust@2715c5f (original) (raw)

12 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
1 +// from rfc2005 test suite
2 +
3 +#![feature(let_else)]
4 +
5 +// Verify the binding mode shifts - only when no `&` are auto-dereferenced is the
6 +// final default binding mode mutable.
7 +
8 +fn main() {
9 +let Some(n): &mut Option<i32> = &&Some(5i32) else { return }; //~ ERROR mismatched types
10 +*n += 1;
11 +let _ = n;
12 +
13 +let Some(n): &mut Option<i32> = &&mut Some(5i32) else { return }; //~ ERROR mismatched types
14 +*n += 1;
15 +let _ = n;
16 +}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
1 +error[E0308]: mismatched types
2 + --> $DIR/let-else-binding-explicit-mut-annotated.rs:9:37
3 + |
4 +LL | let Some(n): &mut Option = &&Some(5i32) else { return };
5 + | ^^^^^^^^^^^^ types differ in mutability
6 + |
7 + = note: expected mutable reference `&mut Option`
8 + found reference `&&Option`
9 +
10 +error[E0308]: mismatched types
11 + --> $DIR/let-else-binding-explicit-mut-annotated.rs:13:37
12 + |
13 +LL | let Some(n): &mut Option = &&mut Some(5i32) else { return };
14 + | ^^^^^^^^^^^^^^^^ types differ in mutability
15 + |
16 + = note: expected mutable reference `&mut Option`
17 + found reference `&&mut Option`
18 +
19 +error: aborting due to 2 previous errors
20 +
21 +For more information about this error, try `rustc --explain E0308`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
1 +#![feature(let_else)]
2 +
3 +// Slightly different from explicit-mut-annotated -- this won't show an error until borrowck.
4 +// Should it show a type error instead?
5 +
6 +fn main() {
7 +let Some(n): &mut Option<i32> = &mut &Some(5i32) else {
8 +//~^ ERROR cannot borrow data in a `&` reference as mutable
9 +return
10 +};
11 +*n += 1;
12 +let _ = n;
13 +}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
1 +error[E0596]: cannot borrow data in a `&` reference as mutable
2 + --> $DIR/let-else-binding-explicit-mut-borrow.rs:7:37
3 + |
4 +LL | let Some(n): &mut Option = &mut &Some(5i32) else {
5 + | ^^^^^^^^^^^^^^^^ cannot borrow as mutable
6 +
7 +error: aborting due to previous error
8 +
9 +For more information about this error, try `rustc --explain E0596`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
1 +// check-pass
2 +
3 +#![feature(let_else)]
4 +
5 +fn main() {
6 +let Some(n) = &mut &mut Some(5i32) else { return; };
7 +*n += 1; // OK
8 +let _ = n;
9 +
10 +let Some(n): &mut Option<i32> = &mut &mut Some(5i32) else { return; };
11 +*n += 1; // OK
12 +let _ = n;
13 +}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
1 +// from rfc2005 test suite
2 +
3 +#![feature(let_else)]
4 +
5 +// Verify the binding mode shifts - only when no `&` are auto-dereferenced is the
6 +// final default binding mode mutable.
7 +
8 +fn main() {
9 +let Some(n) = &&Some(5i32) else { return };
10 +*n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
11 +let _ = n;
12 +
13 +let Some(n) = &mut &Some(5i32) else { return };
14 +*n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
15 +let _ = n;
16 +
17 +let Some(n) = &&mut Some(5i32) else { return };
18 +*n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
19 +let _ = n;
20 +}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
1 +error[E0594]: cannot assign to `*n`, which is behind a `&` reference
2 + --> $DIR/let-else-binding-explicit-mut.rs:10:5
3 + |
4 +LL | *n += 1;
5 + | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
6 +
7 +error[E0594]: cannot assign to `*n`, which is behind a `&` reference
8 + --> $DIR/let-else-binding-explicit-mut.rs:14:5
9 + |
10 +LL | *n += 1;
11 + | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
12 +
13 +error[E0594]: cannot assign to `*n`, which is behind a `&` reference
14 + --> $DIR/let-else-binding-explicit-mut.rs🔞5
15 + |
16 +LL | *n += 1;
17 + | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
18 +
19 +error: aborting due to 3 previous errors
20 +
21 +For more information about this error, try `rustc --explain E0594`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
1 +// from rfc2005 test suite
2 +
3 +#![feature(let_else)]
4 +
5 +pub fn main() {
6 +let Some(x) = &Some(3) else {
7 +panic!();
8 +};
9 +*x += 1; //~ ERROR: cannot assign to `*x`, which is behind a `&` reference
10 +}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
1 +error[E0594]: cannot assign to `*x`, which is behind a `&` reference
2 + --> $DIR/let-else-binding-immutable.rs:9:5
3 + |
4 +LL | *x += 1;
5 + | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
6 +
7 +error: aborting due to previous error
8 +
9 +For more information about this error, try `rustc --explain E0594`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
1 +// run-pass
2 +// adapted from src/test/ui/binding/if-let.rs
3 +#![feature(let_else)]
4 +#![allow(dead_code)]
5 +
6 +fn none() -> bool {
7 +let None = Some("test") else {
8 +return true;
9 +};
10 +false
11 +}
12 +
13 +fn ok() -> bool {
14 +let Ok(()) = Err::<(),&'static str>("test") else {
15 +return true;
16 +};
17 +false
18 +}
19 +
20 +pub fn main() {
21 +let x = Some(3);
22 +let Some(y) = x else {
23 +panic!("let-else panicked");
24 +};
25 +assert_eq!(y, 3);
26 +let Some(_) = x else {
27 +panic!("bad match");
28 +};
29 +assert!(none());
30 +assert!(ok());
31 +
32 +assert!((|
33 +let 1 = 2 else {
34 +return true;
35 +};
36 +false
37 +})());
38 +
39 +enum Foo {
40 +One,
41 +Two(usize),
42 +Three(String, isize),
43 +}
44 +
45 +let foo = Foo::Three("three".to_string(), 42);
46 +let one = |
47 +let Foo::One = foo else {
48 +return true;
49 +};
50 +false
51 +};
52 +assert!(one());
53 +let two = |
54 +let Foo::Two(_x) = foo else {
55 +return true;
56 +};
57 +false
58 +};
59 +assert!(two());
60 +let three = |
61 +let Foo::Three(s, _x) = foo else {
62 +return false;
63 +};
64 + s == "three"
65 +};
66 +assert!(three());
67 +
68 +let a@Foo::Two(_) = Foo::Two(42_usize) else {
69 +panic!("bad match")
70 +};
71 +let Foo::Two(b) = a else {
72 +panic!("panic in nested `if let`");
73 +};
74 +assert_eq!(b, 42_usize);
75 +}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
1 +// from rfc2005 test suite
2 +
3 +#![feature(let_else)]
4 +
5 +// Without caching type lookups in FnCtxt.resolve_ty_and_def_ufcs
6 +// the error below would be reported twice (once when checking
7 +// for a non-ref pattern, once when processing the pattern).
8 +
9 +fn main() {
10 +let foo = 22;
11 +let u32::XXX = foo else { return }; //~ ERROR: no associated item named `XXX` found for type `u32` in the current scope [E0599]
12 +}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
1 +error[E0599]: no associated item named `XXX` found for type `u32` in the current scope
2 + --> $DIR/let-else-no-double-error.rs:11:14
3 + |
4 +LL | let u32::XXX = foo else { return };
5 + | ^^^ associated item not found in `u32`
6 +
7 +error: aborting due to previous error
8 +
9 +For more information about this error, try `rustc --explain E0599`.