diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 3e953729aabec..328086af183d6 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1192,6 +1192,7 @@ impl Expr { ExprKind::Field(..) => ExprPrecedence::Field, ExprKind::Index(..) => ExprPrecedence::Index, ExprKind::Range(..) => ExprPrecedence::Range, + ExprKind::Underscore => ExprPrecedence::Path, ExprKind::Path(..) => ExprPrecedence::Path, ExprKind::AddrOf(..) => ExprPrecedence::AddrOf, ExprKind::Break(..) => ExprPrecedence::Break, @@ -1324,6 +1325,8 @@ pub enum ExprKind { Index(P, P), /// A range (e.g., `1..2`, `1..`, `..2`, `1..=2`, `..=2`; and `..` in destructuring assingment). Range(Option>, Option>, RangeLimits), + /// An underscore, used in destructuring assignment to ignore a value. + Underscore, /// Variable reference, possibly containing `::` and/or type /// parameters (e.g., `foo::bar::`). diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 26097980e8be4..ddae0ab03e404 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1232,6 +1232,7 @@ pub fn noop_visit_expr( visit_opt(e1, |e1| vis.visit_expr(e1)); visit_opt(e2, |e2| vis.visit_expr(e2)); } + ExprKind::Underscore => {} ExprKind::Path(qself, path) => { vis.visit_qself(qself); vis.visit_path(path); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 49b521afcdc78..560064182e18d 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -806,6 +806,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { walk_list!(visitor, visit_expr, start); walk_list!(visitor, visit_expr, end); } + ExprKind::Underscore => {} ExprKind::Path(ref maybe_qself, ref path) => { if let Some(ref qself) = *maybe_qself { visitor.visit_ty(&qself.ty); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 330776fc8c598..ecbe97bd45a0b 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -164,6 +164,16 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Range(ref e1, ref e2, lims) => { self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims) } + ExprKind::Underscore => { + self.sess + .struct_span_err( + e.span, + "in expressions, `_` can only be used on the left-hand side of an assignment", + ) + .span_label(e.span, "`_` not allowed here") + .emit(); + hir::ExprKind::Err + } ExprKind::Path(ref qself, ref path) => { let qpath = self.lower_qpath( e.id, @@ -863,7 +873,10 @@ impl<'hir> LoweringContext<'_, 'hir> { // Return early in case of an ordinary assignment. fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool { match &lhs.kind { - ExprKind::Array(..) | ExprKind::Struct(..) | ExprKind::Tup(..) => false, + ExprKind::Array(..) + | ExprKind::Struct(..) + | ExprKind::Tup(..) + | ExprKind::Underscore => false, // Check for tuple struct constructor. ExprKind::Call(callee, ..) => lower_ctx.extract_tuple_struct_path(callee).is_none(), ExprKind::Paren(e) => { @@ -943,6 +956,10 @@ impl<'hir> LoweringContext<'_, 'hir> { assignments: &mut Vec>, ) -> &'hir hir::Pat<'hir> { match &lhs.kind { + // Underscore pattern. + ExprKind::Underscore => { + return self.pat_without_dbm(lhs.span, hir::PatKind::Wild); + } // Slice patterns. ExprKind::Array(elements) => { let (pats, rest) = diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 2831675cb3671..181783441f3ff 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -630,7 +630,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(const_trait_impl, "const trait impls are experimental"); gate_all!(half_open_range_patterns, "half-open range patterns are unstable"); gate_all!(inline_const, "inline-const is experimental"); - gate_all!(destructuring_assignment, "destructuring assignments are unstable"); + if sess.parse_sess.span_diagnostic.err_count() == 0 { + // Errors for `destructuring_assignment` can get quite noisy, especially where `_` is + // involved, so we only emit errors where there are no other parsing errors. + gate_all!(destructuring_assignment, "destructuring assignments are unstable"); + } // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index a566200c33896..887b60f98f75f 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -2068,6 +2068,7 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(e, fake_prec); } } + ast::ExprKind::Underscore => self.s.word("_"), ast::ExprKind::Path(None, ref path) => self.print_path(path, true, 0), ast::ExprKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, true), ast::ExprKind::Break(opt_label, ref opt_expr) => { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 188bf227c4249..ffbf786491df2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1089,6 +1089,9 @@ impl<'a> Parser<'a> { self.parse_yield_expr(attrs) } else if self.eat_keyword(kw::Let) { self.parse_let_expr(attrs) + } else if self.eat_keyword(kw::Underscore) { + self.sess.gated_spans.gate(sym::destructuring_assignment, self.prev_token.span); + Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore, attrs)) } else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) { // Don't complain about bare semicolons after unclosed braces // recovery in order to keep the error count down. Fixing the diff --git a/src/test/ui/cross/cross-file-errors/main.rs b/src/test/ui/cross/cross-file-errors/main.rs index 74e9461803c52..1902ab94d4c0d 100644 --- a/src/test/ui/cross/cross-file-errors/main.rs +++ b/src/test/ui/cross/cross-file-errors/main.rs @@ -3,5 +3,6 @@ mod underscore; fn main() { underscore!(); - //~^ ERROR expected expression, found reserved identifier `_` + //~^ ERROR `_` can only be used on the left-hand side of an assignment + //~| ERROR destructuring assignments are unstable } diff --git a/src/test/ui/cross/cross-file-errors/main.stderr b/src/test/ui/cross/cross-file-errors/main.stderr index f9101d8a583d3..b8658745060b0 100644 --- a/src/test/ui/cross/cross-file-errors/main.stderr +++ b/src/test/ui/cross/cross-file-errors/main.stderr @@ -1,15 +1,31 @@ -error: expected expression, found reserved identifier `_` +error[E0658]: destructuring assignments are unstable --> $DIR/underscore.rs:8:9 | LL | _ - | ^ expected expression + | ^ | ::: $DIR/main.rs:5:5 | LL | underscore!(); | -------------- in this macro invocation | + = note: see issue #71126 for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/underscore.rs:8:9 + | +LL | _ + | ^ `_` not allowed here + | + ::: $DIR/main.rs:5:5 + | +LL | underscore!(); + | -------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/destructuring-assignment/nested_destructure.rs b/src/test/ui/destructuring-assignment/nested_destructure.rs index 393dfc16c0a1c..0d45ff7da7249 100644 --- a/src/test/ui/destructuring-assignment/nested_destructure.rs +++ b/src/test/ui/destructuring-assignment/nested_destructure.rs @@ -14,4 +14,7 @@ fn main() { 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/src/test/ui/destructuring-assignment/slice_destructure.rs b/src/test/ui/destructuring-assignment/slice_destructure.rs index 3dd10aff19c72..76cdc1260fcde 100644 --- a/src/test/ui/destructuring-assignment/slice_destructure.rs +++ b/src/test/ui/destructuring-assignment/slice_destructure.rs @@ -9,6 +9,8 @@ fn main() { 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/src/test/ui/destructuring-assignment/slice_destructure_fail.rs b/src/test/ui/destructuring-assignment/slice_destructure_fail.rs index f636ea3511c26..90d93892f7f22 100644 --- a/src/test/ui/destructuring-assignment/slice_destructure_fail.rs +++ b/src/test/ui/destructuring-assignment/slice_destructure_fail.rs @@ -4,4 +4,5 @@ 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/src/test/ui/destructuring-assignment/slice_destructure_fail.stderr b/src/test/ui/destructuring-assignment/slice_destructure_fail.stderr index 728687deb8bbb..cc412c72df51d 100644 --- a/src/test/ui/destructuring-assignment/slice_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/slice_destructure_fail.stderr @@ -12,6 +12,12 @@ error[E0527]: pattern requires 3 elements but array has 2 LL | [a, a, b] = [1, 2]; | ^^^^^^^^^ expected 2 elements -error: aborting due to 2 previous errors +error[E0527]: pattern requires 1 element but array has 2 + --> $DIR/slice_destructure_fail.rs:7: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/src/test/ui/destructuring-assignment/struct_destructure.rs b/src/test/ui/destructuring-assignment/struct_destructure.rs index b3a96ee157346..2bcbd9d0d742e 100644 --- a/src/test/ui/destructuring-assignment/struct_destructure.rs +++ b/src/test/ui/destructuring-assignment/struct_destructure.rs @@ -12,8 +12,10 @@ fn main() { 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, 1)); + assert_eq!((a, b), (1, 2)); Struct { .. } = Struct { a: 1, b: 4 }; - assert_eq!((a, b), (1, 1)); + assert_eq!((a, b), (1, 2)); } diff --git a/src/test/ui/destructuring-assignment/struct_destructure_fail.rs b/src/test/ui/destructuring-assignment/struct_destructure_fail.rs index c22695ed38849..4aa327b61f497 100644 --- a/src/test/ui/destructuring-assignment/struct_destructure_fail.rs +++ b/src/test/ui/destructuring-assignment/struct_destructure_fail.rs @@ -9,6 +9,8 @@ fn main() { 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/src/test/ui/destructuring-assignment/struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/struct_destructure_fail.stderr index 4da4698804f1a..81661a357e750 100644 --- a/src/test/ui/destructuring-assignment/struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/struct_destructure_fail.stderr @@ -1,11 +1,19 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/struct_destructure_fail.rs:12: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:12:19 + --> $DIR/struct_destructure_fail.rs:14: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 + --> $DIR/struct_destructure_fail.rs:16:19 | LL | Struct { a, .. }; | ^ add a base expression here @@ -16,6 +24,22 @@ error[E0026]: struct `Struct` does not have a field named `c` LL | Struct { a, b, c } = Struct { a: 0, b: 1 }; | ^ struct `Struct` does not have this field -error: aborting due to 3 previous errors +error[E0027]: pattern does not mention field `b` + --> $DIR/struct_destructure_fail.rs:12: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 -For more information about this error, try `rustc --explain E0026`. +Some errors have detailed explanations: E0026, E0027. +For more information about an error, try `rustc --explain E0026`. diff --git a/src/test/ui/destructuring-assignment/tuple_destructure.rs b/src/test/ui/destructuring-assignment/tuple_destructure.rs index 16aafc4693f3f..2096182d421cf 100644 --- a/src/test/ui/destructuring-assignment/tuple_destructure.rs +++ b/src/test/ui/destructuring-assignment/tuple_destructure.rs @@ -16,6 +16,8 @@ fn main() { 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); diff --git a/src/test/ui/destructuring-assignment/tuple_destructure_fail.rs b/src/test/ui/destructuring-assignment/tuple_destructure_fail.rs index b76f4968e6249..5524e91dc401b 100644 --- a/src/test/ui/destructuring-assignment/tuple_destructure_fail.rs +++ b/src/test/ui/destructuring-assignment/tuple_destructure_fail.rs @@ -7,4 +7,5 @@ fn main() { (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/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr index a60e1cb1eec62..1146b88278d49 100644 --- a/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr @@ -25,7 +25,18 @@ LL | (C, ..) = (0,1); | | | cannot assign to this expression -error: aborting due to 3 previous errors +error[E0308]: mismatched types + --> $DIR/tuple_destructure_fail.rs:10:5 + | +LL | (_,) = (1, 2); + | ^^^^ ------ this expression has type `({integer}, {integer})` + | | + | expected a tuple with 2 elements, found one with 1 element + | + = note: expected type `({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/src/test/ui/destructuring-assignment/tuple_struct_destructure.rs b/src/test/ui/destructuring-assignment/tuple_struct_destructure.rs index 106a9b16db459..7b5c5ad2bae26 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure.rs +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure.rs @@ -23,8 +23,10 @@ fn main() { 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), (1, 2)); + 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); diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.rs b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.rs index 61ae42a51751f..c39db06117767 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.rs +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.rs @@ -29,8 +29,12 @@ fn main() { 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); diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr index 863eedecf7697..0e7174e5b19d6 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -23,17 +23,35 @@ LL | struct TupleStruct(S, T); 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 +error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields --> $DIR/tuple_struct_destructure_fail.rs:32:5 | +LL | struct TupleStruct(S, T); + | ------------------------------- tuple struct defined here +... +LL | TupleStruct(_) = TupleStruct(1, 2); + | ^^^^^^^^^^^^^^ expected 2 fields, found 1 + +error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields + --> $DIR/tuple_struct_destructure_fail.rs:34: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[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields + --> $DIR/tuple_struct_destructure_fail.rs:36:5 + | +LL | SingleVariant(S, T) + | ------------------- tuple variant defined here +... +LL | Enum::SingleVariant(_) = Enum::SingleVariant(1, 2); + | ^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 1 + error[E0070]: invalid left-hand side of assignment - --> $DIR/tuple_struct_destructure_fail.rs:36:12 + --> $DIR/tuple_struct_destructure_fail.rs:40:12 | LL | test() = TupleStruct(0, 0); | ------ ^ @@ -41,7 +59,7 @@ 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 + --> $DIR/tuple_struct_destructure_fail.rs:42:14 | LL | (test)() = TupleStruct(0, 0); | -------- ^ @@ -49,14 +67,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 + --> $DIR/tuple_struct_destructure_fail.rs:44:38 | LL | as Test>::test() = TupleStruct(0, 0); | -------------------------------- ^ | | | cannot assign to this expression -error: aborting due to 7 previous errors +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/src/test/ui/destructuring-assignment/underscore-range-expr-gating.rs b/src/test/ui/destructuring-assignment/underscore-range-expr-gating.rs index b41f2f52a3d6f..4ed4f56702c32 100644 --- a/src/test/ui/destructuring-assignment/underscore-range-expr-gating.rs +++ b/src/test/ui/destructuring-assignment/underscore-range-expr-gating.rs @@ -4,5 +4,7 @@ struct S { x : u32 } #[cfg(FALSE)] fn foo() { + _; //~ ERROR destructuring assignments are unstable + 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 index 442e36cd3065e..a5ed761a01c33 100644 --- a/src/test/ui/destructuring-assignment/underscore-range-expr-gating.stderr +++ b/src/test/ui/destructuring-assignment/underscore-range-expr-gating.stderr @@ -1,5 +1,14 @@ error[E0658]: destructuring assignments are unstable - --> $DIR/underscore-range-expr-gating.rs:7:15 + --> $DIR/underscore-range-expr-gating.rs:7:5 + | +LL | _; + | ^ + | + = note: see issue #71126 for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0658]: destructuring assignments are unstable + --> $DIR/underscore-range-expr-gating.rs:9:15 | LL | S { x: 5, .. }; | ^^ @@ -7,6 +16,6 @@ LL | S { x: 5, .. }; = note: see issue #71126 for more information = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs b/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs index a8ea3faefe876..00638e04f5db9 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs +++ b/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs @@ -8,12 +8,18 @@ trait T { fn main() { let _: usize = foo(_, _); - //~^ ERROR expected expression - //~| ERROR expected expression + //~^ ERROR `_` can only be used on the left-hand side of an assignment + //~| ERROR `_` can only be used on the left-hand side of an assignment + //~| ERROR destructuring assignments are unstable + //~| ERROR destructuring assignments are unstable let _: S = S(_, _); - //~^ ERROR expected expression - //~| ERROR expected expression + //~^ ERROR `_` can only be used on the left-hand side of an assignment + //~| ERROR `_` can only be used on the left-hand side of an assignment + //~| ERROR destructuring assignments are unstable + //~| ERROR destructuring assignments are unstable let _: usize = T::baz(_, _); - //~^ ERROR expected expression - //~| ERROR expected expression + //~^ ERROR `_` can only be used on the left-hand side of an assignment + //~| ERROR `_` can only be used on the left-hand side of an assignment + //~| ERROR destructuring assignments are unstable + //~| ERROR destructuring assignments are unstable } diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr index a6d1c4b859f2f..248fa6b9c9cb2 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr @@ -1,38 +1,93 @@ -error: expected expression, found reserved identifier `_` +error[E0658]: destructuring assignments are unstable --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:24 | LL | let _: usize = foo(_, _); - | ^ expected expression + | ^ + | + = note: see issue #71126 for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0658]: destructuring assignments are unstable + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:27 + | +LL | let _: usize = foo(_, _); + | ^ + | + = note: see issue #71126 for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0658]: destructuring assignments are unstable + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:15:18 + | +LL | let _: S = S(_, _); + | ^ + | + = note: see issue #71126 for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0658]: destructuring assignments are unstable + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:15:21 + | +LL | let _: S = S(_, _); + | ^ + | + = note: see issue #71126 for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0658]: destructuring assignments are unstable + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:20:27 + | +LL | let _: usize = T::baz(_, _); + | ^ + | + = note: see issue #71126 for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0658]: destructuring assignments are unstable + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:20:30 + | +LL | let _: usize = T::baz(_, _); + | ^ + | + = note: see issue #71126 for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:24 + | +LL | let _: usize = foo(_, _); + | ^ `_` not allowed here -error: expected expression, found reserved identifier `_` +error: in expressions, `_` can only be used on the left-hand side of an assignment --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:27 | LL | let _: usize = foo(_, _); - | ^ expected expression + | ^ `_` not allowed here -error: expected expression, found reserved identifier `_` - --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:18 +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:15:18 | LL | let _: S = S(_, _); - | ^ expected expression + | ^ `_` not allowed here -error: expected expression, found reserved identifier `_` - --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:21 +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:15:21 | LL | let _: S = S(_, _); - | ^ expected expression + | ^ `_` not allowed here -error: expected expression, found reserved identifier `_` - --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:27 +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:20:27 | LL | let _: usize = T::baz(_, _); - | ^ expected expression + | ^ `_` not allowed here -error: expected expression, found reserved identifier `_` - --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:30 +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:20:30 | LL | let _: usize = T::baz(_, _); - | ^ expected expression + | ^ `_` not allowed here -error: aborting due to 6 previous errors +error: aborting due to 12 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/src/tools/clippy/clippy_lints/src/utils/sugg.rs b/src/tools/clippy/clippy_lints/src/utils/sugg.rs index 625120b880eb5..1fcd41e4dbfed 100644 --- a/src/tools/clippy/clippy_lints/src/utils/sugg.rs +++ b/src/tools/clippy/clippy_lints/src/utils/sugg.rs @@ -170,6 +170,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::MacCall(..) | ast::ExprKind::MethodCall(..) | ast::ExprKind::Paren(..) + | ast::ExprKind::Underscore | ast::ExprKind::Path(..) | ast::ExprKind::Repeat(..) | ast::ExprKind::Ret(..)