let-else: add match-ergonomics tests adapted from rfc2005
collect explicit-mut passing tests in one file
This commit is contained in:
parent
102b9125e1
commit
2715c5f984
12 changed files with 228 additions and 0 deletions
|
@ -0,0 +1,16 @@
|
||||||
|
// 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;
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
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`.
|
13
src/test/ui/let-else/let-else-binding-explicit-mut-borrow.rs
Normal file
13
src/test/ui/let-else/let-else-binding-explicit-mut-borrow.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#![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;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
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`.
|
13
src/test/ui/let-else/let-else-binding-explicit-mut-pass.rs
Normal file
13
src/test/ui/let-else/let-else-binding-explicit-mut-pass.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// 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;
|
||||||
|
}
|
20
src/test/ui/let-else/let-else-binding-explicit-mut.rs
Normal file
20
src/test/ui/let-else/let-else-binding-explicit-mut.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// 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;
|
||||||
|
}
|
21
src/test/ui/let-else/let-else-binding-explicit-mut.stderr
Normal file
21
src/test/ui/let-else/let-else-binding-explicit-mut.stderr
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
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`.
|
10
src/test/ui/let-else/let-else-binding-immutable.rs
Normal file
10
src/test/ui/let-else/let-else-binding-immutable.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// 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
|
||||||
|
}
|
9
src/test/ui/let-else/let-else-binding-immutable.stderr
Normal file
9
src/test/ui/let-else/let-else-binding-immutable.stderr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
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`.
|
75
src/test/ui/let-else/let-else-bindings.rs
Normal file
75
src/test/ui/let-else/let-else-bindings.rs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
// 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);
|
||||||
|
}
|
12
src/test/ui/let-else/let-else-no-double-error.rs
Normal file
12
src/test/ui/let-else/let-else-no-double-error.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// 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]
|
||||||
|
}
|
9
src/test/ui/let-else/let-else-no-double-error.stderr
Normal file
9
src/test/ui/let-else/let-else-no-double-error.stderr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
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`.
|
Loading…
Add table
Add a link
Reference in a new issue