1
Fork 0

Rollup merge of #79016 - fanzier:underscore-expressions, r=petrochenkov

Make `_` an expression, to discard values in destructuring assignments

This is the third and final step towards implementing destructuring assignment (RFC: rust-lang/rfcs#2909, tracking issue: #71126). This PR is the third and final part of #71156, which was split up to allow for easier review.

With this PR, an underscore `_` is parsed as an expression but is allowed *only* on the left-hand side of a destructuring assignment. There it simply discards a value, similarly to the wildcard `_` in patterns. For instance,
```rust
(a, _) = (1, 2)
```
will simply assign 1 to `a` and discard the 2. Note that for consistency,
```
_ = foo
```
is also allowed and equivalent to just `foo`.

Thanks to ````@varkor```` who helped with the implementation, particularly around pre-expansion gating.

r? ````@petrochenkov````
This commit is contained in:
Jonas Schievink 2020-11-15 13:39:48 +01:00 committed by GitHub
commit f66af28641
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 243 additions and 45 deletions

View file

@ -164,6 +164,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::Range(ref e1, ref e2, lims) => {
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims)
}
ExprKind::Underscore => {
self.sess
.struct_span_err(
e.span,
"in expressions, `_` can only be used on the left-hand side of an assignment",
)
.span_label(e.span, "`_` not allowed here")
.emit();
hir::ExprKind::Err
}
ExprKind::Path(ref qself, ref path) => {
let qpath = self.lower_qpath(
e.id,
@ -863,7 +873,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Return early in case of an ordinary assignment.
fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool {
match &lhs.kind {
ExprKind::Array(..) | ExprKind::Struct(..) | ExprKind::Tup(..) => false,
ExprKind::Array(..)
| ExprKind::Struct(..)
| ExprKind::Tup(..)
| ExprKind::Underscore => false,
// Check for tuple struct constructor.
ExprKind::Call(callee, ..) => lower_ctx.extract_tuple_struct_path(callee).is_none(),
ExprKind::Paren(e) => {
@ -943,6 +956,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
assignments: &mut Vec<hir::Stmt<'hir>>,
) -> &'hir hir::Pat<'hir> {
match &lhs.kind {
// Underscore pattern.
ExprKind::Underscore => {
return self.pat_without_dbm(lhs.span, hir::PatKind::Wild);
}
// Slice patterns.
ExprKind::Array(elements) => {
let (pats, rest) =