about summary refs log tree commit diff
path: root/tests/ui/pattern
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-04-23 16:11:09 +0000
committerbors <bors@rust-lang.org>2024-04-23 16:11:09 +0000
commitc2f2db79ca3024f68d22b45aa22b570775c2c4ad (patch)
treed725cfc9ae921e7f6f11959f0a758ff29bc826f6 /tests/ui/pattern
parentcd90d5c03532da6f7ca7dcfb861ffabdc36a9d00 (diff)
parent5ff1fa992139f152195d0ff263882e5fe458daaa (diff)
downloadrust-c2f2db79ca3024f68d22b45aa22b570775c2c4ad.tar.gz
rust-c2f2db79ca3024f68d22b45aa22b570775c2c4ad.zip
Auto merge of #124295 - fmease:rollup-i3apkc6, r=fmease
Rollup of 7 pull requests

Successful merges:

 - #120929 (Wrap dyn type with parentheses in suggestion)
 - #122591 (Suggest using type args directly instead of equality constraint)
 - #122598 (deref patterns: lower deref patterns to MIR)
 - #123048 (alloc::Layout: explicitly document size invariant on the type level)
 - #123993 (Do `check_coroutine_obligations` once per typeck root)
 - #124218 (Allow nesting subdiagnostics in #[derive(Subdiagnostic)])
 - #124285 (Mark ``@RUSTC_BUILTIN`` search path usage as unstable)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'tests/ui/pattern')
-rw-r--r--tests/ui/pattern/deref-patterns/bindings.rs64
-rw-r--r--tests/ui/pattern/deref-patterns/branch.rs40
-rw-r--r--tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs24
-rw-r--r--tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr27
-rw-r--r--tests/ui/pattern/deref-patterns/closure_capture.rs21
-rw-r--r--tests/ui/pattern/deref-patterns/fake_borrows.rs14
-rw-r--r--tests/ui/pattern/deref-patterns/fake_borrows.stderr12
-rw-r--r--tests/ui/pattern/deref-patterns/typeck.rs16
-rw-r--r--tests/ui/pattern/deref-patterns/typeck_fail.rs17
-rw-r--r--tests/ui/pattern/deref-patterns/typeck_fail.stderr19
10 files changed, 248 insertions, 6 deletions
diff --git a/tests/ui/pattern/deref-patterns/bindings.rs b/tests/ui/pattern/deref-patterns/bindings.rs
new file mode 100644
index 00000000000..5881e4166a4
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/bindings.rs
@@ -0,0 +1,64 @@
+//@ run-pass
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+fn simple_vec(vec: Vec<u32>) -> u32 {
+    match vec {
+        deref!([]) => 100,
+        deref!([x]) if x == 4 => x + 4,
+        deref!([x]) => x,
+        deref!([1, x]) => x + 200,
+        deref!(ref slice) => slice.iter().sum(),
+        _ => 2000,
+    }
+}
+
+fn nested_vec(vecvec: Vec<Vec<u32>>) -> u32 {
+    match vecvec {
+        deref!([]) => 0,
+        deref!([deref!([x])]) => x,
+        deref!([deref!([0, x]) | deref!([1, x])]) => x,
+        deref!([ref x]) => x.iter().sum(),
+        deref!([deref!([]), deref!([1, x, y])]) => y - x,
+        _ => 2000,
+    }
+}
+
+fn ref_mut(val: u32) -> u32 {
+    let mut b = Box::new(0u32);
+    match &mut b {
+        deref!(_x) if false => unreachable!(),
+        deref!(x) => {
+            *x = val;
+        }
+        _ => unreachable!(),
+    }
+    let deref!(x) = &b else { unreachable!() };
+    *x
+}
+
+#[rustfmt::skip]
+fn or_and_guard(tuple: (u32, u32)) -> u32 {
+    let mut sum = 0;
+    let b = Box::new(tuple);
+    match b {
+        deref!((x, _) | (_, x)) if { sum += x; false } => {},
+        _ => {},
+    }
+    sum
+}
+
+fn main() {
+    assert_eq!(simple_vec(vec![1]), 1);
+    assert_eq!(simple_vec(vec![1, 2]), 202);
+    assert_eq!(simple_vec(vec![1, 2, 3]), 6);
+    assert_eq!(simple_vec(vec![4]), 8);
+
+    assert_eq!(nested_vec(vec![vec![0, 42]]), 42);
+    assert_eq!(nested_vec(vec![vec![1, 42]]), 42);
+    assert_eq!(nested_vec(vec![vec![1, 2, 3]]), 6);
+    assert_eq!(nested_vec(vec![vec![], vec![1, 2, 3]]), 1);
+
+    assert_eq!(ref_mut(42), 42);
+    assert_eq!(or_and_guard((10, 32)), 42);
+}
diff --git a/tests/ui/pattern/deref-patterns/branch.rs b/tests/ui/pattern/deref-patterns/branch.rs
new file mode 100644
index 00000000000..1bac1006d9d
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/branch.rs
@@ -0,0 +1,40 @@
+//@ run-pass
+// Test the execution of deref patterns.
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+fn branch(vec: Vec<u32>) -> u32 {
+    match vec {
+        deref!([]) => 0,
+        deref!([1, _, 3]) => 1,
+        deref!([2, ..]) => 2,
+        _ => 1000,
+    }
+}
+
+fn nested(vec: Vec<Vec<u32>>) -> u32 {
+    match vec {
+        deref!([deref!([]), ..]) => 1,
+        deref!([deref!([0, ..]), deref!([1, ..])]) => 2,
+        _ => 1000,
+    }
+}
+
+fn main() {
+    assert!(matches!(Vec::<u32>::new(), deref!([])));
+    assert!(matches!(vec![1], deref!([1])));
+    assert!(matches!(&vec![1], deref!([1])));
+    assert!(matches!(vec![&1], deref!([1])));
+    assert!(matches!(vec![vec![1]], deref!([deref!([1])])));
+
+    assert_eq!(branch(vec![]), 0);
+    assert_eq!(branch(vec![1, 2, 3]), 1);
+    assert_eq!(branch(vec![3, 2, 1]), 1000);
+    assert_eq!(branch(vec![2]), 2);
+    assert_eq!(branch(vec![2, 3]), 2);
+    assert_eq!(branch(vec![3, 2]), 1000);
+
+    assert_eq!(nested(vec![vec![], vec![2]]), 1);
+    assert_eq!(nested(vec![vec![0], vec![1]]), 2);
+    assert_eq!(nested(vec![vec![0, 2], vec![1, 2]]), 2);
+}
diff --git a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs
new file mode 100644
index 00000000000..84b5ec09dc7
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs
@@ -0,0 +1,24 @@
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+use std::rc::Rc;
+
+struct Struct;
+
+fn cant_move_out_box(b: Box<Struct>) -> Struct {
+    match b {
+        //~^ ERROR: cannot move out of a shared reference
+        deref!(x) => x,
+        _ => unreachable!(),
+    }
+}
+
+fn cant_move_out_rc(rc: Rc<Struct>) -> Struct {
+    match rc {
+        //~^ ERROR: cannot move out of a shared reference
+        deref!(x) => x,
+        _ => unreachable!(),
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr
new file mode 100644
index 00000000000..108db6d9e4b
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr
@@ -0,0 +1,27 @@
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/cant_move_out_of_pattern.rs:9:11
+   |
+LL |     match b {
+   |           ^
+LL |
+LL |         deref!(x) => x,
+   |                -
+   |                |
+   |                data moved here
+   |                move occurs because `x` has type `Struct`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/cant_move_out_of_pattern.rs:17:11
+   |
+LL |     match rc {
+   |           ^^
+LL |
+LL |         deref!(x) => x,
+   |                -
+   |                |
+   |                data moved here
+   |                move occurs because `x` has type `Struct`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/pattern/deref-patterns/closure_capture.rs b/tests/ui/pattern/deref-patterns/closure_capture.rs
new file mode 100644
index 00000000000..fc0ddedac2b
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/closure_capture.rs
@@ -0,0 +1,21 @@
+//@ run-pass
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+fn main() {
+    let b = Box::new("aaa".to_string());
+    let f = || {
+        let deref!(ref s) = b else { unreachable!() };
+        assert_eq!(s.len(), 3);
+    };
+    assert_eq!(b.len(), 3);
+    f();
+
+    let mut b = Box::new("aaa".to_string());
+    let mut f = || {
+        let deref!(ref mut s) = b else { unreachable!() };
+        s.push_str("aa");
+    };
+    f();
+    assert_eq!(b.len(), 5);
+}
diff --git a/tests/ui/pattern/deref-patterns/fake_borrows.rs b/tests/ui/pattern/deref-patterns/fake_borrows.rs
new file mode 100644
index 00000000000..35fa9cbf7d8
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/fake_borrows.rs
@@ -0,0 +1,14 @@
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+#[rustfmt::skip]
+fn main() {
+    let mut b = Box::new(false);
+    match b {
+        deref!(true) => {}
+        _ if { *b = true; false } => {}
+        //~^ ERROR cannot assign `*b` in match guard
+        deref!(false) => {}
+        _ => {},
+    }
+}
diff --git a/tests/ui/pattern/deref-patterns/fake_borrows.stderr b/tests/ui/pattern/deref-patterns/fake_borrows.stderr
new file mode 100644
index 00000000000..6a591e6416c
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/fake_borrows.stderr
@@ -0,0 +1,12 @@
+error[E0510]: cannot assign `*b` in match guard
+  --> $DIR/fake_borrows.rs:9:16
+   |
+LL |     match b {
+   |           - value is immutable in match guard
+LL |         deref!(true) => {}
+LL |         _ if { *b = true; false } => {}
+   |                ^^^^^^^^^ cannot assign
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0510`.
diff --git a/tests/ui/pattern/deref-patterns/typeck.rs b/tests/ui/pattern/deref-patterns/typeck.rs
index ead6dcdbaf0..f23f7042cd8 100644
--- a/tests/ui/pattern/deref-patterns/typeck.rs
+++ b/tests/ui/pattern/deref-patterns/typeck.rs
@@ -4,6 +4,8 @@
 
 use std::rc::Rc;
 
+struct Struct;
+
 fn main() {
     let vec: Vec<u32> = Vec::new();
     match vec {
@@ -22,10 +24,12 @@ fn main() {
         deref!(1..) => {}
         _ => {}
     }
-    // FIXME(deref_patterns): fails to typecheck because `"foo"` has type &str but deref creates a
-    // place of type `str`.
-    // match "foo".to_string() {
-    //     box "foo" => {}
-    //     _ => {}
-    // }
+    let _: &Struct = match &Rc::new(Struct) {
+        deref!(x) => x,
+        _ => unreachable!(),
+    };
+    let _: &[Struct] = match &Rc::new(vec![Struct]) {
+        deref!(deref!(x)) => x,
+        _ => unreachable!(),
+    };
 }
diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.rs b/tests/ui/pattern/deref-patterns/typeck_fail.rs
new file mode 100644
index 00000000000..040118449ec
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/typeck_fail.rs
@@ -0,0 +1,17 @@
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+fn main() {
+    // FIXME(deref_patterns): fails to typecheck because `"foo"` has type &str but deref creates a
+    // place of type `str`.
+    match "foo".to_string() {
+        deref!("foo") => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
+    match &"foo".to_string() {
+        deref!("foo") => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
+}
diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.stderr b/tests/ui/pattern/deref-patterns/typeck_fail.stderr
new file mode 100644
index 00000000000..1c14802745a
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/typeck_fail.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+  --> $DIR/typeck_fail.rs:8:16
+   |
+LL |     match "foo".to_string() {
+   |           ----------------- this expression has type `String`
+LL |         deref!("foo") => {}
+   |                ^^^^^ expected `str`, found `&str`
+
+error[E0308]: mismatched types
+  --> $DIR/typeck_fail.rs:13:16
+   |
+LL |     match &"foo".to_string() {
+   |           ------------------ this expression has type `&String`
+LL |         deref!("foo") => {}
+   |                ^^^^^ expected `str`, found `&str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.