From 218caa410aa38c29984be31a5229b9fa717560ee Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:13 +0200 Subject: Merging upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- tests/ui/destructuring-assignment/bad-expr-lhs.rs | 9 ++ .../destructuring-assignment/bad-expr-lhs.stderr | 44 ++++++++++ .../default-match-bindings-forbidden.rs | 5 ++ .../default-match-bindings-forbidden.stderr | 14 ++++ tests/ui/destructuring-assignment/drop-order.rs | 43 ++++++++++ .../destructuring-assignment/nested_destructure.rs | 18 ++++ .../destructuring-assignment/note-unsupported.rs | 22 +++++ .../note-unsupported.stderr | 66 +++++++++++++++ .../destructuring-assignment/slice_destructure.rs | 15 ++++ .../slice_destructure_fail.rs | 6 ++ .../slice_destructure_fail.stderr | 23 +++++ .../struct-or-enum-variant-path.rs | 34 ++++++++ .../destructuring-assignment/struct_destructure.rs | 20 +++++ .../struct_destructure_fail.rs | 16 ++++ .../struct_destructure_fail.stderr | 45 ++++++++++ .../destructuring-assignment/tuple_destructure.rs | 37 ++++++++ .../tuple_destructure_fail.rs | 9 ++ .../tuple_destructure_fail.stderr | 42 ++++++++++ .../tuple_struct_destructure.rs | 34 ++++++++ .../tuple_struct_destructure_fail.rs | 44 ++++++++++ .../tuple_struct_destructure_fail.stderr | 98 ++++++++++++++++++++++ .../warn-unused-duplication.rs | 21 +++++ .../warn-unused-duplication.stderr | 15 ++++ 23 files changed, 680 insertions(+) create mode 100644 tests/ui/destructuring-assignment/bad-expr-lhs.rs create mode 100644 tests/ui/destructuring-assignment/bad-expr-lhs.stderr create mode 100644 tests/ui/destructuring-assignment/default-match-bindings-forbidden.rs create mode 100644 tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr create mode 100644 tests/ui/destructuring-assignment/drop-order.rs create mode 100644 tests/ui/destructuring-assignment/nested_destructure.rs create mode 100644 tests/ui/destructuring-assignment/note-unsupported.rs create mode 100644 tests/ui/destructuring-assignment/note-unsupported.stderr create mode 100644 tests/ui/destructuring-assignment/slice_destructure.rs create mode 100644 tests/ui/destructuring-assignment/slice_destructure_fail.rs create mode 100644 tests/ui/destructuring-assignment/slice_destructure_fail.stderr create mode 100644 tests/ui/destructuring-assignment/struct-or-enum-variant-path.rs create mode 100644 tests/ui/destructuring-assignment/struct_destructure.rs create mode 100644 tests/ui/destructuring-assignment/struct_destructure_fail.rs create mode 100644 tests/ui/destructuring-assignment/struct_destructure_fail.stderr create mode 100644 tests/ui/destructuring-assignment/tuple_destructure.rs create mode 100644 tests/ui/destructuring-assignment/tuple_destructure_fail.rs create mode 100644 tests/ui/destructuring-assignment/tuple_destructure_fail.stderr create mode 100644 tests/ui/destructuring-assignment/tuple_struct_destructure.rs create mode 100644 tests/ui/destructuring-assignment/tuple_struct_destructure_fail.rs create mode 100644 tests/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr create mode 100644 tests/ui/destructuring-assignment/warn-unused-duplication.rs create mode 100644 tests/ui/destructuring-assignment/warn-unused-duplication.stderr (limited to 'tests/ui/destructuring-assignment') diff --git a/tests/ui/destructuring-assignment/bad-expr-lhs.rs b/tests/ui/destructuring-assignment/bad-expr-lhs.rs new file mode 100644 index 000000000..53794783a --- /dev/null +++ b/tests/ui/destructuring-assignment/bad-expr-lhs.rs @@ -0,0 +1,9 @@ +fn main() { + 1 = 2; //~ ERROR invalid left-hand side of assignment + 1 += 2; //~ ERROR invalid left-hand side of assignment + (1, 2) = (3, 4); + //~^ ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + + None = Some(3); //~ ERROR invalid left-hand side of assignment +} diff --git a/tests/ui/destructuring-assignment/bad-expr-lhs.stderr b/tests/ui/destructuring-assignment/bad-expr-lhs.stderr new file mode 100644 index 000000000..d29867474 --- /dev/null +++ b/tests/ui/destructuring-assignment/bad-expr-lhs.stderr @@ -0,0 +1,44 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/bad-expr-lhs.rs:2:7 + | +LL | 1 = 2; + | - ^ + | | + | cannot assign to this expression + +error[E0067]: invalid left-hand side of assignment + --> $DIR/bad-expr-lhs.rs:3:7 + | +LL | 1 += 2; + | - ^^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/bad-expr-lhs.rs:4:12 + | +LL | (1, 2) = (3, 4); + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/bad-expr-lhs.rs:4:12 + | +LL | (1, 2) = (3, 4); + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/bad-expr-lhs.rs:8:10 + | +LL | None = Some(3); + | ---- ^ + | | + | cannot assign to this expression + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0067, E0070. +For more information about an error, try `rustc --explain E0067`. diff --git a/tests/ui/destructuring-assignment/default-match-bindings-forbidden.rs b/tests/ui/destructuring-assignment/default-match-bindings-forbidden.rs new file mode 100644 index 000000000..ff867c000 --- /dev/null +++ b/tests/ui/destructuring-assignment/default-match-bindings-forbidden.rs @@ -0,0 +1,5 @@ +fn main() { + let mut x = &0; + let mut y = &0; + (x, y) = &(1, 2); //~ ERROR mismatched types +} diff --git a/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr b/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr new file mode 100644 index 000000000..950e0223e --- /dev/null +++ b/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/default-match-bindings-forbidden.rs:4:5 + | +LL | (x, y) = &(1, 2); + | ^^^^^^ ------- this expression has type `&({integer}, {integer})` + | | + | expected reference, found tuple + | + = note: expected reference `&({integer}, {integer})` + found tuple `(_, _)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/destructuring-assignment/drop-order.rs b/tests/ui/destructuring-assignment/drop-order.rs new file mode 100644 index 000000000..79671054c --- /dev/null +++ b/tests/ui/destructuring-assignment/drop-order.rs @@ -0,0 +1,43 @@ +// run-pass + +//! Test that let bindings and destructuring assignments have consistent drop orders + +#![allow(unused_variables, unused_assignments)] + +use std::cell::RefCell; + +thread_local! { + static DROP_ORDER: RefCell> = RefCell::new(Vec::new()); +} + +struct DropRecorder(usize); +impl Drop for DropRecorder { + fn drop(&mut self) { + DROP_ORDER.with(|d| d.borrow_mut().push(self.0)); + } +} + +fn main() { + let expected_drop_order = vec![1, 4, 5, 3, 2]; + // Check the drop order for let bindings: + { + let _ = DropRecorder(1); + let _val = DropRecorder(2); + let (x, _) = (DropRecorder(3), DropRecorder(4)); + drop(DropRecorder(5)); + } + DROP_ORDER.with(|d| { + assert_eq!(&*d.borrow(), &expected_drop_order); + d.borrow_mut().clear(); + }); + // Check that the drop order for destructuring assignment is the same: + { + let _val; + let x; + _ = DropRecorder(1); + _val = DropRecorder(2); + (x, _) = (DropRecorder(3), DropRecorder(4)); + drop(DropRecorder(5)); + } + DROP_ORDER.with(|d| assert_eq!(&*d.borrow(), &expected_drop_order)); +} diff --git a/tests/ui/destructuring-assignment/nested_destructure.rs b/tests/ui/destructuring-assignment/nested_destructure.rs new file mode 100644 index 000000000..94b3a5ff9 --- /dev/null +++ b/tests/ui/destructuring-assignment/nested_destructure.rs @@ -0,0 +1,18 @@ +// run-pass + +struct Struct { + a: S, + b: T, +} + +struct TupleStruct(S, T); + +fn main() { + let (a, b, c, d); + Struct { a: TupleStruct((a, b), c), b: [d] } = + Struct { a: TupleStruct((0, 1), 2), b: [3] }; + assert_eq!((a, b, c, d), (0, 1, 2, 3)); + + // unnested underscore: just discard + _ = 1; +} diff --git a/tests/ui/destructuring-assignment/note-unsupported.rs b/tests/ui/destructuring-assignment/note-unsupported.rs new file mode 100644 index 000000000..c69edd421 --- /dev/null +++ b/tests/ui/destructuring-assignment/note-unsupported.rs @@ -0,0 +1,22 @@ +struct S { x: u8, y: u8 } + +fn main() { + let (a, b) = (1, 2); + + (a, b) = (3, 4); + (a, b) += (3, 4); //~ ERROR invalid left-hand side of assignment + //~| ERROR binary assignment operation `+=` cannot be applied + + [a, b] = [3, 4]; + [a, b] += [3, 4]; //~ ERROR invalid left-hand side of assignment + //~| ERROR binary assignment operation `+=` cannot be applied + + let s = S { x: 3, y: 4 }; + + S { x: a, y: b } = s; + S { x: a, y: b } += s; //~ ERROR invalid left-hand side of assignment + //~| ERROR binary assignment operation `+=` cannot be applied + + S { x: a, ..s } = S { x: 3, y: 4 }; + //~^ ERROR functional record updates are not allowed in destructuring assignments +} diff --git a/tests/ui/destructuring-assignment/note-unsupported.stderr b/tests/ui/destructuring-assignment/note-unsupported.stderr new file mode 100644 index 000000000..8a88332b7 --- /dev/null +++ b/tests/ui/destructuring-assignment/note-unsupported.stderr @@ -0,0 +1,66 @@ +error: functional record updates are not allowed in destructuring assignments + --> $DIR/note-unsupported.rs:20:17 + | +LL | S { x: a, ..s } = S { x: 3, y: 4 }; + | ^ help: consider removing the trailing pattern + +error[E0368]: binary assignment operation `+=` cannot be applied to type `({integer}, {integer})` + --> $DIR/note-unsupported.rs:7:5 + | +LL | (a, b) += (3, 4); + | ------^^^^^^^^^^ + | | + | cannot use `+=` on type `({integer}, {integer})` + +error[E0067]: invalid left-hand side of assignment + --> $DIR/note-unsupported.rs:7:12 + | +LL | (a, b) += (3, 4); + | ------ ^^ + | | + | cannot assign to this expression + +error[E0368]: binary assignment operation `+=` cannot be applied to type `[{integer}; 2]` + --> $DIR/note-unsupported.rs:11:5 + | +LL | [a, b] += [3, 4]; + | ------^^^^^^^^^^ + | | + | cannot use `+=` on type `[{integer}; 2]` + +error[E0067]: invalid left-hand side of assignment + --> $DIR/note-unsupported.rs:11:12 + | +LL | [a, b] += [3, 4]; + | ------ ^^ + | | + | cannot assign to this expression + +error[E0368]: binary assignment operation `+=` cannot be applied to type `S` + --> $DIR/note-unsupported.rs:17:5 + | +LL | S { x: a, y: b } += s; + | ----------------^^^^^ + | | + | cannot use `+=` on type `S` + | +note: an implementation of `AddAssign<_>` might be missing for `S` + --> $DIR/note-unsupported.rs:1:1 + | +LL | struct S { x: u8, y: u8 } + | ^^^^^^^^ must implement `AddAssign<_>` +note: the trait `AddAssign` must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error[E0067]: invalid left-hand side of assignment + --> $DIR/note-unsupported.rs:17:22 + | +LL | S { x: a, y: b } += s; + | ---------------- ^^ + | | + | cannot assign to this expression + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0067, E0368. +For more information about an error, try `rustc --explain E0067`. diff --git a/tests/ui/destructuring-assignment/slice_destructure.rs b/tests/ui/destructuring-assignment/slice_destructure.rs new file mode 100644 index 000000000..762c4b5e8 --- /dev/null +++ b/tests/ui/destructuring-assignment/slice_destructure.rs @@ -0,0 +1,15 @@ +// run-pass + +fn main() { + let (mut a, mut b); + [a, b] = [0, 1]; + assert_eq!((a, b), (0, 1)); + let mut c; + [a, .., b, c] = [1, 2, 3, 4, 5]; + assert_eq!((a, b, c), (1, 4, 5)); + [_, a, _] = [1, 2, 3]; + assert_eq!((a, b), (2, 4)); + [..] = [1, 2, 3]; + [c, ..] = [5, 6, 6]; + assert_eq!(c, 5); +} diff --git a/tests/ui/destructuring-assignment/slice_destructure_fail.rs b/tests/ui/destructuring-assignment/slice_destructure_fail.rs new file mode 100644 index 000000000..33b09eb34 --- /dev/null +++ b/tests/ui/destructuring-assignment/slice_destructure_fail.rs @@ -0,0 +1,6 @@ +fn main() { + let (mut a, mut b); + [a, .., b, ..] = [0, 1]; //~ ERROR `..` can only be used once per slice pattern + [a, a, b] = [1, 2]; //~ ERROR pattern requires 3 elements but array has 2 + [_] = [1, 2]; //~ ERROR pattern requires 1 element but array has 2 +} diff --git a/tests/ui/destructuring-assignment/slice_destructure_fail.stderr b/tests/ui/destructuring-assignment/slice_destructure_fail.stderr new file mode 100644 index 000000000..92c86feba --- /dev/null +++ b/tests/ui/destructuring-assignment/slice_destructure_fail.stderr @@ -0,0 +1,23 @@ +error: `..` can only be used once per slice pattern + --> $DIR/slice_destructure_fail.rs:3:14 + | +LL | [a, .., b, ..] = [0, 1]; + | -- ^^ can only be used once per slice pattern + | | + | previously used here + +error[E0527]: pattern requires 3 elements but array has 2 + --> $DIR/slice_destructure_fail.rs:4:3 + | +LL | [a, a, b] = [1, 2]; + | ^^^^^^^^^ expected 2 elements + +error[E0527]: pattern requires 1 element but array has 2 + --> $DIR/slice_destructure_fail.rs:5:3 + | +LL | [_] = [1, 2]; + | ^^^ expected 2 elements + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0527`. diff --git a/tests/ui/destructuring-assignment/struct-or-enum-variant-path.rs b/tests/ui/destructuring-assignment/struct-or-enum-variant-path.rs new file mode 100644 index 000000000..8da7f90c5 --- /dev/null +++ b/tests/ui/destructuring-assignment/struct-or-enum-variant-path.rs @@ -0,0 +1,34 @@ +// check-pass + +struct S; + +enum E { + V, +} + +type A = E; + +fn main() { + let mut a; + + (S, a) = (S, ()); + + (E::V, a) = (E::V, ()); + + (::V, a) = (E::V, ()); + (A::V, a) = (E::V, ()); +} + +impl S { + fn check() { + let a; + (Self, a) = (S, ()); + } +} + +impl E { + fn check() { + let a; + (Self::V, a) = (E::V, ()); + } +} diff --git a/tests/ui/destructuring-assignment/struct_destructure.rs b/tests/ui/destructuring-assignment/struct_destructure.rs new file mode 100644 index 000000000..8cceaadd7 --- /dev/null +++ b/tests/ui/destructuring-assignment/struct_destructure.rs @@ -0,0 +1,20 @@ +// run-pass + +struct Struct { + a: S, + b: T, +} + +fn main() { + let (mut a, mut b); + Struct { a, b } = Struct { a: 0, b: 1 }; + assert_eq!((a, b), (0, 1)); + Struct { a: b, b: a } = Struct { a: 1, b: 2 }; + assert_eq!((a,b), (2, 1)); + Struct { a: _, b } = Struct { a: 1, b: 2 }; + assert_eq!((a, b), (2, 2)); + Struct { a, .. } = Struct { a: 1, b: 3 }; + assert_eq!((a, b), (1, 2)); + Struct { .. } = Struct { a: 1, b: 4 }; + assert_eq!((a, b), (1, 2)); +} diff --git a/tests/ui/destructuring-assignment/struct_destructure_fail.rs b/tests/ui/destructuring-assignment/struct_destructure_fail.rs new file mode 100644 index 000000000..c001fccd4 --- /dev/null +++ b/tests/ui/destructuring-assignment/struct_destructure_fail.rs @@ -0,0 +1,16 @@ +struct Struct { + a: S, + b: T, +} + +fn main() { + let (mut a, b); + let mut c; + let d = Struct { a: 0, b: 1 }; + Struct { a, b, c } = Struct { a: 0, b: 1 }; //~ ERROR does not have a field named `c` + Struct { a, _ } = Struct { a: 1, b: 2 }; //~ ERROR pattern does not mention field `b` + //~| ERROR expected identifier, found reserved identifier `_` + Struct { a, ..d } = Struct { a: 1, b: 2 }; + //~^ ERROR functional record updates are not allowed in destructuring assignments + Struct { a, .. }; //~ ERROR base expression required after `..` +} diff --git a/tests/ui/destructuring-assignment/struct_destructure_fail.stderr b/tests/ui/destructuring-assignment/struct_destructure_fail.stderr new file mode 100644 index 000000000..ae7b3d1e5 --- /dev/null +++ b/tests/ui/destructuring-assignment/struct_destructure_fail.stderr @@ -0,0 +1,45 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/struct_destructure_fail.rs:11:17 + | +LL | Struct { a, _ } = Struct { a: 1, b: 2 }; + | ------ ^ expected identifier, found reserved identifier + | | + | while parsing this struct + +error: functional record updates are not allowed in destructuring assignments + --> $DIR/struct_destructure_fail.rs:13:19 + | +LL | Struct { a, ..d } = Struct { a: 1, b: 2 }; + | ^ help: consider removing the trailing pattern + +error: base expression required after `..` + --> $DIR/struct_destructure_fail.rs:15:19 + | +LL | Struct { a, .. }; + | ^ add a base expression here + +error[E0026]: struct `Struct` does not have a field named `c` + --> $DIR/struct_destructure_fail.rs:10:20 + | +LL | Struct { a, b, c } = Struct { a: 0, b: 1 }; + | ^ struct `Struct` does not have this field + +error[E0027]: pattern does not mention field `b` + --> $DIR/struct_destructure_fail.rs:11:5 + | +LL | Struct { a, _ } = Struct { a: 1, b: 2 }; + | ^^^^^^^^^^^^^^^ missing field `b` + | +help: include the missing field in the pattern + | +LL | Struct { a, b } = Struct { a: 1, b: 2 }; + | ~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | Struct { a, .. } = Struct { a: 1, b: 2 }; + | ~~~~~~ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0026, E0027. +For more information about an error, try `rustc --explain E0026`. diff --git a/tests/ui/destructuring-assignment/tuple_destructure.rs b/tests/ui/destructuring-assignment/tuple_destructure.rs new file mode 100644 index 000000000..2a8584029 --- /dev/null +++ b/tests/ui/destructuring-assignment/tuple_destructure.rs @@ -0,0 +1,37 @@ +// run-pass + +fn main() { + let (mut a, mut b); + (a, b) = (0, 1); + assert_eq!((a, b), (0, 1)); + (b, a) = (a, b); + assert_eq!((a, b), (1, 0)); + (a, .., b) = (1, 2); + assert_eq!((a, b), (1, 2)); + (.., a) = (1, 2); + assert_eq!((a, b), (2, 2)); + (..) = (3, 4); + assert_eq!((a, b), (2, 2)); + (b, ..) = (5, 6, 7); + assert_eq!(b, 5); + (a, _) = (8, 9); + assert_eq!(a, 8); + + // Test for a non-Copy type (String): + let (mut c, mut d); + (c, d) = ("c".to_owned(), "d".to_owned()); + assert_eq!(c, "c"); + assert_eq!(d, "d"); + (d, c) = (c, d); + assert_eq!(c, "d"); + assert_eq!(d, "c"); + + // Test nesting/parentheses: + ((a, b)) = (0, 1); + assert_eq!((a, b), (0, 1)); + (((a, b)), (c)) = ((2, 3), d); + assert_eq!((a, b), (2, 3)); + assert_eq!(c, "c"); + ((a, .., b), .., (..)) = ((4, 5), ()); + assert_eq!((a, b), (4, 5)); +} diff --git a/tests/ui/destructuring-assignment/tuple_destructure_fail.rs b/tests/ui/destructuring-assignment/tuple_destructure_fail.rs new file mode 100644 index 000000000..4e3172d19 --- /dev/null +++ b/tests/ui/destructuring-assignment/tuple_destructure_fail.rs @@ -0,0 +1,9 @@ +const C: i32 = 1; + +fn main() { + let (mut a, mut b); + (a, .., b, ..) = (0, 1); //~ ERROR `..` can only be used once per tuple pattern + (a, a, b) = (1, 2); //~ ERROR mismatched types + (C, ..) = (0,1); //~ ERROR invalid left-hand side of assignment + (_,) = (1, 2); //~ ERROR mismatched types +} diff --git a/tests/ui/destructuring-assignment/tuple_destructure_fail.stderr b/tests/ui/destructuring-assignment/tuple_destructure_fail.stderr new file mode 100644 index 000000000..a3004cbbe --- /dev/null +++ b/tests/ui/destructuring-assignment/tuple_destructure_fail.stderr @@ -0,0 +1,42 @@ +error: `..` can only be used once per tuple pattern + --> $DIR/tuple_destructure_fail.rs:5:16 + | +LL | (a, .., b, ..) = (0, 1); + | -- ^^ can only be used once per tuple pattern + | | + | previously used here + +error[E0308]: mismatched types + --> $DIR/tuple_destructure_fail.rs:6:5 + | +LL | (a, a, b) = (1, 2); + | ^^^^^^^^^ ------ this expression has type `({integer}, {integer})` + | | + | expected a tuple with 2 elements, found one with 3 elements + | + = note: expected tuple `({integer}, {integer})` + found tuple `(_, _, _)` + +error[E0070]: invalid left-hand side of assignment + --> $DIR/tuple_destructure_fail.rs:7:13 + | +LL | (C, ..) = (0,1); + | - ^ + | | + | cannot assign to this expression + +error[E0308]: mismatched types + --> $DIR/tuple_destructure_fail.rs:8:5 + | +LL | (_,) = (1, 2); + | ^^^^ ------ this expression has type `({integer}, {integer})` + | | + | expected a tuple with 2 elements, found one with 1 element + | + = note: expected tuple `({integer}, {integer})` + found tuple `(_,)` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0070, E0308. +For more information about an error, try `rustc --explain E0070`. diff --git a/tests/ui/destructuring-assignment/tuple_struct_destructure.rs b/tests/ui/destructuring-assignment/tuple_struct_destructure.rs new file mode 100644 index 000000000..07b5f7a31 --- /dev/null +++ b/tests/ui/destructuring-assignment/tuple_struct_destructure.rs @@ -0,0 +1,34 @@ +// run-pass + +struct TupleStruct(S, T); + +impl TupleStruct { + fn assign(self, first: &mut S, second: &mut T) { + // Test usage of `Self` instead of the struct name: + Self(*first, *second) = self + } +} + +enum Enum { + SingleVariant(S, T) +} + +type Alias = Enum; + +fn main() { + let (mut a, mut b); + TupleStruct(a, b) = TupleStruct(0, 1); + assert_eq!((a, b), (0, 1)); + TupleStruct(a, .., b) = TupleStruct(1, 2); + assert_eq!((a, b), (1, 2)); + TupleStruct(_, a) = TupleStruct(2, 2); + assert_eq!((a, b), (2, 2)); + TupleStruct(..) = TupleStruct(3, 4); + assert_eq!((a, b), (2, 2)); + TupleStruct(5,6).assign(&mut a, &mut b); + assert_eq!((a, b), (5, 6)); + Enum::SingleVariant(a, b) = Enum::SingleVariant(7, 8); + assert_eq!((a, b), (7, 8)); + Alias::SingleVariant(a, b) = Alias::SingleVariant(9, 10); + assert_eq!((a, b), (9, 10)); +} diff --git a/tests/ui/destructuring-assignment/tuple_struct_destructure_fail.rs b/tests/ui/destructuring-assignment/tuple_struct_destructure_fail.rs new file mode 100644 index 000000000..845f867d7 --- /dev/null +++ b/tests/ui/destructuring-assignment/tuple_struct_destructure_fail.rs @@ -0,0 +1,44 @@ +struct TupleStruct(S, T); + +enum Enum { + SingleVariant(S, T) +} + +type Alias = Enum; + +trait Test { + fn test() -> TupleStruct { + TupleStruct(0, 0) + } +} + +impl Test for Alias {} + +fn test() -> TupleStruct { + TupleStruct(0, 0) +} + +fn main() { + let (mut a, mut b); + TupleStruct(a, .., b, ..) = TupleStruct(0, 1); + //~^ ERROR `..` can only be used once per tuple struct or variant pattern + Enum::SingleVariant(a, .., b, ..) = Enum::SingleVariant(0, 1); + //~^ ERROR `..` can only be used once per tuple struct or variant pattern + + TupleStruct(a, a, b) = TupleStruct(1, 2); + //~^ ERROR this pattern has 3 fields, but the corresponding tuple struct has 2 fields + TupleStruct(_) = TupleStruct(1, 2); + //~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields + Enum::SingleVariant(a, a, b) = Enum::SingleVariant(1, 2); + //~^ ERROR this pattern has 3 fields, but the corresponding tuple variant has 2 fields + Enum::SingleVariant(_) = Enum::SingleVariant(1, 2); + //~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields + + // Check if `test` is recognized as not a tuple struct but a function call: + test() = TupleStruct(0, 0); + //~^ ERROR invalid left-hand side of assignment + (test)() = TupleStruct(0, 0); + //~^ ERROR invalid left-hand side of assignment + as Test>::test() = TupleStruct(0, 0); + //~^ ERROR invalid left-hand side of assignment +} diff --git a/tests/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/tests/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr new file mode 100644 index 000000000..5cc7acba3 --- /dev/null +++ b/tests/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -0,0 +1,98 @@ +error: `..` can only be used once per tuple struct or variant pattern + --> $DIR/tuple_struct_destructure_fail.rs:23:27 + | +LL | TupleStruct(a, .., b, ..) = TupleStruct(0, 1); + | -- ^^ can only be used once per tuple struct or variant pattern + | | + | previously used here + +error: `..` can only be used once per tuple struct or variant pattern + --> $DIR/tuple_struct_destructure_fail.rs:25:35 + | +LL | Enum::SingleVariant(a, .., b, ..) = Enum::SingleVariant(0, 1); + | -- ^^ can only be used once per tuple struct or variant pattern + | | + | previously used here + +error[E0023]: this pattern has 3 fields, but the corresponding tuple struct has 2 fields + --> $DIR/tuple_struct_destructure_fail.rs:28:17 + | +LL | struct TupleStruct(S, T); + | - - tuple struct has 2 fields +... +LL | TupleStruct(a, a, b) = TupleStruct(1, 2); + | ^ ^ ^ expected 2 fields, found 3 + +error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields + --> $DIR/tuple_struct_destructure_fail.rs:30:17 + | +LL | struct TupleStruct(S, T); + | - - tuple struct has 2 fields +... +LL | TupleStruct(_) = TupleStruct(1, 2); + | ^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | TupleStruct(_, _) = TupleStruct(1, 2); + | +++ +help: use `..` to ignore all fields + | +LL | TupleStruct(..) = TupleStruct(1, 2); + | ~~ + +error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields + --> $DIR/tuple_struct_destructure_fail.rs:32:25 + | +LL | SingleVariant(S, T) + | - - tuple variant has 2 fields +... +LL | Enum::SingleVariant(a, a, b) = Enum::SingleVariant(1, 2); + | ^ ^ ^ expected 2 fields, found 3 + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields + --> $DIR/tuple_struct_destructure_fail.rs:34:25 + | +LL | SingleVariant(S, T) + | - - tuple variant has 2 fields +... +LL | Enum::SingleVariant(_) = Enum::SingleVariant(1, 2); + | ^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | Enum::SingleVariant(_, _) = Enum::SingleVariant(1, 2); + | +++ +help: use `..` to ignore all fields + | +LL | Enum::SingleVariant(..) = Enum::SingleVariant(1, 2); + | ~~ + +error[E0070]: invalid left-hand side of assignment + --> $DIR/tuple_struct_destructure_fail.rs:38:12 + | +LL | test() = TupleStruct(0, 0); + | ------ ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/tuple_struct_destructure_fail.rs:40:14 + | +LL | (test)() = TupleStruct(0, 0); + | -------- ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/tuple_struct_destructure_fail.rs:42:38 + | +LL | as Test>::test() = TupleStruct(0, 0); + | -------------------------------- ^ + | | + | cannot assign to this expression + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0023, E0070. +For more information about an error, try `rustc --explain E0023`. diff --git a/tests/ui/destructuring-assignment/warn-unused-duplication.rs b/tests/ui/destructuring-assignment/warn-unused-duplication.rs new file mode 100644 index 000000000..390f44b8a --- /dev/null +++ b/tests/ui/destructuring-assignment/warn-unused-duplication.rs @@ -0,0 +1,21 @@ +// run-pass + +#![warn(unused_assignments)] + +fn main() { + let mut a; + // Assignment occurs left-to-right. + // However, we emit warnings when this happens, so it is clear that this is happening. + (a, a) = (0, 1); //~ WARN value assigned to `a` is never read + assert_eq!(a, 1); + + // We can't always tell when a variable is being assigned to twice, which is why we don't try + // to emit an error, which would be fallible. + let mut x = 1; + (*foo(&mut x), *foo(&mut x)) = (5, 6); + assert_eq!(x, 6); +} + +fn foo<'a>(x: &'a mut u32) -> &'a mut u32 { + x +} diff --git a/tests/ui/destructuring-assignment/warn-unused-duplication.stderr b/tests/ui/destructuring-assignment/warn-unused-duplication.stderr new file mode 100644 index 000000000..e16625136 --- /dev/null +++ b/tests/ui/destructuring-assignment/warn-unused-duplication.stderr @@ -0,0 +1,15 @@ +warning: value assigned to `a` is never read + --> $DIR/warn-unused-duplication.rs:9:6 + | +LL | (a, a) = (0, 1); + | ^ + | + = help: maybe it is overwritten before being read? +note: the lint level is defined here + --> $DIR/warn-unused-duplication.rs:3:9 + | +LL | #![warn(unused_assignments)] + | ^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + -- cgit v1.2.3