about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-11-12 23:23:56 +0000
committerbors <bors@rust-lang.org>2020-11-12 23:23:56 +0000
commite80ee05bfc135d7d800f3fcc89bc005d6858cd9b (patch)
tree4b8950bc77d07a409c0c444ac07d6816785eede1 /src/test
parent9722952f0bed5815cb22cb4878be09fb39f92804 (diff)
parent38ca6e3561dbd2465cd604feeed93cf82580745c (diff)
downloadrust-e80ee05bfc135d7d800f3fcc89bc005d6858cd9b.tar.gz
rust-e80ee05bfc135d7d800f3fcc89bc005d6858cd9b.zip
Auto merge of #78998 - m-ou-se:rollup-6r4pt9m, r=m-ou-se
Rollup of 7 pull requests

Successful merges:

 - #76730 (Fix rustdoc rendering of by-value mutable arguments in async fn)
 - #78836 (Implement destructuring assignment for structs and slices)
 - #78857 (Improve BinaryHeap performance)
 - #78950 (Add asm register information for SPIR-V)
 - #78970 (update rustfmt to v1.4.25)
 - #78972 (Update cargo)
 - #78987 (extend min_const_generics param ty tests)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src/test')
-rw-r--r--src/test/rustdoc/async-fn.rs14
-rw-r--r--src/test/rustdoc/const-generics/const-generics-docs.rs3
-rw-r--r--src/test/ui-fulldeps/pprust-expr-roundtrip.rs2
-rw-r--r--src/test/ui/const-generics/core-types.rs51
-rw-r--r--src/test/ui/const-generics/min_const_generics/complex-types.rs11
-rw-r--r--src/test/ui/const-generics/min_const_generics/complex-types.stderr37
-rw-r--r--src/test/ui/destructuring-assignment/nested_destructure.rs17
-rw-r--r--src/test/ui/destructuring-assignment/note-unsupported.rs7
-rw-r--r--src/test/ui/destructuring-assignment/note-unsupported.stderr69
-rw-r--r--src/test/ui/destructuring-assignment/slice_destructure.rs15
-rw-r--r--src/test/ui/destructuring-assignment/slice_destructure_fail.rs7
-rw-r--r--src/test/ui/destructuring-assignment/slice_destructure_fail.stderr17
-rw-r--r--src/test/ui/destructuring-assignment/struct_destructure.rs19
-rw-r--r--src/test/ui/destructuring-assignment/struct_destructure_fail.rs15
-rw-r--r--src/test/ui/destructuring-assignment/struct_destructure_fail.stderr21
-rw-r--r--src/test/ui/destructuring-assignment/tuple_struct_destructure.rs34
-rw-r--r--src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.rs42
-rw-r--r--src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr62
-rw-r--r--src/test/ui/destructuring-assignment/underscore-range-expr-gating.rs8
-rw-r--r--src/test/ui/destructuring-assignment/underscore-range-expr-gating.stderr12
-rw-r--r--src/test/ui/issues/issue-77218.rs10
-rw-r--r--src/test/ui/issues/issue-77218.stderr38
-rw-r--r--src/test/ui/suggestions/if-let-typo.rs5
-rw-r--r--src/test/ui/suggestions/if-let-typo.stderr75
24 files changed, 520 insertions, 71 deletions
diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs
index 5a03e821e8a..e7a7d1831f7 100644
--- a/src/test/rustdoc/async-fn.rs
+++ b/src/test/rustdoc/async-fn.rs
@@ -1,4 +1,5 @@
 // edition:2018
+#![feature(min_const_generics)]
 
 // @has async_fn/fn.foo.html '//pre[@class="rust fn"]' 'pub async fn foo() -> Option<Foo>'
 pub async fn foo() -> Option<Foo> {
@@ -20,6 +21,12 @@ pub async unsafe fn qux() -> char {
     '⚠'
 }
 
+// @has async_fn/fn.mut_args.html '//pre[@class="rust fn"]' 'pub async fn mut_args(a: usize)'
+pub async fn mut_args(mut a: usize) {}
+
+// @has async_fn/fn.mut_ref.html '//pre[@class="rust fn"]' 'pub async fn mut_ref(x: i32)'
+pub async fn mut_ref(ref mut x: i32) {}
+
 trait Bar {}
 
 impl Bar for () {}
@@ -32,9 +39,16 @@ pub async fn quux() -> impl Bar {
 // @has async_fn/struct.Foo.html
 // @matches - '//code' 'pub async fn f\(\)$'
 // @matches - '//code' 'pub async unsafe fn g\(\)$'
+// @matches - '//code' 'pub async fn mut_self\(self, first: usize\)$'
 pub struct Foo;
 
 impl Foo {
     pub async fn f() {}
     pub async unsafe fn g() {}
+    pub async fn mut_self(mut self, mut first: usize) {}
 }
+
+pub trait Trait<const N: usize> {}
+// @has async_fn/fn.const_generics.html
+// @has - '//pre[@class="rust fn"]' 'pub async fn const_generics<const N: usize>(_: impl Trait<N>)'
+pub async fn const_generics<const N: usize>(_: impl Trait<N>) {}
diff --git a/src/test/rustdoc/const-generics/const-generics-docs.rs b/src/test/rustdoc/const-generics/const-generics-docs.rs
index 8dcba36600d..9c68e067c6f 100644
--- a/src/test/rustdoc/const-generics/const-generics-docs.rs
+++ b/src/test/rustdoc/const-generics/const-generics-docs.rs
@@ -70,8 +70,7 @@ pub async fn a_sink<const N: usize>(v: [u8; N]) -> impl Trait<N> {
 }
 
 // @has foo/fn.b_sink.html '//pre[@class="rust fn"]' \
-//      'pub async fn b_sink<const N: usize>(__arg0: impl Trait<N>)'
-// FIXME(const_generics): This should be `_` not `__arg0`.
+//      'pub async fn b_sink<const N: usize>(_: impl Trait<N>)'
 pub async fn b_sink<const N: usize>(_: impl Trait<N>) {}
 
 // @has foo/fn.concrete.html '//pre[@class="rust fn"]' \
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/const-generics/core-types.rs b/src/test/ui/const-generics/core-types.rs
new file mode 100644
index 00000000000..c4351e059de
--- /dev/null
+++ b/src/test/ui/const-generics/core-types.rs
@@ -0,0 +1,51 @@
+// Check that all types allowed with `min_const_generics` work.
+// run-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
+struct A<const N: u8>;
+struct B<const N: u16>;
+struct C<const N: u32>;
+struct D<const N: u64>;
+struct E<const N: u128>;
+struct F<const N: usize>;
+struct G<const N: i8>;
+struct H<const N: i16>;
+struct I<const N: i32>;
+struct J<const N: i64>;
+struct K<const N: i128>;
+struct L<const N: isize>;
+struct M<const N: char>;
+struct N<const N: bool>;
+
+fn main() {
+    let _ = A::<{u8::MIN}>;
+    let _ = A::<{u8::MAX}>;
+    let _ = B::<{u16::MIN}>;
+    let _ = B::<{u16::MAX}>;
+    let _ = C::<{u32::MIN}>;
+    let _ = C::<{u32::MAX}>;
+    let _ = D::<{u64::MIN}>;
+    let _ = D::<{u64::MAX}>;
+    let _ = E::<{u128::MIN}>;
+    let _ = E::<{u128::MAX}>;
+    let _ = F::<{usize::MIN}>;
+    let _ = F::<{usize::MAX}>;
+    let _ = G::<{i8::MIN}>;
+    let _ = G::<{i8::MAX}>;
+    let _ = H::<{i16::MIN}>;
+    let _ = H::<{i16::MAX}>;
+    let _ = I::<{i32::MIN}>;
+    let _ = I::<{i32::MAX}>;
+    let _ = J::<{i64::MIN}>;
+    let _ = J::<{i64::MAX}>;
+    let _ = K::<{i128::MIN}>;
+    let _ = K::<{i128::MAX}>;
+    let _ = L::<{isize::MIN}>;
+    let _ = L::<{isize::MAX}>;
+    let _ = M::<'A'>;
+    let _ = N::<true>;
+}
diff --git a/src/test/ui/const-generics/min_const_generics/complex-types.rs b/src/test/ui/const-generics/min_const_generics/complex-types.rs
index 98bc99d0194..2aaf2c39875 100644
--- a/src/test/ui/const-generics/min_const_generics/complex-types.rs
+++ b/src/test/ui/const-generics/min_const_generics/complex-types.rs
@@ -1,4 +1,5 @@
 #![feature(min_const_generics)]
+#![feature(never_type)]
 
 struct Foo<const N: [u8; 0]>;
 //~^ ERROR `[u8; 0]` is forbidden
@@ -14,4 +15,14 @@ struct Fez<const N: No>;
 struct Faz<const N: &'static u8>;
 //~^ ERROR `&'static u8` is forbidden
 
+struct Fiz<const N: !>;
+//~^ ERROR `!` is forbidden
+
+enum Goo<const N: ()> { A, B }
+//~^ ERROR `()` is forbidden
+
+union Boo<const N: ()> { a: () }
+//~^ ERROR `()` is forbidden
+
+
 fn main() {}
diff --git a/src/test/ui/const-generics/min_const_generics/complex-types.stderr b/src/test/ui/const-generics/min_const_generics/complex-types.stderr
index 4772aaf1b3e..52ed3c1c6ee 100644
--- a/src/test/ui/const-generics/min_const_generics/complex-types.stderr
+++ b/src/test/ui/const-generics/min_const_generics/complex-types.stderr
@@ -1,5 +1,5 @@
 error: `[u8; 0]` is forbidden as the type of a const generic parameter
-  --> $DIR/complex-types.rs:3:21
+  --> $DIR/complex-types.rs:4:21
    |
 LL | struct Foo<const N: [u8; 0]>;
    |                     ^^^^^^^
@@ -8,7 +8,7 @@ LL | struct Foo<const N: [u8; 0]>;
    = note: more complex types are supported with `#[feature(const_generics)]`
 
 error: `()` is forbidden as the type of a const generic parameter
-  --> $DIR/complex-types.rs:6:21
+  --> $DIR/complex-types.rs:7:21
    |
 LL | struct Bar<const N: ()>;
    |                     ^^
@@ -17,7 +17,7 @@ LL | struct Bar<const N: ()>;
    = note: more complex types are supported with `#[feature(const_generics)]`
 
 error: `No` is forbidden as the type of a const generic parameter
-  --> $DIR/complex-types.rs:11:21
+  --> $DIR/complex-types.rs:12:21
    |
 LL | struct Fez<const N: No>;
    |                     ^^
@@ -26,7 +26,7 @@ LL | struct Fez<const N: No>;
    = note: more complex types are supported with `#[feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
-  --> $DIR/complex-types.rs:14:21
+  --> $DIR/complex-types.rs:15:21
    |
 LL | struct Faz<const N: &'static u8>;
    |                     ^^^^^^^^^^^
@@ -34,5 +34,32 @@ LL | struct Faz<const N: &'static u8>;
    = note: the only supported types are integers, `bool` and `char`
    = note: more complex types are supported with `#[feature(const_generics)]`
 
-error: aborting due to 4 previous errors
+error: `!` is forbidden as the type of a const generic parameter
+  --> $DIR/complex-types.rs:18:21
+   |
+LL | struct Fiz<const N: !>;
+   |                     ^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: `()` is forbidden as the type of a const generic parameter
+  --> $DIR/complex-types.rs:21:19
+   |
+LL | enum Goo<const N: ()> { A, B }
+   |                   ^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: `()` is forbidden as the type of a const generic parameter
+  --> $DIR/complex-types.rs:24:20
+   |
+LL | union Boo<const N: ()> { a: () }
+   |                    ^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 7 previous errors
 
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`.