Skip to content

Commit 3631ab5

Browse files
committed
Allow _ on the LHS of an assignment to discard a value
1 parent f54533b commit 3631ab5

14 files changed

+75
-10
lines changed

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
871871
) -> hir::ExprKind<'hir> {
872872
// Return early in case of an ordinary assignment.
873873
let is_ordinary = match &lhs.kind {
874-
ExprKind::Array(..) | ExprKind::Struct(_, _, None) | ExprKind::Tup(..) => false,
874+
ExprKind::Array(..)
875+
| ExprKind::Struct(_, _, None)
876+
| ExprKind::Tup(..)
877+
| ExprKind::Underscore => false,
875878
ExprKind::Call(callee, ..) => {
876879
// Check for tuple struct constructor.
877880
if let ExprKind::Path(qself, path) = &callee.kind {
@@ -931,8 +934,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
931934
eq_sign_span: Span,
932935
assignments: &mut Vec<hir::Stmt<'hir>>,
933936
) -> &'hir hir::Pat<'hir> {
934-
// FIXME: Handle `_`, requires changes to the parser
935937
match &lhs.kind {
938+
ExprKind::Underscore => {
939+
return self.pat(lhs.span, hir::PatKind::Wild);
940+
}
936941
// slices:
937942
ExprKind::Array(elements) => {
938943
let (pats, rest) =

src/test/ui/destructuring-assignment/nested_destructure.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,7 @@ fn main() {
1414
Struct { a: TupleStruct((a, b), c), b: [d] } =
1515
Struct { a: TupleStruct((0, 1), 2), b: [3] };
1616
assert_eq!((a, b, c, d), (0, 1, 2, 3));
17+
18+
// unnested underscore: just discard
19+
_ = 1;
1720
}

src/test/ui/destructuring-assignment/slice_destructure.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ fn main() {
88
assert_eq!((a,b), (0,1));
99
[a, .., b] = [1,2];
1010
assert_eq!((a,b), (1,2));
11+
[_, a] = [1,2];
12+
assert_eq!((a,b), (2,2));
1113
}

src/test/ui/destructuring-assignment/slice_destructure_fail.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ fn main() {
44
let (mut a, mut b);
55
[a, .., b, ..] = [0, 1]; //~ ERROR `..` can only be used once per slice pattern
66
[a, a, b] = [1,2]; //~ ERROR pattern requires 3 elements but array has 2
7+
[_] = [1,2]; //~ ERROR pattern requires 1 element but array has 2
78
}

src/test/ui/destructuring-assignment/slice_destructure_fail.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ error[E0527]: pattern requires 3 elements but array has 2
1212
LL | [a, a, b] = [1,2];
1313
| ^^^^^^^^^ expected 2 elements
1414

15-
error: aborting due to 2 previous errors
15+
error[E0527]: pattern requires 1 element but array has 2
16+
--> $DIR/slice_destructure_fail.rs:7:3
17+
|
18+
LL | [_] = [1,2];
19+
| ^^^ expected 2 elements
20+
21+
error: aborting due to 3 previous errors
1622

1723
For more information about this error, try `rustc --explain E0527`.

src/test/ui/destructuring-assignment/struct_destructure.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ struct Struct<S, T> {
77
}
88

99
fn main() {
10-
let (a, b);
10+
let (mut a, mut b);
1111
Struct { a, b } = Struct { a: 0, b: 1 };
1212
assert_eq!((a, b), (0, 1));
13+
Struct { a: b, b: a } = Struct { a: 1, b: 2};
14+
assert_eq!((a,b), (2,1));
15+
Struct { a: _, b } = Struct { a: 1, b: 2 };
16+
assert_eq!((a,b), (2,2));
1317
}

src/test/ui/destructuring-assignment/struct_destructure_fail.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ fn main() {
88
let (mut a, b);
99
let mut c;
1010
Struct { a, b, c } = Struct { a: 0, b: 1 }; //~ ERROR does not have a field named `c`
11+
Struct { a, _ } = Struct { a: 1, b: 2 }; //~ ERROR pattern does not mention field `b`
12+
//~| ERROR expected identifier, found reserved identifier `_`
1113
}
Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
1+
error: expected identifier, found reserved identifier `_`
2+
--> $DIR/struct_destructure_fail.rs:11:17
3+
|
4+
LL | Struct { a, _ } = Struct { a: 1, b: 2 };
5+
| ------ ^ expected identifier, found reserved identifier
6+
| |
7+
| while parsing this struct
8+
19
error[E0026]: struct `Struct` does not have a field named `c`
210
--> $DIR/struct_destructure_fail.rs:10:20
311
|
412
LL | Struct { a, b, c } = Struct { a: 0, b: 1 };
513
| ^ struct `Struct` does not have this field
614

7-
error: aborting due to previous error
15+
error[E0027]: pattern does not mention field `b`
16+
--> $DIR/struct_destructure_fail.rs:11:5
17+
|
18+
LL | Struct { a, _ } = Struct { a: 1, b: 2 };
19+
| ^^^^^^^^^^^^^^^ missing field `b`
20+
21+
error: aborting due to 3 previous errors
822

9-
For more information about this error, try `rustc --explain E0026`.
23+
Some errors have detailed explanations: E0026, E0027.
24+
For more information about an error, try `rustc --explain E0026`.

src/test/ui/destructuring-assignment/tuple_destructure.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ fn main() {
88
assert_eq!((a,b), (0,1));
99
(a, .., b) = (1,2);
1010
assert_eq!((a,b), (1,2));
11+
(_, a) = (1,2);
12+
assert_eq!((a,b), (2,2));
1113
}

src/test/ui/destructuring-assignment/tuple_destructure_fail.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ fn main() {
44
let (mut a, mut b);
55
(a, .., b, ..) = (0, 1); //~ ERROR `..` can only be used once per tuple pattern
66
(a, a, b) = (1,2); //~ ERROR mismatched types
7+
(_,) = (1,2); //~ ERROR mismatched types
78
}

0 commit comments

Comments
 (0)