diff options
| author | Laurențiu Nicola <lnicola@users.noreply.github.com> | 2025-05-01 07:33:30 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-01 07:33:30 +0000 |
| commit | 00d2f60efd516bc7ea658bd0a6de5e2f1f1df322 (patch) | |
| tree | 9375885343e27ab26b20dfe5a3714e00d5d378d0 /tests/ui/pattern/deref-patterns | |
| parent | e7502210ce5ab2d92cb87c372dab51b637ba6df4 (diff) | |
| parent | 1c5de64814d72effc6890ca823fa4d248041a0bd (diff) | |
Merge pull request #19726 from lnicola/sync-from-rust
Sync from downstream again
Diffstat (limited to 'tests/ui/pattern/deref-patterns')
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 _ => {} } } |
