let-else: add match-ergonomics tests adapted from rfc2005

collect explicit-mut passing tests in one file
This commit is contained in:
Cormac Relf 2021-10-17 16:42:22 +11:00
parent 102b9125e1
commit 2715c5f984
12 changed files with 228 additions and 0 deletions

View File

@ -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;
}

View File

@ -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`.

View 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;
}

View File

@ -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`.

View 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;
}

View 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;
}

View 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`.

View 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
}

View 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`.

View 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);
}

View 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]
}

View 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`.