Add note about destructuring assignments
This commit is contained in:
parent
b7bfdbe681
commit
5fa02ecc29
@ -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
|
||||
|
21
src/test/ui/bad/destructuring-assignment.rs
Normal file
21
src/test/ui/bad/destructuring-assignment.rs
Normal file
@ -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
|
||||
}
|
111
src/test/ui/bad/destructuring-assignment.stderr
Normal file
111
src/test/ui/bad/destructuring-assignment.stderr
Normal file
@ -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`.
|
Loading…
x
Reference in New Issue
Block a user