Skip to content
Permalink
Browse files

Add note about destructuring assignments

  • Loading branch information
varkor committed Dec 22, 2019
1 parent b7bfdbe commit 5fa02ecc291f0a6b356fbb3b1e14649082b93a2f
@@ -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);
@@ -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
}

@@ -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
@@ -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
}
@@ -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`.

0 comments on commit 5fa02ec

Please sign in to comment.
You can’t perform that action at this time.