Skip to content

Commit a2a0bb2

Browse files
committed
Add note about destructuring assignments
1 parent 5c92da4 commit a2a0bb2

File tree

5 files changed

+177
-20
lines changed

5 files changed

+177
-20
lines changed

src/librustc_typeck/check/expr.rs

+36-8
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::util::common::ErrorReported;
1717
use crate::util::nodemap::FxHashMap;
1818
use crate::astconv::AstConv as _;
1919

20-
use errors::{Applicability, DiagnosticBuilder, pluralize};
20+
use errors::{Applicability, DiagnosticBuilder, DiagnosticId, pluralize};
2121
use syntax_pos::hygiene::DesugaringKind;
2222
use syntax::ast;
2323
use syntax::symbol::{Symbol, kw, sym};
@@ -761,6 +761,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
761761
);
762762
}
763763

764+
pub(crate) fn check_lhs_assignable(
765+
&self,
766+
lhs: &'tcx hir::Expr,
767+
err_code: &'static str,
768+
expr_span: &Span,
769+
) {
770+
if !lhs.is_syntactic_place_expr() {
771+
let mut err = self.tcx.sess.struct_span_err_with_code(
772+
*expr_span,
773+
"invalid left-hand side of assignment",
774+
DiagnosticId::Error(err_code.into()),
775+
);
776+
err.span_label(lhs.span, "cannot assign to this expression");
777+
let destructuring_assignment = match &lhs.kind {
778+
ExprKind::Array(comps) | ExprKind::Tup(comps) => {
779+
comps.iter().all(|e| e.is_syntactic_place_expr())
780+
}
781+
ExprKind::Struct(_path, fields, rest) => {
782+
rest.as_ref().map(|e| e.is_syntactic_place_expr()).unwrap_or(true) &&
783+
fields.iter().all(|f| f.expr.is_syntactic_place_expr())
784+
}
785+
_ => false,
786+
};
787+
if destructuring_assignment {
788+
err.note("destructuring assignments are not yet supported");
789+
err.note(
790+
"for more information, see https://github.com/rust-lang/rfcs/issues/372",
791+
);
792+
}
793+
err.emit();
794+
}
795+
}
796+
764797
/// Type check assignment expression `expr` of form `lhs = rhs`.
765798
/// The expected type is `()` and is passsed to the function for the purposes of diagnostics.
766799
fn check_expr_assign(
@@ -790,13 +823,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
790823
err.help(msg);
791824
}
792825
err.emit();
793-
} else if !lhs.is_syntactic_place_expr() {
794-
struct_span_err!(
795-
self.tcx.sess,
796-
expr.span,
797-
E0070,
798-
"invalid left-hand side of assignment",
799-
).span_label(lhs.span, "cannot assign to this expression").emit();
826+
} else {
827+
self.check_lhs_assignable(lhs, "E0070", &expr.span);
800828
}
801829

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

src/librustc_typeck/check/op.rs

+6-12
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 = if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var()
2929
&& is_builtin_binop(lhs_ty, rhs_ty, op) {
30-
self.enforce_builtin_binop_types(lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
30+
self.enforce_builtin_binop_types(lhs, lhs_ty, rhs, rhs_ty, 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)