diff options
| author | Mara Bos <m-ou.se@m-ou.se> | 2020-11-12 19:46:09 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-11-12 19:46:09 +0100 |
| commit | 755dd14e00fd9007a67779b129e81b47c6435113 (patch) | |
| tree | 8082b642e059fe77959dfea3893351db34c3f872 /src | |
| parent | 4b0b42a2808e9d1f4f49bc9e3767f90feacbd152 (diff) | |
| parent | de84ad95b4b097e504171c7c606bf3715803c13b (diff) | |
Rollup merge of #78836 - fanzier:struct-and-slice-destructuring, r=petrochenkov
Implement destructuring assignment for structs and slices
This is the second step towards implementing destructuring assignment (RFC: rust-lang/rfcs#2909, tracking issue: #71126). This PR is the second part of #71156, which was split up to allow for easier review.
Note that the first PR (#78748) is not merged yet, so it is included as the first commit in this one. I thought this would allow the review to start earlier because I have some time this weekend to respond to reviews. If ``@petrochenkov`` prefers to wait until the first PR is merged, I totally understand, of course.
This PR implements destructuring assignment for (tuple) structs and slices. In order to do this, the following *parser change* was necessary: struct expressions are not required to have a base expression, i.e. `Struct { a: 1, .. }` becomes legal (in order to act like a struct pattern).
Unfortunately, this PR slightly regresses the diagnostics implemented in #77283. However, it is only a missing help message in `src/test/ui/issues/issue-77218.rs`. Other instances of this diagnostic are not affected. Since I don't exactly understand how this help message works and how to fix it yet, I was hoping it's OK to regress this temporarily and fix it in a follow-up PR.
Thanks to ``@varkor`` who helped with the implementation, particularly around the struct rest changes.
r? ``@petrochenkov``
Diffstat (limited to 'src')
21 files changed, 443 insertions, 72 deletions
diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs index caf55bec53d..bff92d8607e 100644 --- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs @@ -155,7 +155,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) { }, 17 => { let path = Path::from_ident(Ident::from_str("S")); - g(ExprKind::Struct(path, vec![], Some(make_x()))); + g(ExprKind::Struct(path, vec![], StructRest::Base(make_x()))); }, 18 => { iter_exprs(depth - 1, &mut |e| g(ExprKind::Try(e))); diff --git a/src/test/ui/destructuring-assignment/nested_destructure.rs b/src/test/ui/destructuring-assignment/nested_destructure.rs new file mode 100644 index 00000000000..393dfc16c0a --- /dev/null +++ b/src/test/ui/destructuring-assignment/nested_destructure.rs @@ -0,0 +1,17 @@ +// run-pass + +#![feature(destructuring_assignment)] + +struct Struct<S, T> { + a: S, + b: T, +} + +struct TupleStruct<S, T>(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)); +} diff --git a/src/test/ui/destructuring-assignment/note-unsupported.rs b/src/test/ui/destructuring-assignment/note-unsupported.rs index e0cb9dc9158..249fba7f920 100644 --- a/src/test/ui/destructuring-assignment/note-unsupported.rs +++ b/src/test/ui/destructuring-assignment/note-unsupported.rs @@ -7,18 +7,19 @@ fn main() { (a, b) += (3, 4); //~ ERROR invalid left-hand side of assignment //~| ERROR binary assignment operation `+=` cannot be applied - [a, b] = [3, 4]; //~ ERROR invalid left-hand side of assignment + [a, b] = [3, 4]; //~ ERROR destructuring assignments are unstable [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; //~ ERROR invalid left-hand side of assignment + S { x: a, y: b } = s; //~ ERROR destructuring assignments are unstable 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 invalid left-hand side of assignment + //~^ ERROR functional record updates are not allowed in destructuring assignments + //~| ERROR destructuring assignments are unstable let c = 3; diff --git a/src/test/ui/destructuring-assignment/note-unsupported.stderr b/src/test/ui/destructuring-assignment/note-unsupported.stderr index c5543fab825..a81324b99e5 100644 --- a/src/test/ui/destructuring-assignment/note-unsupported.stderr +++ b/src/test/ui/destructuring-assignment/note-unsupported.stderr @@ -10,7 +10,46 @@ LL | (a, b) = (3, 4); = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable error[E0658]: destructuring assignments are unstable - --> $DIR/note-unsupported.rs:25:17 + --> $DIR/note-unsupported.rs:10:12 + | +LL | [a, b] = [3, 4]; + | ------ ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0658]: destructuring assignments are unstable + --> $DIR/note-unsupported.rs:16:22 + | +LL | S { x: a, y: b } = s; + | ---------------- ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0658]: destructuring assignments are unstable + --> $DIR/note-unsupported.rs:20:21 + | +LL | S { x: a, ..s } = S { x: 3, y: 4 }; + | --------------- ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +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[E0658]: destructuring assignments are unstable + --> $DIR/note-unsupported.rs:26:17 | LL | ((a, b), c) = ((3, 4), 5); | ----------- ^ @@ -36,14 +75,6 @@ LL | (a, b) += (3, 4); | | | cannot assign to this expression -error[E0070]: invalid left-hand side of assignment - --> $DIR/note-unsupported.rs:10: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 | @@ -60,14 +91,6 @@ LL | [a, b] += [3, 4]; | | | cannot assign to this expression -error[E0070]: invalid left-hand side of assignment - --> $DIR/note-unsupported.rs:16:22 - | -LL | S { x: a, y: b } = s; - | ---------------- ^ - | | - | cannot assign to this expression - error[E0368]: binary assignment operation `+=` cannot be applied to type `S` --> $DIR/note-unsupported.rs:17:5 | @@ -86,15 +109,7 @@ LL | S { x: a, y: b } += s; | | | cannot assign to this expression -error[E0070]: invalid left-hand side of assignment - --> $DIR/note-unsupported.rs:20:21 - | -LL | S { x: a, ..s } = S { x: 3, y: 4 }; - | --------------- ^ - | | - | cannot assign to this expression - -error: aborting due to 11 previous errors +error: aborting due to 12 previous errors -Some errors have detailed explanations: E0067, E0070, E0368, E0658. +Some errors have detailed explanations: E0067, E0368, E0658. For more information about an error, try `rustc --explain E0067`. diff --git a/src/test/ui/destructuring-assignment/slice_destructure.rs b/src/test/ui/destructuring-assignment/slice_destructure.rs new file mode 100644 index 00000000000..3dd10aff19c --- /dev/null +++ b/src/test/ui/destructuring-assignment/slice_destructure.rs @@ -0,0 +1,15 @@ +// run-pass + +#![feature(destructuring_assignment)] + +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)); + [..] = [1, 2, 3]; + [c, ..] = [5, 6, 6]; + assert_eq!(c, 5); +} diff --git a/src/test/ui/destructuring-assignment/slice_destructure_fail.rs b/src/test/ui/destructuring-assignment/slice_destructure_fail.rs new file mode 100644 index 00000000000..f636ea3511c --- /dev/null +++ b/src/test/ui/destructuring-assignment/slice_destructure_fail.rs @@ -0,0 +1,7 @@ +#![feature(destructuring_assignment)] + +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 +} diff --git a/src/test/ui/destructuring-assignment/slice_destructure_fail.stderr b/src/test/ui/destructuring-assignment/slice_destructure_fail.stderr new file mode 100644 index 00000000000..728687deb8b --- /dev/null +++ b/src/test/ui/destructuring-assignment/slice_destructure_fail.stderr @@ -0,0 +1,17 @@ +error: `..` can only be used once per slice pattern + --> $DIR/slice_destructure_fail.rs:5: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:6:3 + | +LL | [a, a, b] = [1, 2]; + | ^^^^^^^^^ expected 2 elements + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0527`. diff --git a/src/test/ui/destructuring-assignment/struct_destructure.rs b/src/test/ui/destructuring-assignment/struct_destructure.rs new file mode 100644 index 00000000000..b3a96ee1573 --- /dev/null +++ b/src/test/ui/destructuring-assignment/struct_destructure.rs @@ -0,0 +1,19 @@ +// run-pass + +#![feature(destructuring_assignment)] +struct Struct<S, T> { + 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, .. } = Struct { a: 1, b: 3 }; + assert_eq!((a, b), (1, 1)); + Struct { .. } = Struct { a: 1, b: 4 }; + assert_eq!((a, b), (1, 1)); +} diff --git a/src/test/ui/destructuring-assignment/struct_destructure_fail.rs b/src/test/ui/destructuring-assignment/struct_destructure_fail.rs new file mode 100644 index 00000000000..c22695ed388 --- /dev/null +++ b/src/test/ui/destructuring-assignment/struct_destructure_fail.rs @@ -0,0 +1,15 @@ +#![feature(destructuring_assignment)] +struct Struct<S, T> { + 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, ..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/src/test/ui/destructuring-assignment/struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/struct_destructure_fail.stderr new file mode 100644 index 00000000000..4da4698804f --- /dev/null +++ b/src/test/ui/destructuring-assignment/struct_destructure_fail.stderr @@ -0,0 +1,21 @@ +error: functional record updates are not allowed in destructuring assignments + --> $DIR/struct_destructure_fail.rs:12: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:14: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:11:20 + | +LL | Struct { a, b, c } = Struct { a: 0, b: 1 }; + | ^ struct `Struct` does not have this field + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0026`. diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure.rs b/src/test/ui/destructuring-assignment/tuple_struct_destructure.rs new file mode 100644 index 00000000000..106a9b16db4 --- /dev/null +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure.rs @@ -0,0 +1,34 @@ +// run-pass + +#![feature(destructuring_assignment)] + +struct TupleStruct<S, T>(S, T); + +impl<S, T> TupleStruct<S, T> { + fn assign(self, first: &mut S, second: &mut T) { + // Test usage of `Self` instead of the struct name: + Self(*first, *second) = self + } +} + +enum Enum<S, T> { + SingleVariant(S, T) +} + +type Alias<S> = Enum<S, isize>; + +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(..) = TupleStruct(3, 4); + assert_eq!((a, b), (1, 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/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.rs b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.rs new file mode 100644 index 00000000000..61ae42a5175 --- /dev/null +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.rs @@ -0,0 +1,42 @@ +#![feature(destructuring_assignment)] + +struct TupleStruct<S, T>(S, T); + +enum Enum<S, T> { + SingleVariant(S, T) +} + +type Alias<S> = Enum<S, isize>; + +trait Test { + fn test() -> TupleStruct<isize, isize> { + TupleStruct(0, 0) + } +} + +impl Test for Alias<isize> {} + +fn test() -> TupleStruct<isize, isize> { + 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 + Enum::SingleVariant(a, a, b) = Enum::SingleVariant(1, 2); + //~^ ERROR this pattern has 3 fields, 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 + <Alias::<isize> as Test>::test() = TupleStruct(0, 0); + //~^ ERROR invalid left-hand side of assignment +} diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr new file mode 100644 index 00000000000..863eedecf76 --- /dev/null +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -0,0 +1,62 @@ +error: `..` can only be used once per tuple struct or variant pattern + --> $DIR/tuple_struct_destructure_fail.rs:25: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:27: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:30:5 + | +LL | struct TupleStruct<S, T>(S, T); + | ------------------------------- tuple struct defined here +... +LL | TupleStruct(a, a, b) = TupleStruct(1, 2); + | ^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3 + +error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields + --> $DIR/tuple_struct_destructure_fail.rs:32:5 + | +LL | SingleVariant(S, T) + | ------------------- tuple variant defined here +... +LL | Enum::SingleVariant(a, a, b) = Enum::SingleVariant(1, 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3 + +error[E0070]: invalid left-hand side of assignment + --> $DIR/tuple_struct_destructure_fail.rs:36: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:38: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:40:38 + | +LL | <Alias::<isize> as Test>::test() = TupleStruct(0, 0); + | -------------------------------- ^ + | | + | cannot assign to this expression + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0023, E0070. +For more information about an error, try `rustc --explain E0023`. diff --git a/src/test/ui/destructuring-assignment/underscore-range-expr-gating.rs b/src/test/ui/destructuring-assignment/underscore-range-expr-gating.rs new file mode 100644 index 00000000000..b41f2f52a3d --- /dev/null +++ b/src/test/ui/destructuring-assignment/underscore-range-expr-gating.rs @@ -0,0 +1,8 @@ +fn main() {} + +struct S { x : u32 } + +#[cfg(FALSE)] +fn foo() { + S { x: 5, .. }; //~ ERROR destructuring assignments are unstable +} diff --git a/src/test/ui/destructuring-assignment/underscore-range-expr-gating.stderr b/src/test/ui/destructuring-assignment/underscore-range-expr-gating.stderr new file mode 100644 index 00000000000..442e36cd306 --- /dev/null +++ b/src/test/ui/destructuring-assignment/underscore-range-expr-gating.stderr @@ -0,0 +1,12 @@ +error[E0658]: destructuring assignments are unstable + --> $DIR/underscore-range-expr-gating.rs:7:15 + | +LL | S { x: 5, .. }; + | ^^ + | + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-77218.rs b/src/test/ui/issues/issue-77218.rs index bc992c21dca..a6a2401795f 100644 --- a/src/test/ui/issues/issue-77218.rs +++ b/src/test/ui/issues/issue-77218.rs @@ -1,7 +1,11 @@ fn main() { let value = [7u8]; - while Some(0) = value.get(0) { //~ ERROR mismatched types - //~^ NOTE expected `bool`, found `()` - //~| HELP you might have meant to use pattern matching + while Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable + //~| ERROR invalid left-hand side of assignment + //~| ERROR mismatched types + //~| ERROR mismatched types + + // FIXME The following diagnostic should also be emitted + // HELP you might have meant to use pattern matching } } diff --git a/src/test/ui/issues/issue-77218.stderr b/src/test/ui/issues/issue-77218.stderr index eca44725eb2..4f6fbaa2265 100644 --- a/src/test/ui/issues/issue-77218.stderr +++ b/src/test/ui/issues/issue-77218.stderr @@ -1,14 +1,38 @@ +error[E0658]: destructuring assignments are unstable + --> $DIR/issue-77218.rs:3:19 + | +LL | while Some(0) = value.get(0) { + | ------- ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0070]: invalid left-hand side of assignment + --> $DIR/issue-77218.rs:3:19 + | +LL | while Some(0) = value.get(0) { + | - ^ + | | + | cannot assign to this expression + +error[E0308]: mismatched types + --> $DIR/issue-77218.rs:3:16 + | +LL | while Some(0) = value.get(0) { + | ^ + | | + | expected integer, found `&u8` + | help: consider dereferencing the borrow: `*0` + error[E0308]: mismatched types --> $DIR/issue-77218.rs:3:11 | LL | while Some(0) = value.get(0) { | ^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` - | -help: you might have meant to use pattern matching - | -LL | while let Some(0) = value.get(0) { - | ^^^ -error: aborting due to previous error +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0070, E0308, E0658. +For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/suggestions/if-let-typo.rs b/src/test/ui/suggestions/if-let-typo.rs index 87def13c476..688b6e82658 100644 --- a/src/test/ui/suggestions/if-let-typo.rs +++ b/src/test/ui/suggestions/if-let-typo.rs @@ -2,7 +2,12 @@ fn main() { let foo = Some(0); let bar = None; if Some(x) = foo {} //~ ERROR cannot find value `x` in this scope + //~^ ERROR mismatched types + //~^^ ERROR destructuring assignments are unstable if Some(foo) = bar {} //~ ERROR mismatched types + //~^ ERROR destructuring assignments are unstable if 3 = foo {} //~ ERROR mismatched types if Some(3) = foo {} //~ ERROR mismatched types + //~^ ERROR destructuring assignments are unstable + //~^^ ERROR invalid left-hand side of assignment } diff --git a/src/test/ui/suggestions/if-let-typo.stderr b/src/test/ui/suggestions/if-let-typo.stderr index d8e50cae55a..ce1ee0cd06d 100644 --- a/src/test/ui/suggestions/if-let-typo.stderr +++ b/src/test/ui/suggestions/if-let-typo.stderr @@ -9,23 +9,53 @@ help: you might have meant to use pattern matching LL | if let Some(x) = foo {} | ^^^ -error[E0308]: mismatched types - --> $DIR/if-let-typo.rs:5:8 +error[E0658]: destructuring assignments are unstable + --> $DIR/if-let-typo.rs:4:16 + | +LL | if Some(x) = foo {} + | ------- ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0658]: destructuring assignments are unstable + --> $DIR/if-let-typo.rs:7:18 | LL | if Some(foo) = bar {} - | ^^^^^^^^^^^^^^^ expected `bool`, found `()` + | --------- ^ + | | + | cannot assign to this expression | -help: you might have meant to use pattern matching + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0658]: destructuring assignments are unstable + --> $DIR/if-let-typo.rs:10:16 | -LL | if let Some(foo) = bar {} - | ^^^ -help: you might have meant to compare for equality +LL | if Some(3) = foo {} + | ------- ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/if-let-typo.rs:4:8 + | +LL | if Some(x) = foo {} + | ^^^^^^^^^^^^^ expected `bool`, found `()` + +error[E0308]: mismatched types + --> $DIR/if-let-typo.rs:7:8 | -LL | if Some(foo) == bar {} - | ^^ +LL | if Some(foo) = bar {} + | ^^^^^^^^^^^^^^^ expected `bool`, found `()` error[E0308]: mismatched types - --> $DIR/if-let-typo.rs:6:8 + --> $DIR/if-let-typo.rs:9:8 | LL | if 3 = foo {} | ^^^^^^^ expected `bool`, found `()` @@ -35,22 +65,21 @@ help: you might have meant to use pattern matching LL | if let 3 = foo {} | ^^^ +error[E0070]: invalid left-hand side of assignment + --> $DIR/if-let-typo.rs:10:16 + | +LL | if Some(3) = foo {} + | - ^ + | | + | cannot assign to this expression + error[E0308]: mismatched types - --> $DIR/if-let-typo.rs:7:8 + --> $DIR/if-let-typo.rs:10:8 | LL | if Some(3) = foo {} | ^^^^^^^^^^^^^ expected `bool`, found `()` - | -help: you might have meant to use pattern matching - | -LL | if let Some(3) = foo {} - | ^^^ -help: you might have meant to compare for equality - | -LL | if Some(3) == foo {} - | ^^ -error: aborting due to 4 previous errors +error: aborting due to 9 previous errors -Some errors have detailed explanations: E0308, E0425. -For more information about an error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0070, E0308, E0425, E0658. +For more information about an error, try `rustc --explain E0070`. diff --git a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs index b68e33f101d..9050b9b2d9a 100644 --- a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs +++ b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs @@ -107,6 +107,15 @@ pub fn eq_expr_opt(l: &Option<P<Expr>>, r: &Option<P<Expr>>) -> bool { both(l, r, |l, r| eq_expr(l, r)) } +pub fn eq_struct_rest(l: &StructRest, r: &StructRest) -> bool { + match (l, r) { + (StructRest::Base(lb), StructRest::Base(rb)) => eq_expr(lb, rb), + (StructRest::Rest(_), StructRest::Rest(_)) => true, + (StructRest::None, StructRest::None) => true, + _ => false, + } +} + pub fn eq_expr(l: &Expr, r: &Expr) -> bool { use ExprKind::*; if !over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) { @@ -150,7 +159,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { (Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp), (MacCall(l), MacCall(r)) => eq_mac_call(l, r), (Struct(lp, lfs, lb), Struct(rp, rfs, rb)) => { - eq_path(lp, rp) && eq_expr_opt(lb, rb) && unordered_over(lfs, rfs, |l, r| eq_field(l, r)) + eq_path(lp, rp) && eq_struct_rest(lb, rb) && unordered_over(lfs, rfs, |l, r| eq_field(l, r)) }, _ => false, } diff --git a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr index 8241dcd8feb..c38727316cd 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr @@ -1,3 +1,14 @@ +error[E0658]: destructuring assignments are unstable + --> $DIR/ice-6250.rs:12:25 + | +LL | Some(reference) = cache.data.get(key) { + | --------------- ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + error[E0601]: `main` function not found in crate `ice_6250` --> $DIR/ice-6250.rs:4:1 | @@ -11,17 +22,21 @@ LL | | } | |_^ consider adding a `main` function to `$DIR/ice-6250.rs` error[E0308]: mismatched types + --> $DIR/ice-6250.rs:12:14 + | +LL | Some(reference) = cache.data.get(key) { + | ^^^^^^^^^ + | | + | expected integer, found `&i32` + | help: consider dereferencing the borrow: `*reference` + +error[E0308]: mismatched types --> $DIR/ice-6250.rs:12:9 | LL | Some(reference) = cache.data.get(key) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` - | -help: you might have meant to use pattern matching - | -LL | let Some(reference) = cache.data.get(key) { - | ^^^ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0308, E0601. +Some errors have detailed explanations: E0308, E0601, E0658. For more information about an error, try `rustc --explain E0308`. |
