about summary refs log tree commit diff
path: root/tests/ui/pattern/deref-patterns
diff options
context:
space:
mode:
authorLaurențiu Nicola <lnicola@users.noreply.github.com>2025-05-01 07:33:30 +0000
committerGitHub <noreply@github.com>2025-05-01 07:33:30 +0000
commit00d2f60efd516bc7ea658bd0a6de5e2f1f1df322 (patch)
tree9375885343e27ab26b20dfe5a3714e00d5d378d0 /tests/ui/pattern/deref-patterns
parente7502210ce5ab2d92cb87c372dab51b637ba6df4 (diff)
parent1c5de64814d72effc6890ca823fa4d248041a0bd (diff)
Merge pull request #19726 from lnicola/sync-from-rust
Sync from downstream again
Diffstat (limited to 'tests/ui/pattern/deref-patterns')
-rw-r--r--tests/ui/pattern/deref-patterns/bindings.rs22
-rw-r--r--tests/ui/pattern/deref-patterns/byte-string-type-errors.rs12
-rw-r--r--tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr10
-rw-r--r--tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs20
-rw-r--r--tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr41
-rw-r--r--tests/ui/pattern/deref-patterns/closure_capture.rs28
-rw-r--r--tests/ui/pattern/deref-patterns/deref-box.rs37
-rw-r--r--tests/ui/pattern/deref-patterns/fake_borrows.rs17
-rw-r--r--tests/ui/pattern/deref-patterns/fake_borrows.stderr31
-rw-r--r--tests/ui/pattern/deref-patterns/implicit-cow-deref.rs5
-rw-r--r--tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs2
11 files changed, 164 insertions, 61 deletions
diff --git a/tests/ui/pattern/deref-patterns/bindings.rs b/tests/ui/pattern/deref-patterns/bindings.rs
index c14d57f3f24..ac48e3ffefc 100644
--- a/tests/ui/pattern/deref-patterns/bindings.rs
+++ b/tests/ui/pattern/deref-patterns/bindings.rs
@@ -3,6 +3,8 @@
 #![feature(deref_patterns)]
 #![allow(incomplete_features)]
 
+use std::rc::Rc;
+
 #[cfg(explicit)]
 fn simple_vec(vec: Vec<u32>) -> u32 {
     match vec {
@@ -53,29 +55,29 @@ fn nested_vec(vecvec: Vec<Vec<u32>>) -> u32 {
 
 #[cfg(explicit)]
 fn ref_mut(val: u32) -> u32 {
-    let mut b = Box::new(0u32);
+    let mut b = vec![0u32];
     match &mut b {
-        deref!(_x) if false => unreachable!(),
-        deref!(x) => {
+        deref!([_x]) if false => unreachable!(),
+        deref!([x]) => {
             *x = val;
         }
         _ => unreachable!(),
     }
-    let deref!(x) = &b else { unreachable!() };
+    let deref!([x]) = &b else { unreachable!() };
     *x
 }
 
 #[cfg(implicit)]
 fn ref_mut(val: u32) -> u32 {
-    let mut b = Box::new((0u32,));
+    let mut b = vec![0u32];
     match &mut b {
-        (_x,) if false => unreachable!(),
-        (x,) => {
+        [_x] if false => unreachable!(),
+        [x] => {
             *x = val;
         }
         _ => unreachable!(),
     }
-    let (x,) = &b else { unreachable!() };
+    let [x] = &b else { unreachable!() };
     *x
 }
 
@@ -83,7 +85,7 @@ fn ref_mut(val: u32) -> u32 {
 #[rustfmt::skip]
 fn or_and_guard(tuple: (u32, u32)) -> u32 {
     let mut sum = 0;
-    let b = Box::new(tuple);
+    let b = Rc::new(tuple);
     match b {
         deref!((x, _) | (_, x)) if { sum += x; false } => {},
         _ => {},
@@ -95,7 +97,7 @@ fn or_and_guard(tuple: (u32, u32)) -> u32 {
 #[rustfmt::skip]
 fn or_and_guard(tuple: (u32, u32)) -> u32 {
     let mut sum = 0;
-    let b = Box::new(tuple);
+    let b = Rc::new(tuple);
     match b {
         (x, _) | (_, x) if { sum += x; false } => {},
         _ => {},
diff --git a/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs b/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs
index 29a33e3e2c3..64acc4748af 100644
--- a/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs
+++ b/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs
@@ -2,6 +2,8 @@
 //! patterns to have type `[u8]` or `[u8; N]` when matching on a slice or array; this can affect the
 //! "found" type reported in error messages when matching on a slice or array of the wrong type.
 
+//@ dont-require-annotations: NOTE
+
 #![feature(deref_patterns)]
 #![expect(incomplete_features)]
 
@@ -10,25 +12,25 @@ fn main() {
     // the same as byte string literals.
     if let b"test" = () {}
     //~^ ERROR mismatched types
-    //~| expected `()`, found `&[u8; 4]`
+    //~| NOTE expected `()`, found `&[u8; 4]`
 
     // Baseline 2: there's a special case for byte string patterns in stable rust, allowing them to
     // match on slice references. This affects the error when matching on a non-`&[u8]` slice ref,
     // reporting the "found" type as `&[u8]`.
     if let b"test" = &[] as &[i8] {}
     //~^ ERROR mismatched types
-    //~| expected `&[i8]`, found `&[u8]`
+    //~| NOTE expected `&[i8]`, found `&[u8]`
 
     // Test matching on a non-`[u8]` slice: the pattern has type `[u8]` if a slice is expected.
     if let b"test" = *(&[] as &[i8]) {}
     //~^ ERROR mismatched types
-    //~| expected `[i8]`, found `[u8]`
+    //~| NOTE expected `[i8]`, found `[u8]`
 
     // Test matching on a non-`[u8;4]` array: the pattern has type `[u8;4]` if an array is expected.
     if let b"test" = [()] {}
     //~^ ERROR mismatched types
-    //~| expected `[(); 1]`, found `[u8; 4]`
+    //~| NOTE expected `[(); 1]`, found `[u8; 4]`
     if let b"test" = *b"this array is too long" {}
     //~^ ERROR mismatched types
-    //~| expected an array with a size of 22, found one with a size of 4
+    //~| NOTE expected an array with a size of 22, found one with a size of 4
 }
diff --git a/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr b/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr
index d29a5b59252..0317b7209e1 100644
--- a/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr
+++ b/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/byte-string-type-errors.rs:11:12
+  --> $DIR/byte-string-type-errors.rs:13:12
    |
 LL |     if let b"test" = () {}
    |            ^^^^^^^   -- this expression has type `()`
@@ -7,7 +7,7 @@ LL |     if let b"test" = () {}
    |            expected `()`, found `&[u8; 4]`
 
 error[E0308]: mismatched types
-  --> $DIR/byte-string-type-errors.rs:18:12
+  --> $DIR/byte-string-type-errors.rs:20:12
    |
 LL |     if let b"test" = &[] as &[i8] {}
    |            ^^^^^^^   ------------ this expression has type `&[i8]`
@@ -18,7 +18,7 @@ LL |     if let b"test" = &[] as &[i8] {}
               found reference `&'static [u8]`
 
 error[E0308]: mismatched types
-  --> $DIR/byte-string-type-errors.rs:23:12
+  --> $DIR/byte-string-type-errors.rs:25:12
    |
 LL |     if let b"test" = *(&[] as &[i8]) {}
    |            ^^^^^^^   --------------- this expression has type `[i8]`
@@ -29,7 +29,7 @@ LL |     if let b"test" = *(&[] as &[i8]) {}
               found slice `[u8]`
 
 error[E0308]: mismatched types
-  --> $DIR/byte-string-type-errors.rs:28:12
+  --> $DIR/byte-string-type-errors.rs:30:12
    |
 LL |     if let b"test" = [()] {}
    |            ^^^^^^^   ---- this expression has type `[(); 1]`
@@ -40,7 +40,7 @@ LL |     if let b"test" = [()] {}
               found array `[u8; 4]`
 
 error[E0308]: mismatched types
-  --> $DIR/byte-string-type-errors.rs:31:12
+  --> $DIR/byte-string-type-errors.rs:33:12
    |
 LL |     if let b"test" = *b"this array is too long" {}
    |            ^^^^^^^   -------------------------- this expression has type `[u8; 22]`
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
index 791776be5ac..2b4746e33e6 100644
--- a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs
+++ b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs
@@ -5,11 +5,11 @@ use std::rc::Rc;
 
 struct Struct;
 
-fn cant_move_out_box(b: Box<Struct>) -> Struct {
+fn cant_move_out_vec(b: Vec<Struct>) -> Struct {
     match b {
-        //~^ ERROR: cannot move out of a shared reference
-        deref!(x) => x,
-        _ => unreachable!(),
+        //~^ ERROR: cannot move out of type `[Struct]`, a non-copy slice
+        deref!([x]) => x,
+        _ => panic!(),
     }
 }
 
@@ -21,16 +21,16 @@ fn cant_move_out_rc(rc: Rc<Struct>) -> Struct {
     }
 }
 
-struct Container(Struct);
-
-fn cant_move_out_box_implicit(b: Box<Container>) -> Struct {
+fn cant_move_out_vec_implicit(b: Vec<Struct>) -> Struct {
     match b {
-        //~^ ERROR: cannot move out of a shared reference
-        Container(x) => x,
-        _ => unreachable!(),
+        //~^ ERROR: cannot move out of type `[Struct]`, a non-copy slice
+        [x] => x,
+        _ => panic!(),
     }
 }
 
+struct Container(Struct);
+
 fn cant_move_out_rc_implicit(rc: Rc<Container>) -> Struct {
     match rc {
         //~^ ERROR: cannot move out of a shared reference
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
index 1887800fc38..a548ac5909a 100644
--- a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr
+++ b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr
@@ -1,19 +1,19 @@
-error[E0507]: cannot move out of a shared reference
+error[E0508]: cannot move out of type `[Struct]`, a non-copy slice
   --> $DIR/cant_move_out_of_pattern.rs:9:11
    |
 LL |     match b {
-   |           ^
+   |           ^ cannot move out of here
 LL |
-LL |         deref!(x) => x,
-   |                -
-   |                |
-   |                data moved here
-   |                move occurs because `x` has type `Struct`, which does not implement the `Copy` trait
+LL |         deref!([x]) => x,
+   |                 -
+   |                 |
+   |                 data moved here
+   |                 move occurs because `x` has type `Struct`, which does not implement the `Copy` trait
    |
 help: consider borrowing the pattern binding
    |
-LL |         deref!(ref x) => x,
-   |                +++
+LL |         deref!([ref x]) => x,
+   |                 +++
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/cant_move_out_of_pattern.rs:17:11
@@ -32,22 +32,22 @@ help: consider borrowing the pattern binding
 LL |         deref!(ref x) => x,
    |                +++
 
-error[E0507]: cannot move out of a shared reference
-  --> $DIR/cant_move_out_of_pattern.rs:27:11
+error[E0508]: cannot move out of type `[Struct]`, a non-copy slice
+  --> $DIR/cant_move_out_of_pattern.rs:25:11
    |
 LL |     match b {
-   |           ^
+   |           ^ cannot move out of here
 LL |
-LL |         Container(x) => x,
-   |                   -
-   |                   |
-   |                   data moved here
-   |                   move occurs because `x` has type `Struct`, which does not implement the `Copy` trait
+LL |         [x] => x,
+   |          -
+   |          |
+   |          data moved here
+   |          move occurs because `x` has type `Struct`, which does not implement the `Copy` trait
    |
 help: consider borrowing the pattern binding
    |
-LL |         Container(ref x) => x,
-   |                   +++
+LL |         [ref x] => x,
+   |          +++
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/cant_move_out_of_pattern.rs:35:11
@@ -68,4 +68,5 @@ LL |         Container(ref x) => x,
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0507`.
+Some errors have detailed explanations: E0507, E0508.
+For more information about an 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
index 08586b6c7ab..cf78eeda1d5 100644
--- a/tests/ui/pattern/deref-patterns/closure_capture.rs
+++ b/tests/ui/pattern/deref-patterns/closure_capture.rs
@@ -2,8 +2,12 @@
 #![feature(deref_patterns)]
 #![allow(incomplete_features)]
 
+use std::rc::Rc;
+
+struct NoCopy;
+
 fn main() {
-    let b = Box::new("aaa".to_string());
+    let b = Rc::new("aaa".to_string());
     let f = || {
         let deref!(ref s) = b else { unreachable!() };
         assert_eq!(s.len(), 3);
@@ -20,13 +24,13 @@ fn main() {
     assert_eq!(v, [1, 2, 3]);
     f();
 
-    let mut b = Box::new("aaa".to_string());
+    let mut b = "aaa".to_string();
     let mut f = || {
         let deref!(ref mut s) = b else { unreachable!() };
-        s.push_str("aa");
+        s.make_ascii_uppercase();
     };
     f();
-    assert_eq!(b.len(), 5);
+    assert_eq!(b, "AAA");
 
     let mut v = vec![1, 2, 3];
     let mut f = || {
@@ -45,4 +49,20 @@ fn main() {
     };
     f();
     assert_eq!(v, [1, 2, 4]);
+
+    let b = Box::new(NoCopy);
+    let f = || {
+        // this should move out of the box rather than borrow.
+        let deref!(x) = b else { unreachable!() };
+        drop::<NoCopy>(x);
+    };
+    f();
+
+    let b = Box::new((NoCopy,));
+    let f = || {
+        // this should move out of the box rather than borrow.
+        let (x,) = b else { unreachable!() };
+        drop::<NoCopy>(x);
+    };
+    f();
 }
diff --git a/tests/ui/pattern/deref-patterns/deref-box.rs b/tests/ui/pattern/deref-patterns/deref-box.rs
new file mode 100644
index 00000000000..2d0a8d01972
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/deref-box.rs
@@ -0,0 +1,37 @@
+//@ run-pass
+//! Deref patterns on boxes are lowered using built-in derefs, rather than generic `Deref::deref`
+//! and `DerefMut::deref_mut`. Test that they work as expected.
+
+#![feature(deref_patterns)]
+#![expect(incomplete_features)]
+
+fn unbox_1<T>(b: Box<T>) -> T {
+    let deref!(x) = b else { unreachable!() };
+    x
+}
+
+fn unbox_2<T>(b: Box<(T,)>) -> T {
+    let (x,) = b else { unreachable!() };
+    x
+}
+
+fn unbox_separately<T>(b: Box<(T, T)>) -> (T, T) {
+    let (x, _) = b else { unreachable!() };
+    let (_, y) = b else { unreachable!() };
+    (x, y)
+}
+
+fn main() {
+    // test that deref patterns can move out of boxes
+    let b1 = Box::new(0);
+    let b2 = Box::new((0,));
+    assert_eq!(unbox_1(b1), unbox_2(b2));
+    let b3 = Box::new((1, 2));
+    assert_eq!(unbox_separately(b3), (1, 2));
+
+    // test that borrowing from a box also works
+    let mut b = "hi".to_owned().into_boxed_str();
+    let deref!(ref mut s) = b else { unreachable!() };
+    s.make_ascii_uppercase();
+    assert_eq!(&*b, "HI");
+}
diff --git a/tests/ui/pattern/deref-patterns/fake_borrows.rs b/tests/ui/pattern/deref-patterns/fake_borrows.rs
index bf614d7d66f..fba2873fd02 100644
--- a/tests/ui/pattern/deref-patterns/fake_borrows.rs
+++ b/tests/ui/pattern/deref-patterns/fake_borrows.rs
@@ -3,6 +3,23 @@
 
 #[rustfmt::skip]
 fn main() {
+    let mut v = vec![false];
+    match v {
+        deref!([true]) => {}
+        _ if { v[0] = true; false } => {}
+        //~^ ERROR cannot borrow `v` as mutable because it is also borrowed as immutable
+        deref!([false]) => {}
+        _ => {},
+    }
+    match v {
+        [true] => {}
+        _ if { v[0] = true; false } => {}
+        //~^ ERROR cannot borrow `v` as mutable because it is also borrowed as immutable
+        [false] => {}
+        _ => {},
+    }
+
+    // deref patterns on boxes are lowered specially; test them separately.
     let mut b = Box::new(false);
     match b {
         deref!(true) => {}
diff --git a/tests/ui/pattern/deref-patterns/fake_borrows.stderr b/tests/ui/pattern/deref-patterns/fake_borrows.stderr
index 8c060236d0d..7dc3001739e 100644
--- a/tests/ui/pattern/deref-patterns/fake_borrows.stderr
+++ b/tests/ui/pattern/deref-patterns/fake_borrows.stderr
@@ -1,6 +1,28 @@
-error[E0510]: cannot assign `*b` in match guard
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
   --> $DIR/fake_borrows.rs:9:16
    |
+LL |     match v {
+   |           - immutable borrow occurs here
+LL |         deref!([true]) => {}
+LL |         _ if { v[0] = true; false } => {}
+   |                ^                  - immutable borrow later used here
+   |                |
+   |                mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/fake_borrows.rs:16:16
+   |
+LL |     match v {
+   |           - immutable borrow occurs here
+LL |         [true] => {}
+LL |         _ if { v[0] = true; false } => {}
+   |                ^                  - immutable borrow later used here
+   |                |
+   |                mutable borrow occurs here
+
+error[E0510]: cannot assign `*b` in match guard
+  --> $DIR/fake_borrows.rs:26:16
+   |
 LL |     match b {
    |           - value is immutable in match guard
 LL |         deref!(true) => {}
@@ -8,7 +30,7 @@ LL |         _ if { *b = true; false } => {}
    |                ^^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `*b` in match guard
-  --> $DIR/fake_borrows.rs:16:16
+  --> $DIR/fake_borrows.rs:33:16
    |
 LL |     match b {
    |           - value is immutable in match guard
@@ -16,6 +38,7 @@ LL |         true => {}
 LL |         _ if { *b = true; false } => {}
    |                ^^^^^^^^^ cannot assign
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0510`.
+Some errors have detailed explanations: E0502, E0510.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs b/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs
index a9b8de86010..04c83d4c33f 100644
--- a/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs
+++ b/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs
@@ -4,6 +4,7 @@
 #![allow(incomplete_features)]
 
 use std::borrow::Cow;
+use std::rc::Rc;
 
 fn main() {
     let cow: Cow<'static, [u8]> = Cow::Borrowed(&[1, 2, 3]);
@@ -18,7 +19,7 @@ fn main() {
         Cow::Owned(_) => unreachable!(),
     }
 
-    match Box::new(&cow) {
+    match Rc::new(&cow) {
         Cow::Borrowed { 0: _ } => {}
         Cow::Owned { 0: _ } => unreachable!(),
         _ => unreachable!(),
@@ -37,7 +38,7 @@ fn main() {
         Cow::Owned(_) => {}
     }
 
-    match Box::new(&cow_of_cow) {
+    match Rc::new(&cow_of_cow) {
         Cow::Borrowed { 0: _ } => unreachable!(),
         Cow::Owned { 0: _ } => {}
         _ => unreachable!(),
diff --git a/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs
index 00064b2320c..9e95f4ec409 100644
--- a/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs
+++ b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs
@@ -15,7 +15,7 @@ fn main() {
     // FIXME(deref_patterns): there should be a special diagnostic for missing `DerefPure`.
     match MyPointer {
         () => {}
-        //~^ the trait bound `MyPointer: DerefPure` is not satisfied
+        //~^ ERROR the trait bound `MyPointer: DerefPure` is not satisfied
         _ => {}
     }
 }