Skip to content

Commit 5fa02ec

Browse files
committed
Add note about destructuring assignments
1 parent b7bfdbe commit 5fa02ec

File tree

5 files changed

+178
-21
lines changed

5 files changed

+178
-21
lines changed

src/librustc_typeck/check/expr.rs

+36-8
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::check::TupleArgumentsFlag::DontTupleArguments;
1717
use crate::util::common::ErrorReported;
1818
use crate::util::nodemap::FxHashMap;
1919

20-
use errors::{pluralize, Applicability, DiagnosticBuilder};
20+
use errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
2121
use rustc::hir;
2222
use rustc::hir::def::{CtorKind, DefKind, Res};
2323
use rustc::hir::def_id::DefId;
@@ -723,6 +723,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
723723
);
724724
}
725725

726+
pub(crate) fn check_lhs_assignable(
727+
&self,
728+
lhs: &'tcx hir::Expr,
729+
err_code: &'static str,
730+
expr_span: &Span,
731+
) {
732+
if !lhs.is_syntactic_place_expr() {
733+
let mut err = self.tcx.sess.struct_span_err_with_code(
734+
*expr_span,
735+
"invalid left-hand side of assignment",
736+
DiagnosticId::Error(err_code.into()),
737+
);
738+
err.span_label(lhs.span, "cannot assign to this expression");
739+
let destructuring_assignment = match &lhs.kind {
740+
ExprKind::Array(comps) | ExprKind::Tup(comps) => {
741+
comps.iter().all(|e| e.is_syntactic_place_expr())
742+
}
743+
ExprKind::Struct(_path, fields, rest) => {
744+
rest.as_ref().map(|e| e.is_syntactic_place_expr()).unwrap_or(true) &&
745+
fields.iter().all(|f| f.expr.is_syntactic_place_expr())
746+
}
747+
_ => false,
748+
};
749+
if destructuring_assignment {
750+
err.note("destructuring assignments are not yet supported");
751+
err.note(
752+
"for more information, see https://github.com/rust-lang/rfcs/issues/372",
753+
);
754+
}
755+
err.emit();
756+
}
757+
}
758+
726759
/// Type check assignment expression `expr` of form `lhs = rhs`.
727760
/// The expected type is `()` and is passsed to the function for the purposes of diagnostics.
728761
fn check_expr_assign(
@@ -752,13 +785,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
752785
err.help(msg);
753786
}
754787
err.emit();
755-
} else if !lhs.is_syntactic_place_expr() {
756-
struct_span_err!(
757-
self.tcx.sess,
758-
expr.span,
759-
E0070,
760-
"invalid left-hand side of assignment",
761-
).span_label(lhs.span, "cannot assign to this expression").emit();
788+
} else {
789+
self.check_lhs_assignable(lhs, "E0070", &expr.span);
762790
}
763791

764792
self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);

src/librustc_typeck/check/op.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1919
&self,
2020
expr: &'tcx hir::Expr,
2121
op: hir::BinOp,
22-
lhs_expr: &'tcx hir::Expr,
23-
rhs_expr: &'tcx hir::Expr,
22+
lhs: &'tcx hir::Expr,
23+
rhs: &'tcx hir::Expr,
2424
) -> Ty<'tcx> {
2525
let (lhs_ty, rhs_ty, return_ty) =
26-
self.check_overloaded_binop(expr, lhs_expr, rhs_expr, op, IsAssign::Yes);
26+
self.check_overloaded_binop(expr, lhs, rhs, op, IsAssign::Yes);
2727

2828
let ty =
29-
if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) {
30-
self.enforce_builtin_binop_types(lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
29+
if !lhs.is_ty_var() && !rhs.is_ty_var() && is_builtin_binop(lhs, rhs, op) {
30+
self.enforce_builtin_binop_types(lhs_expr, lhs, rhs_expr, rhs, op);
3131
self.tcx.mk_unit()
3232
} else {
3333
return_ty
3434
};
3535

36-
if !lhs_expr.is_syntactic_place_expr() {
37-
struct_span_err!(
38-
self.tcx.sess,
39-
op.span,
40-
E0067,
41-
"invalid left-hand side of assignment",
42-
).span_label(lhs_expr.span, "cannot assign to this expression").emit();
43-
}
36+
self.check_lhs_assignable(lhs, "E0067", &op.span);
37+
4438
ty
4539
}
4640

src/test/ui/bad/bad-expr-lhs.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ LL | (a, b) = (3, 4);
2929
| ------^^^^^^^^^
3030
| |
3131
| cannot assign to this expression
32+
|
33+
= note: destructuring assignments are not yet supported
34+
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
3235

3336
error[E0070]: invalid left-hand side of assignment
3437
--> $DIR/bad-expr-lhs.rs:9:5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
struct S { x: u8, y: u8 }
2+
3+
fn main() {
4+
let (a, b) = (1, 2);
5+
6+
(a, b) = (3, 4); //~ ERROR invalid left-hand side of assignment
7+
(a, b) += (3, 4); //~ ERROR invalid left-hand side of assignment
8+
//~^ ERROR binary assignment operation `+=` cannot be applied
9+
10+
[a, b] = [3, 4]; //~ ERROR invalid left-hand side of assignment
11+
[a, b] += [3, 4]; //~ ERROR invalid left-hand side of assignment
12+
//~^ ERROR binary assignment operation `+=` cannot be applied
13+
14+
let s = S { x: 3, y: 4 };
15+
16+
S { x: a, y: b } = s; //~ ERROR invalid left-hand side of assignment
17+
S { x: a, y: b } += s; //~ ERROR invalid left-hand side of assignment
18+
//~^ ERROR binary assignment operation `+=` cannot be applied
19+
20+
S { x: a, ..s } = S { x: 3, y: 4 }; //~ ERROR invalid left-hand side of assignment
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
error[E0070]: invalid left-hand side of assignment
2+
--> $DIR/destructuring-assignment.rs:6:5
3+
|
4+
LL | (a, b) = (3, 4);
5+
| ------^^^^^^^^^
6+
| |
7+
| cannot assign to this expression
8+
|
9+
= note: destructuring assignments are not yet supported
10+
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
11+
12+
error[E0368]: binary assignment operation `+=` cannot be applied to type `({integer}, {integer})`
13+
--> $DIR/destructuring-assignment.rs:7:5
14+
|
15+
LL | (a, b) += (3, 4);
16+
| ------^^^^^^^^^^
17+
| |
18+
| cannot use `+=` on type `({integer}, {integer})`
19+
|
20+
= note: an implementation of `std::ops::AddAssign` might be missing for `({integer}, {integer})`
21+
22+
error[E0067]: invalid left-hand side of assignment
23+
--> $DIR/destructuring-assignment.rs:7:12
24+
|
25+
LL | (a, b) += (3, 4);
26+
| ------ ^^
27+
| |
28+
| cannot assign to this expression
29+
|
30+
= note: destructuring assignments are not yet supported
31+
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
32+
33+
error[E0070]: invalid left-hand side of assignment
34+
--> $DIR/destructuring-assignment.rs:10:5
35+
|
36+
LL | [a, b] = [3, 4];
37+
| ------^^^^^^^^^
38+
| |
39+
| cannot assign to this expression
40+
|
41+
= note: destructuring assignments are not yet supported
42+
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
43+
44+
error[E0368]: binary assignment operation `+=` cannot be applied to type `[{integer}; 2]`
45+
--> $DIR/destructuring-assignment.rs:11:5
46+
|
47+
LL | [a, b] += [3, 4];
48+
| ------^^^^^^^^^^
49+
| |
50+
| cannot use `+=` on type `[{integer}; 2]`
51+
|
52+
= note: an implementation of `std::ops::AddAssign` might be missing for `[{integer}; 2]`
53+
54+
error[E0067]: invalid left-hand side of assignment
55+
--> $DIR/destructuring-assignment.rs:11:12
56+
|
57+
LL | [a, b] += [3, 4];
58+
| ------ ^^
59+
| |
60+
| cannot assign to this expression
61+
|
62+
= note: destructuring assignments are not yet supported
63+
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
64+
65+
error[E0070]: invalid left-hand side of assignment
66+
--> $DIR/destructuring-assignment.rs:16:5
67+
|
68+
LL | S { x: a, y: b } = s;
69+
| ----------------^^^^
70+
| |
71+
| cannot assign to this expression
72+
|
73+
= note: destructuring assignments are not yet supported
74+
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
75+
76+
error[E0368]: binary assignment operation `+=` cannot be applied to type `S`
77+
--> $DIR/destructuring-assignment.rs:17:5
78+
|
79+
LL | S { x: a, y: b } += s;
80+
| ----------------^^^^^
81+
| |
82+
| cannot use `+=` on type `S`
83+
|
84+
= note: an implementation of `std::ops::AddAssign` might be missing for `S`
85+
86+
error[E0067]: invalid left-hand side of assignment
87+
--> $DIR/destructuring-assignment.rs:17:22
88+
|
89+
LL | S { x: a, y: b } += s;
90+
| ---------------- ^^
91+
| |
92+
| cannot assign to this expression
93+
|
94+
= note: destructuring assignments are not yet supported
95+
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
96+
97+
error[E0070]: invalid left-hand side of assignment
98+
--> $DIR/destructuring-assignment.rs:20:5
99+
|
100+
LL | S { x: a, ..s } = S { x: 3, y: 4 };
101+
| ---------------^^^^^^^^^^^^^^^^^^^
102+
| |
103+
| cannot assign to this expression
104+
|
105+
= note: destructuring assignments are not yet supported
106+
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
107+
108+
error: aborting due to 10 previous errors
109+
110+
Some errors have detailed explanations: E0067, E0070, E0368.
111+
For more information about an error, try `rustc --explain E0067`.

0 commit comments

Comments
 (0)