Skip to content

Commit 2715c5f

Browse files
committed
let-else: add match-ergonomics tests adapted from rfc2005
collect explicit-mut passing tests in one file
1 parent 102b912 commit 2715c5f

12 files changed

+228
-0
lines changed
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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<i32> = &&Some(5i32) else { return };
5+
| ^^^^^^^^^^^^ types differ in mutability
6+
|
7+
= note: expected mutable reference `&mut Option<i32>`
8+
found reference `&&Option<i32>`
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<i32> = &&mut Some(5i32) else { return };
14+
| ^^^^^^^^^^^^^^^^ types differ in mutability
15+
|
16+
= note: expected mutable reference `&mut Option<i32>`
17+
found reference `&&mut Option<i32>`
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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<i32> = &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 numberDiff line numberDiff 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 numberDiff line numberDiff 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 numberDiff line numberDiff 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:18: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 numberDiff line numberDiff 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 numberDiff line numberDiff 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`.
+75
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 numberDiff line numberDiff 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`.

0 commit comments

Comments
 (0)