From a5991c57cf4430d1f67886637c65f2178ff1b372 Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 22 Dec 2019 18:18:49 +0000 Subject: [PATCH 1/7] Add the full issue reference to equality constraints in `where` clauses --- src/librustc_passes/ast_validation.rs | 10 ++++++++-- .../ui/where-clauses/where-equality-constraints.rs | 4 ++-- .../ui/where-clauses/where-equality-constraints.stderr | 8 ++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index ee6a67802ade3..1d5e65c6d27cd 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -737,8 +737,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { for predicate in &generics.where_clause.predicates { if let WherePredicate::EqPredicate(ref predicate) = *predicate { self.err_handler() - .span_err(predicate.span, "equality constraints are not yet \ - supported in where clauses (see #20041)"); + .struct_span_err( + predicate.span, + "equality constraints are not yet supported in `where` clauses", + ) + .note( + "for more information, see https://github.com/rust-lang/rust/issues/20041", + ) + .emit(); } } diff --git a/src/test/ui/where-clauses/where-equality-constraints.rs b/src/test/ui/where-clauses/where-equality-constraints.rs index f2349144b88ae..8828f09d92d33 100644 --- a/src/test/ui/where-clauses/where-equality-constraints.rs +++ b/src/test/ui/where-clauses/where-equality-constraints.rs @@ -1,6 +1,6 @@ fn f() where u8 = u16 {} -//~^ ERROR equality constraints are not yet supported in where clauses +//~^ ERROR equality constraints are not yet supported in `where` clauses fn g() where for<'a> &'static (u8,) == u16, {} -//~^ ERROR equality constraints are not yet supported in where clauses +//~^ ERROR equality constraints are not yet supported in `where` clauses fn main() {} diff --git a/src/test/ui/where-clauses/where-equality-constraints.stderr b/src/test/ui/where-clauses/where-equality-constraints.stderr index 220447079c629..c0241fe708f64 100644 --- a/src/test/ui/where-clauses/where-equality-constraints.stderr +++ b/src/test/ui/where-clauses/where-equality-constraints.stderr @@ -1,14 +1,18 @@ -error: equality constraints are not yet supported in where clauses (see #20041) +error: equality constraints are not yet supported in `where` clauses --> $DIR/where-equality-constraints.rs:1:14 | LL | fn f() where u8 = u16 {} | ^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/20041 -error: equality constraints are not yet supported in where clauses (see #20041) +error: equality constraints are not yet supported in `where` clauses --> $DIR/where-equality-constraints.rs:3:14 | LL | fn g() where for<'a> &'static (u8,) == u16, {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/20041 error: aborting due to 2 previous errors From b7bfdbe68147f2ea8ca4870270643180bef76e02 Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 22 Dec 2019 18:42:15 +0000 Subject: [PATCH 2/7] Improve invalid assignment error --- src/librustc_typeck/check/expr.rs | 9 ++++-- src/librustc_typeck/check/op.rs | 8 ++--- src/test/ui/bad/bad-expr-lhs.rs | 10 +++--- src/test/ui/bad/bad-expr-lhs.stderr | 32 ++++++++++++------- src/test/ui/error-codes/E0067.stderr | 8 +++-- src/test/ui/error-codes/E0070.stderr | 18 +++++++---- src/test/ui/issues/issue-13407.rs | 2 +- src/test/ui/issues/issue-13407.stderr | 6 ++-- src/test/ui/issues/issue-26093.rs | 4 ++- src/test/ui/issues/issue-26093.stderr | 26 ++++++++++++--- src/test/ui/issues/issue-34334.rs | 2 +- src/test/ui/issues/issue-34334.stderr | 6 ++-- .../type-check/assignment-expected-bool.rs | 2 +- .../assignment-expected-bool.stderr | 6 ++-- .../ui/type/type-check/assignment-in-if.rs | 2 +- 15 files changed, 92 insertions(+), 49 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 6ecf3ccd6e7ed..27f6b3cb45f4b 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -753,9 +753,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } err.emit(); } else if !lhs.is_syntactic_place_expr() { - struct_span_err!(self.tcx.sess, expr.span, E0070, "invalid left-hand side expression") - .span_label(expr.span, "left-hand of expression not valid") - .emit(); + struct_span_err!( + self.tcx.sess, + expr.span, + E0070, + "invalid left-hand side of assignment", + ).span_label(lhs.span, "cannot assign to this expression").emit(); } self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized); diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 53475569b2c3f..eeee7dea4d1c1 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -36,12 +36,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !lhs_expr.is_syntactic_place_expr() { struct_span_err!( self.tcx.sess, - lhs_expr.span, + op.span, E0067, - "invalid left-hand side expression" - ) - .span_label(lhs_expr.span, "invalid expression for left-hand side") - .emit(); + "invalid left-hand side of assignment", + ).span_label(lhs_expr.span, "cannot assign to this expression").emit(); } ty } diff --git a/src/test/ui/bad/bad-expr-lhs.rs b/src/test/ui/bad/bad-expr-lhs.rs index 2cd8bc9d47333..d7cf1b7700514 100644 --- a/src/test/ui/bad/bad-expr-lhs.rs +++ b/src/test/ui/bad/bad-expr-lhs.rs @@ -1,10 +1,10 @@ fn main() { - 1 = 2; //~ ERROR invalid left-hand side expression - 1 += 2; //~ ERROR invalid left-hand side expression - (1, 2) = (3, 4); //~ ERROR invalid left-hand side expression + 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 let (a, b) = (1, 2); - (a, b) = (3, 4); //~ ERROR invalid left-hand side expression + (a, b) = (3, 4); //~ ERROR invalid left-hand side of assignment - None = Some(3); //~ ERROR invalid left-hand side expression + None = Some(3); //~ ERROR invalid left-hand side of assignment } diff --git a/src/test/ui/bad/bad-expr-lhs.stderr b/src/test/ui/bad/bad-expr-lhs.stderr index a0de6a73797e2..07cffbe97a8d9 100644 --- a/src/test/ui/bad/bad-expr-lhs.stderr +++ b/src/test/ui/bad/bad-expr-lhs.stderr @@ -1,32 +1,42 @@ -error[E0070]: invalid left-hand side expression +error[E0070]: invalid left-hand side of assignment --> $DIR/bad-expr-lhs.rs:2:5 | LL | 1 = 2; - | ^^^^^ left-hand of expression not valid + | -^^^^ + | | + | cannot assign to this expression -error[E0067]: invalid left-hand side expression - --> $DIR/bad-expr-lhs.rs:3:5 +error[E0067]: invalid left-hand side of assignment + --> $DIR/bad-expr-lhs.rs:3:7 | LL | 1 += 2; - | ^ invalid expression for left-hand side + | - ^^ + | | + | cannot assign to this expression -error[E0070]: invalid left-hand side expression +error[E0070]: invalid left-hand side of assignment --> $DIR/bad-expr-lhs.rs:4:5 | LL | (1, 2) = (3, 4); - | ^^^^^^^^^^^^^^^ left-hand of expression not valid + | ------^^^^^^^^^ + | | + | cannot assign to this expression -error[E0070]: invalid left-hand side expression +error[E0070]: invalid left-hand side of assignment --> $DIR/bad-expr-lhs.rs:7:5 | LL | (a, b) = (3, 4); - | ^^^^^^^^^^^^^^^ left-hand of expression not valid + | ------^^^^^^^^^ + | | + | cannot assign to this expression -error[E0070]: invalid left-hand side expression +error[E0070]: invalid left-hand side of assignment --> $DIR/bad-expr-lhs.rs:9:5 | LL | None = Some(3); - | ^^^^^^^^^^^^^^ left-hand of expression not valid + | ----^^^^^^^^^^ + | | + | cannot assign to this expression error: aborting due to 5 previous errors diff --git a/src/test/ui/error-codes/E0067.stderr b/src/test/ui/error-codes/E0067.stderr index 0334565840f83..526503798b3d4 100644 --- a/src/test/ui/error-codes/E0067.stderr +++ b/src/test/ui/error-codes/E0067.stderr @@ -8,11 +8,13 @@ LL | LinkedList::new() += 1; | = note: an implementation of `std::ops::AddAssign` might be missing for `std::collections::LinkedList<_>` -error[E0067]: invalid left-hand side expression - --> $DIR/E0067.rs:4:5 +error[E0067]: invalid left-hand side of assignment + --> $DIR/E0067.rs:4:23 | LL | LinkedList::new() += 1; - | ^^^^^^^^^^^^^^^^^ invalid expression for left-hand side + | ----------------- ^^ + | | + | cannot assign to this expression error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0070.stderr b/src/test/ui/error-codes/E0070.stderr index 845833bc82f70..1fb812d94672f 100644 --- a/src/test/ui/error-codes/E0070.stderr +++ b/src/test/ui/error-codes/E0070.stderr @@ -1,14 +1,18 @@ -error[E0070]: invalid left-hand side expression +error[E0070]: invalid left-hand side of assignment --> $DIR/E0070.rs:6:5 | LL | SOME_CONST = 14; - | ^^^^^^^^^^^^^^^ left-hand of expression not valid + | ----------^^^^^ + | | + | cannot assign to this expression -error[E0070]: invalid left-hand side expression +error[E0070]: invalid left-hand side of assignment --> $DIR/E0070.rs:7:5 | LL | 1 = 3; - | ^^^^^ left-hand of expression not valid + | -^^^^ + | | + | cannot assign to this expression error[E0308]: mismatched types --> $DIR/E0070.rs:8:25 @@ -16,11 +20,13 @@ error[E0308]: mismatched types LL | some_other_func() = 4; | ^ expected `()`, found integer -error[E0070]: invalid left-hand side expression +error[E0070]: invalid left-hand side of assignment --> $DIR/E0070.rs:8:5 | LL | some_other_func() = 4; - | ^^^^^^^^^^^^^^^^^^^^^ left-hand of expression not valid + | -----------------^^^^ + | | + | cannot assign to this expression error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-13407.rs b/src/test/ui/issues/issue-13407.rs index 322e67cc13180..fa53d55f5b3d7 100644 --- a/src/test/ui/issues/issue-13407.rs +++ b/src/test/ui/issues/issue-13407.rs @@ -4,7 +4,7 @@ mod A { fn main() { A::C = 1; - //~^ ERROR: invalid left-hand side expression + //~^ ERROR: invalid left-hand side of assignment //~| ERROR: mismatched types //~| ERROR: struct `C` is private } diff --git a/src/test/ui/issues/issue-13407.stderr b/src/test/ui/issues/issue-13407.stderr index 5a465cc533bb7..05fd97b025f60 100644 --- a/src/test/ui/issues/issue-13407.stderr +++ b/src/test/ui/issues/issue-13407.stderr @@ -10,11 +10,13 @@ error[E0308]: mismatched types LL | A::C = 1; | ^ expected struct `A::C`, found integer -error[E0070]: invalid left-hand side expression +error[E0070]: invalid left-hand side of assignment --> $DIR/issue-13407.rs:6:5 | LL | A::C = 1; - | ^^^^^^^^ left-hand of expression not valid + | ----^^^^ + | | + | cannot assign to this expression error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-26093.rs b/src/test/ui/issues/issue-26093.rs index 7895c90068fe2..c838515caf997 100644 --- a/src/test/ui/issues/issue-26093.rs +++ b/src/test/ui/issues/issue-26093.rs @@ -1,7 +1,9 @@ macro_rules! not_a_place { ($thing:expr) => { $thing = 42; - //~^ ERROR invalid left-hand side expression + //~^ ERROR invalid left-hand side of assignment + $thing += 42; + //~^ ERROR invalid left-hand side of assignment } } diff --git a/src/test/ui/issues/issue-26093.stderr b/src/test/ui/issues/issue-26093.stderr index 947c52f08d2e6..48f72cef0a85a 100644 --- a/src/test/ui/issues/issue-26093.stderr +++ b/src/test/ui/issues/issue-26093.stderr @@ -1,12 +1,28 @@ -error[E0070]: invalid left-hand side expression +error[E0070]: invalid left-hand side of assignment --> $DIR/issue-26093.rs:3:9 | LL | $thing = 42; - | ^^^^^^^^^^^ left-hand of expression not valid + | ^^^^^^^^^^^ ... LL | not_a_place!(99); - | ----------------- in this macro invocation + | ----------------- + | | | + | | cannot assign to this expression + | in this macro invocation -error: aborting due to previous error +error[E0067]: invalid left-hand side of assignment + --> $DIR/issue-26093.rs:5:16 + | +LL | $thing += 42; + | ^^ +... +LL | not_a_place!(99); + | ----------------- + | | | + | | cannot assign to this expression + | in this macro invocation + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0070`. +Some errors have detailed explanations: E0067, E0070. +For more information about an error, try `rustc --explain E0067`. diff --git a/src/test/ui/issues/issue-34334.rs b/src/test/ui/issues/issue-34334.rs index 4457d71cbb4a7..e34b5c9a0f47e 100644 --- a/src/test/ui/issues/issue-34334.rs +++ b/src/test/ui/issues/issue-34334.rs @@ -3,7 +3,7 @@ fn main () { //~^ ERROR expected one of `,` or `>`, found `=` //~| ERROR expected value, found struct `Vec` //~| ERROR mismatched types - //~| ERROR invalid left-hand side expression + //~| ERROR invalid left-hand side of assignment //~| ERROR expected expression, found reserved identifier `_` //~| ERROR expected expression, found reserved identifier `_` let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index fc90e0674cf55..e54f0c77cd973 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -35,11 +35,13 @@ LL | let sr: Vec<(u32, _, _) = vec![]; found struct `std::vec::Vec<_>` = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error[E0070]: invalid left-hand side expression +error[E0070]: invalid left-hand side of assignment --> $DIR/issue-34334.rs:2:13 | LL | let sr: Vec<(u32, _, _) = vec![]; - | ^^^^^^^^^^^^^^^^^^^^^^^^ left-hand of expression not valid + | ---------------^^^^^^^^^ + | | + | cannot assign to this expression error[E0599]: no method named `iter` found for type `()` in the current scope --> $DIR/issue-34334.rs:9:36 diff --git a/src/test/ui/type/type-check/assignment-expected-bool.rs b/src/test/ui/type/type-check/assignment-expected-bool.rs index 03830fea062cf..191939bdb705b 100644 --- a/src/test/ui/type/type-check/assignment-expected-bool.rs +++ b/src/test/ui/type/type-check/assignment-expected-bool.rs @@ -30,5 +30,5 @@ fn main() { // A test to check that not expecting `bool` behaves well: let _: usize = 0 = 0; //~^ ERROR mismatched types [E0308] - //~| ERROR invalid left-hand side expression [E0070] + //~| ERROR invalid left-hand side of assignment [E0070] } diff --git a/src/test/ui/type/type-check/assignment-expected-bool.stderr b/src/test/ui/type/type-check/assignment-expected-bool.stderr index 9a1cf5b25625c..bbd961f845016 100644 --- a/src/test/ui/type/type-check/assignment-expected-bool.stderr +++ b/src/test/ui/type/type-check/assignment-expected-bool.stderr @@ -97,11 +97,13 @@ LL | || (0 = 0); | expected `bool`, found `()` | help: try comparing for equality: `0 == 0` -error[E0070]: invalid left-hand side expression +error[E0070]: invalid left-hand side of assignment --> $DIR/assignment-expected-bool.rs:31:20 | LL | let _: usize = 0 = 0; - | ^^^^^ left-hand of expression not valid + | -^^^^ + | | + | cannot assign to this expression error[E0308]: mismatched types --> $DIR/assignment-expected-bool.rs:31:20 diff --git a/src/test/ui/type/type-check/assignment-in-if.rs b/src/test/ui/type/type-check/assignment-in-if.rs index 77b122b0a794a..8da7b32b47b14 100644 --- a/src/test/ui/type/type-check/assignment-in-if.rs +++ b/src/test/ui/type/type-check/assignment-in-if.rs @@ -26,7 +26,7 @@ fn main() { //~^ ERROR mismatched types println!("{}", x); } - // "invalid left-hand side expression" error is suppresed + // "invalid left-hand side of assignment" error is suppresed if 3 = x { //~^ ERROR mismatched types println!("{}", x); From 5fa02ecc291f0a6b356fbb3b1e14649082b93a2f Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 22 Dec 2019 20:14:08 +0000 Subject: [PATCH 3/7] Add note about destructuring assignments --- src/librustc_typeck/check/expr.rs | 44 +++++-- src/librustc_typeck/check/op.rs | 20 ++-- src/test/ui/bad/bad-expr-lhs.stderr | 3 + src/test/ui/bad/destructuring-assignment.rs | 21 ++++ .../ui/bad/destructuring-assignment.stderr | 111 ++++++++++++++++++ 5 files changed, 178 insertions(+), 21 deletions(-) create mode 100644 src/test/ui/bad/destructuring-assignment.rs create mode 100644 src/test/ui/bad/destructuring-assignment.stderr diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 27f6b3cb45f4b..9085528c84e9f 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -17,7 +17,7 @@ use crate::check::TupleArgumentsFlag::DontTupleArguments; use crate::util::common::ErrorReported; use crate::util::nodemap::FxHashMap; -use errors::{pluralize, Applicability, DiagnosticBuilder}; +use errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId}; use rustc::hir; use rustc::hir::def::{CtorKind, DefKind, Res}; use rustc::hir::def_id::DefId; @@ -723,6 +723,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } + pub(crate) fn check_lhs_assignable( + &self, + lhs: &'tcx hir::Expr, + err_code: &'static str, + expr_span: &Span, + ) { + if !lhs.is_syntactic_place_expr() { + let mut err = self.tcx.sess.struct_span_err_with_code( + *expr_span, + "invalid left-hand side of assignment", + DiagnosticId::Error(err_code.into()), + ); + err.span_label(lhs.span, "cannot assign to this expression"); + let destructuring_assignment = match &lhs.kind { + ExprKind::Array(comps) | ExprKind::Tup(comps) => { + comps.iter().all(|e| e.is_syntactic_place_expr()) + } + ExprKind::Struct(_path, fields, rest) => { + rest.as_ref().map(|e| e.is_syntactic_place_expr()).unwrap_or(true) && + fields.iter().all(|f| f.expr.is_syntactic_place_expr()) + } + _ => false, + }; + if destructuring_assignment { + err.note("destructuring assignments are not yet supported"); + err.note( + "for more information, see https://github.com/rust-lang/rfcs/issues/372", + ); + } + err.emit(); + } + } + /// Type check assignment expression `expr` of form `lhs = rhs`. /// The expected type is `()` and is passsed to the function for the purposes of diagnostics. fn check_expr_assign( @@ -752,13 +785,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.help(msg); } err.emit(); - } else if !lhs.is_syntactic_place_expr() { - struct_span_err!( - self.tcx.sess, - expr.span, - E0070, - "invalid left-hand side of assignment", - ).span_label(lhs.span, "cannot assign to this expression").emit(); + } else { + self.check_lhs_assignable(lhs, "E0070", &expr.span); } self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized); diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index eeee7dea4d1c1..dfa55e324a625 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -19,28 +19,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, expr: &'tcx hir::Expr, op: hir::BinOp, - lhs_expr: &'tcx hir::Expr, - rhs_expr: &'tcx hir::Expr, + lhs: &'tcx hir::Expr, + rhs: &'tcx hir::Expr, ) -> Ty<'tcx> { let (lhs_ty, rhs_ty, return_ty) = - self.check_overloaded_binop(expr, lhs_expr, rhs_expr, op, IsAssign::Yes); + self.check_overloaded_binop(expr, lhs, rhs, op, IsAssign::Yes); let ty = - if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) { - self.enforce_builtin_binop_types(lhs_expr, lhs_ty, rhs_expr, rhs_ty, op); + if !lhs.is_ty_var() && !rhs.is_ty_var() && is_builtin_binop(lhs, rhs, op) { + self.enforce_builtin_binop_types(lhs_expr, lhs, rhs_expr, rhs, op); self.tcx.mk_unit() } else { return_ty }; - if !lhs_expr.is_syntactic_place_expr() { - struct_span_err!( - self.tcx.sess, - op.span, - E0067, - "invalid left-hand side of assignment", - ).span_label(lhs_expr.span, "cannot assign to this expression").emit(); - } + self.check_lhs_assignable(lhs, "E0067", &op.span); + ty } diff --git a/src/test/ui/bad/bad-expr-lhs.stderr b/src/test/ui/bad/bad-expr-lhs.stderr index 07cffbe97a8d9..61c25bb471c37 100644 --- a/src/test/ui/bad/bad-expr-lhs.stderr +++ b/src/test/ui/bad/bad-expr-lhs.stderr @@ -29,6 +29,9 @@ LL | (a, b) = (3, 4); | ------^^^^^^^^^ | | | cannot assign to this expression + | + = note: destructuring assignments are not yet supported + = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 error[E0070]: invalid left-hand side of assignment --> $DIR/bad-expr-lhs.rs:9:5 diff --git a/src/test/ui/bad/destructuring-assignment.rs b/src/test/ui/bad/destructuring-assignment.rs new file mode 100644 index 0000000000000..7112cedfd0009 --- /dev/null +++ b/src/test/ui/bad/destructuring-assignment.rs @@ -0,0 +1,21 @@ +struct S { x: u8, y: u8 } + +fn main() { + let (a, b) = (1, 2); + + (a, b) = (3, 4); //~ ERROR invalid left-hand side of assignment + (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 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 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 +} diff --git a/src/test/ui/bad/destructuring-assignment.stderr b/src/test/ui/bad/destructuring-assignment.stderr new file mode 100644 index 0000000000000..676576b7bc526 --- /dev/null +++ b/src/test/ui/bad/destructuring-assignment.stderr @@ -0,0 +1,111 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/destructuring-assignment.rs:6:5 + | +LL | (a, b) = (3, 4); + | ------^^^^^^^^^ + | | + | cannot assign to this expression + | + = note: destructuring assignments are not yet supported + = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 + +error[E0368]: binary assignment operation `+=` cannot be applied to type `({integer}, {integer})` + --> $DIR/destructuring-assignment.rs:7:5 + | +LL | (a, b) += (3, 4); + | ------^^^^^^^^^^ + | | + | cannot use `+=` on type `({integer}, {integer})` + | + = note: an implementation of `std::ops::AddAssign` might be missing for `({integer}, {integer})` + +error[E0067]: invalid left-hand side of assignment + --> $DIR/destructuring-assignment.rs:7:12 + | +LL | (a, b) += (3, 4); + | ------ ^^ + | | + | cannot assign to this expression + | + = note: destructuring assignments are not yet supported + = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 + +error[E0070]: invalid left-hand side of assignment + --> $DIR/destructuring-assignment.rs:10:5 + | +LL | [a, b] = [3, 4]; + | ------^^^^^^^^^ + | | + | cannot assign to this expression + | + = note: destructuring assignments are not yet supported + = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 + +error[E0368]: binary assignment operation `+=` cannot be applied to type `[{integer}; 2]` + --> $DIR/destructuring-assignment.rs:11:5 + | +LL | [a, b] += [3, 4]; + | ------^^^^^^^^^^ + | | + | cannot use `+=` on type `[{integer}; 2]` + | + = note: an implementation of `std::ops::AddAssign` might be missing for `[{integer}; 2]` + +error[E0067]: invalid left-hand side of assignment + --> $DIR/destructuring-assignment.rs:11:12 + | +LL | [a, b] += [3, 4]; + | ------ ^^ + | | + | cannot assign to this expression + | + = note: destructuring assignments are not yet supported + = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 + +error[E0070]: invalid left-hand side of assignment + --> $DIR/destructuring-assignment.rs:16:5 + | +LL | S { x: a, y: b } = s; + | ----------------^^^^ + | | + | cannot assign to this expression + | + = note: destructuring assignments are not yet supported + = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 + +error[E0368]: binary assignment operation `+=` cannot be applied to type `S` + --> $DIR/destructuring-assignment.rs:17:5 + | +LL | S { x: a, y: b } += s; + | ----------------^^^^^ + | | + | cannot use `+=` on type `S` + | + = note: an implementation of `std::ops::AddAssign` might be missing for `S` + +error[E0067]: invalid left-hand side of assignment + --> $DIR/destructuring-assignment.rs:17:22 + | +LL | S { x: a, y: b } += s; + | ---------------- ^^ + | | + | cannot assign to this expression + | + = note: destructuring assignments are not yet supported + = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 + +error[E0070]: invalid left-hand side of assignment + --> $DIR/destructuring-assignment.rs:20:5 + | +LL | S { x: a, ..s } = S { x: 3, y: 4 }; + | ---------------^^^^^^^^^^^^^^^^^^^ + | | + | cannot assign to this expression + | + = note: destructuring assignments are not yet supported + = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0067, E0070, E0368. +For more information about an error, try `rustc --explain E0067`. From 5ab4735559aeeece0b5811dad95fdf515b1bcfbd Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 22 Dec 2019 20:27:42 +0000 Subject: [PATCH 4/7] Recognise nested tuples/arrays/structs --- src/librustc_typeck/check/expr.rs | 25 +++++++++++-------- src/test/ui/bad/destructuring-assignment.rs | 4 +++ .../ui/bad/destructuring-assignment.stderr | 13 +++++++++- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 9085528c84e9f..13046d8002a9b 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -723,6 +723,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } + fn is_destructuring_place_expr(&self, expr: &'tcx hir::Expr) -> bool { + match &expr.kind { + ExprKind::Array(comps) | ExprKind::Tup(comps) => { + comps.iter().all(|e| self.is_destructuring_place_expr(e)) + } + ExprKind::Struct(_path, fields, rest) => { + rest.as_ref().map(|e| self.is_destructuring_place_expr(e)).unwrap_or(true) && + fields.iter().all(|f| self.is_destructuring_place_expr(&f.expr)) + } + _ => expr.is_syntactic_place_expr(), + } + } + pub(crate) fn check_lhs_assignable( &self, lhs: &'tcx hir::Expr, @@ -736,17 +749,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { DiagnosticId::Error(err_code.into()), ); err.span_label(lhs.span, "cannot assign to this expression"); - let destructuring_assignment = match &lhs.kind { - ExprKind::Array(comps) | ExprKind::Tup(comps) => { - comps.iter().all(|e| e.is_syntactic_place_expr()) - } - ExprKind::Struct(_path, fields, rest) => { - rest.as_ref().map(|e| e.is_syntactic_place_expr()).unwrap_or(true) && - fields.iter().all(|f| f.expr.is_syntactic_place_expr()) - } - _ => false, - }; - if destructuring_assignment { + if self.is_destructuring_place_expr(lhs) { err.note("destructuring assignments are not yet supported"); err.note( "for more information, see https://github.com/rust-lang/rfcs/issues/372", diff --git a/src/test/ui/bad/destructuring-assignment.rs b/src/test/ui/bad/destructuring-assignment.rs index 7112cedfd0009..876c9efea2647 100644 --- a/src/test/ui/bad/destructuring-assignment.rs +++ b/src/test/ui/bad/destructuring-assignment.rs @@ -18,4 +18,8 @@ fn main() { //~^ ERROR binary assignment operation `+=` cannot be applied S { x: a, ..s } = S { x: 3, y: 4 }; //~ ERROR invalid left-hand side of assignment + + let c = 3; + + ((a, b), c) = ((3, 4), 5); //~ ERROR invalid left-hand side of assignment } diff --git a/src/test/ui/bad/destructuring-assignment.stderr b/src/test/ui/bad/destructuring-assignment.stderr index 676576b7bc526..845008b06937c 100644 --- a/src/test/ui/bad/destructuring-assignment.stderr +++ b/src/test/ui/bad/destructuring-assignment.stderr @@ -105,7 +105,18 @@ LL | S { x: a, ..s } = S { x: 3, y: 4 }; = note: destructuring assignments are not yet supported = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 -error: aborting due to 10 previous errors +error[E0070]: invalid left-hand side of assignment + --> $DIR/destructuring-assignment.rs:24:5 + | +LL | ((a, b), c) = ((3, 4), 5); + | -----------^^^^^^^^^^^^^^ + | | + | cannot assign to this expression + | + = note: destructuring assignments are not yet supported + = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 + +error: aborting due to 11 previous errors Some errors have detailed explanations: E0067, E0070, E0368. For more information about an error, try `rustc --explain E0067`. From 35979a92bf6dba402885a1488ecfd84046e4bd71 Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 22 Dec 2019 21:08:53 +0000 Subject: [PATCH 5/7] Add span information to `ExprKind::Assign` --- src/librustc/hir/intravisit.rs | 6 +++--- src/librustc/hir/lowering/expr.rs | 11 ++++++---- src/librustc/hir/mod.rs | 2 +- src/librustc/hir/print.rs | 4 ++-- src/librustc_lint/unused.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 2 +- src/librustc_parse/parser/expr.rs | 4 +++- src/librustc_passes/liveness.rs | 4 ++-- src/librustc_privacy/lib.rs | 2 +- src/librustc_typeck/check/demand.rs | 2 +- src/librustc_typeck/check/expr.rs | 8 +++++--- src/librustc_typeck/expr_use_visitor.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/util/parser.rs | 2 +- src/libsyntax/visit.rs | 6 +++--- src/test/ui-fulldeps/pprust-expr-roundtrip.rs | 4 ++-- src/test/ui/bad/bad-expr-lhs.stderr | 16 +++++++-------- .../ui/bad/destructuring-assignment.stderr | 20 +++++++++---------- src/test/ui/error-codes/E0070.stderr | 12 +++++------ src/test/ui/issues/issue-13407.stderr | 4 ++-- src/test/ui/issues/issue-26093.stderr | 4 ++-- src/test/ui/issues/issue-34334.stderr | 4 ++-- .../assignment-expected-bool.stderr | 4 ++-- 25 files changed, 69 insertions(+), 62 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index dc2008fdd9743..a7a8673d49eb1 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -1043,9 +1043,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_list!(visitor, visit_label, opt_label); visitor.visit_block(block); } - ExprKind::Assign(ref left_hand_expression, ref right_hand_expression) => { - visitor.visit_expr(right_hand_expression); - visitor.visit_expr(left_hand_expression) + ExprKind::Assign(ref lhs, ref rhs, _) => { + visitor.visit_expr(rhs); + visitor.visit_expr(lhs) } ExprKind::AssignOp(_, ref left_expression, ref right_expression) => { visitor.visit_expr(right_expression); diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index 8939b5eef2660..8311b9168e455 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -122,8 +122,8 @@ impl LoweringContext<'_, '_> { self.lower_block(blk, opt_label.is_some()), self.lower_label(opt_label), ), - ExprKind::Assign(ref el, ref er) => { - hir::ExprKind::Assign(P(self.lower_expr(el)), P(self.lower_expr(er))) + ExprKind::Assign(ref el, ref er, span) => { + hir::ExprKind::Assign(P(self.lower_expr(el)), P(self.lower_expr(er)), span) } ExprKind::AssignOp(op, ref el, ref er) => hir::ExprKind::AssignOp( self.lower_binop(op), @@ -994,8 +994,11 @@ impl LoweringContext<'_, '_> { let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident); let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid)); let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid)); - let assign = - P(self.expr(pat.span, hir::ExprKind::Assign(next_expr, val_expr), ThinVec::new())); + let assign = P(self.expr( + pat.span, + hir::ExprKind::Assign(next_expr, val_expr, pat.span), + ThinVec::new(), + )); let some_pat = self.pat_some(pat.span, val_pat); self.arm(some_pat, assign) }; diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 4aa8c12a219ca..457851bd7ecdd 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1628,7 +1628,7 @@ pub enum ExprKind { Block(P, Option