diff options
| author | varkor <github@varkor.com> | 2019-12-22 20:14:08 +0000 |
|---|---|---|
| committer | varkor <github@varkor.com> | 2019-12-23 11:17:55 +0000 |
| commit | 5fa02ecc291f0a6b356fbb3b1e14649082b93a2f (patch) | |
| tree | 609103e33c18049ba75063c6ce8c07ab701b5cdc | |
| parent | b7bfdbe68147f2ea8ca4870270643180bef76e02 (diff) | |
| download | rust-5fa02ecc291f0a6b356fbb3b1e14649082b93a2f.tar.gz rust-5fa02ecc291f0a6b356fbb3b1e14649082b93a2f.zip | |
Add note about destructuring assignments
| -rw-r--r-- | src/librustc_typeck/check/expr.rs | 44 | ||||
| -rw-r--r-- | src/librustc_typeck/check/op.rs | 20 | ||||
| -rw-r--r-- | src/test/ui/bad/bad-expr-lhs.stderr | 3 | ||||
| -rw-r--r-- | src/test/ui/bad/destructuring-assignment.rs | 21 | ||||
| -rw-r--r-- | src/test/ui/bad/destructuring-assignment.stderr | 111 |
5 files changed, 178 insertions, 21 deletions
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 27f6b3cb45f..9085528c84e 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 eeee7dea4d1..dfa55e324a6 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 07cffbe97a8..61c25bb471c 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 00000000000..7112cedfd00 --- /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 00000000000..676576b7bc5 --- /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`. |
