]> git.lizzy.rs Git - rust.git/commitdiff
let-else: add match-ergonomics tests adapted from rfc2005
authorCormac Relf <web@cormacrelf.net>
Sun, 17 Oct 2021 05:42:22 +0000 (16:42 +1100)
committerCormac Relf <web@cormacrelf.net>
Mon, 13 Dec 2021 03:02:41 +0000 (14:02 +1100)
collect explicit-mut passing tests in one file

12 files changed:
src/test/ui/let-else/let-else-binding-explicit-mut-annotated.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-binding-explicit-mut-annotated.stderr [new file with mode: 0644]
src/test/ui/let-else/let-else-binding-explicit-mut-borrow.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-binding-explicit-mut-borrow.stderr [new file with mode: 0644]
src/test/ui/let-else/let-else-binding-explicit-mut-pass.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-binding-explicit-mut.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-binding-explicit-mut.stderr [new file with mode: 0644]
src/test/ui/let-else/let-else-binding-immutable.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-binding-immutable.stderr [new file with mode: 0644]
src/test/ui/let-else/let-else-bindings.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-no-double-error.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-no-double-error.stderr [new file with mode: 0644]

diff --git a/src/test/ui/let-else/let-else-binding-explicit-mut-annotated.rs b/src/test/ui/let-else/let-else-binding-explicit-mut-annotated.rs
new file mode 100644 (file)
index 0000000..b65fa13
--- /dev/null
@@ -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;
+}
diff --git a/src/test/ui/let-else/let-else-binding-explicit-mut-annotated.stderr b/src/test/ui/let-else/let-else-binding-explicit-mut-annotated.stderr
new file mode 100644 (file)
index 0000000..fdec7e7
--- /dev/null
@@ -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`.
diff --git a/src/test/ui/let-else/let-else-binding-explicit-mut-borrow.rs b/src/test/ui/let-else/let-else-binding-explicit-mut-borrow.rs
new file mode 100644 (file)
index 0000000..63b35df
--- /dev/null
@@ -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;
+}
diff --git a/src/test/ui/let-else/let-else-binding-explicit-mut-borrow.stderr b/src/test/ui/let-else/let-else-binding-explicit-mut-borrow.stderr
new file mode 100644 (file)
index 0000000..023fab8
--- /dev/null
@@ -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`.
diff --git a/src/test/ui/let-else/let-else-binding-explicit-mut-pass.rs b/src/test/ui/let-else/let-else-binding-explicit-mut-pass.rs
new file mode 100644 (file)
index 0000000..305be92
--- /dev/null
@@ -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;
+}
diff --git a/src/test/ui/let-else/let-else-binding-explicit-mut.rs b/src/test/ui/let-else/let-else-binding-explicit-mut.rs
new file mode 100644 (file)
index 0000000..dbe4715
--- /dev/null
@@ -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;
+}
diff --git a/src/test/ui/let-else/let-else-binding-explicit-mut.stderr b/src/test/ui/let-else/let-else-binding-explicit-mut.stderr
new file mode 100644 (file)
index 0000000..45f2b6b
--- /dev/null
@@ -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`.
diff --git a/src/test/ui/let-else/let-else-binding-immutable.rs b/src/test/ui/let-else/let-else-binding-immutable.rs
new file mode 100644 (file)
index 0000000..96de0ff
--- /dev/null
@@ -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
+}
diff --git a/src/test/ui/let-else/let-else-binding-immutable.stderr b/src/test/ui/let-else/let-else-binding-immutable.stderr
new file mode 100644 (file)
index 0000000..dd1365a
--- /dev/null
@@ -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`.
diff --git a/src/test/ui/let-else/let-else-bindings.rs b/src/test/ui/let-else/let-else-bindings.rs
new file mode 100644 (file)
index 0000000..d5121e7
--- /dev/null
@@ -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);
+}
diff --git a/src/test/ui/let-else/let-else-no-double-error.rs b/src/test/ui/let-else/let-else-no-double-error.rs
new file mode 100644 (file)
index 0000000..35dcdd3
--- /dev/null
@@ -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]
+}
diff --git a/src/test/ui/let-else/let-else-no-double-error.stderr b/src/test/ui/let-else/let-else-no-double-error.stderr
new file mode 100644 (file)
index 0000000..941e588
--- /dev/null
@@ -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`.