diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-09-29 20:34:15 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-09-29 20:34:15 +0200 |
| commit | 8109332a4c7a022aaf9d778a59e855c9e91ee9d4 (patch) | |
| tree | 57cdd16913e74f63e1b998b4b9a582be62fe256d /src/librustc | |
| parent | f34e2b1e7cbbc77d1fadcdb613c3db9c79841e5f (diff) | |
| parent | c861e24e7251fcbf0cbb8b85c676afe6b901f8af (diff) | |
| download | rust-8109332a4c7a022aaf9d778a59e855c9e91ee9d4.tar.gz rust-8109332a4c7a022aaf9d778a59e855c9e91ee9d4.zip | |
Rollup merge of #64825 - estebank:match-unit, r=Centril
Point at enclosing match when expecting `()` in arm
When encountering code like the following:
```rust
fn main() {
match 3 {
4 => 1,
3 => {
println!("Yep it maches.");
2
}
_ => 2
}
println!("Bye!")
}
```
point at the enclosing `match` expression and suggest ignoring the
returned value:
```
error[E0308]: mismatched types
--> $DIR/match-needing-semi.rs:8:13
|
LL | / match 3 {
LL | | 4 => 1,
LL | | 3 => {
LL | | 2
| | ^ expected (), found integer
LL | | }
LL | | _ => 2
LL | | }
| | -- help: consider using a semicolon here
| |_____|
| expected this to be `()`
|
= note: expected type `()`
found type `{integer}
```
Fix #40799.
Diffstat (limited to 'src/librustc')
| -rw-r--r-- | src/librustc/hir/lowering/expr.rs | 23 | ||||
| -rw-r--r-- | src/librustc/hir/map/mod.rs | 26 |
2 files changed, 37 insertions, 12 deletions
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index 2f0a318d536..9dcecedd97c 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -1037,10 +1037,9 @@ impl LoweringContext<'_> { ) -> hir::Expr { // expand <head> let mut head = self.lower_expr(head); - let head_sp = head.span; let desugared_span = self.mark_span_with_reason( DesugaringKind::ForLoop, - head_sp, + head.span, None, ); head.span = desugared_span; @@ -1086,21 +1085,21 @@ impl LoweringContext<'_> { // `match ::std::iter::Iterator::next(&mut iter) { ... }` let match_expr = { - let iter = P(self.expr_ident(head_sp, iter, iter_pat_nid)); - let ref_mut_iter = self.expr_mut_addr_of(head_sp, iter); + let iter = P(self.expr_ident(desugared_span, iter, iter_pat_nid)); + let ref_mut_iter = self.expr_mut_addr_of(desugared_span, iter); let next_path = &[sym::iter, sym::Iterator, sym::next]; let next_expr = P(self.expr_call_std_path( - head_sp, + desugared_span, next_path, hir_vec![ref_mut_iter], )); let arms = hir_vec![pat_arm, break_arm]; - self.expr_match(head_sp, next_expr, arms, hir::MatchSource::ForLoopDesugar) + self.expr_match(desugared_span, next_expr, arms, hir::MatchSource::ForLoopDesugar) }; - let match_stmt = self.stmt_expr(head_sp, match_expr); + let match_stmt = self.stmt_expr(desugared_span, match_expr); - let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_hid)); + let next_expr = P(self.expr_ident(desugared_span, next_ident, next_pat_hid)); // `let mut __next` let next_let = self.stmt_let_pat( @@ -1115,7 +1114,7 @@ impl LoweringContext<'_> { let pat = self.lower_pat(pat); let pat_let = self.stmt_let_pat( ThinVec::new(), - head_sp, + desugared_span, Some(next_expr), pat, hir::LocalSource::ForLoopDesugar, @@ -1152,14 +1151,14 @@ impl LoweringContext<'_> { let into_iter_path = &[sym::iter, sym::IntoIterator, sym::into_iter]; P(self.expr_call_std_path( - head_sp, + desugared_span, into_iter_path, hir_vec![head], )) }; let match_expr = P(self.expr_match( - head_sp, + desugared_span, into_iter_expr, hir_vec![iter_arm], hir::MatchSource::ForLoopDesugar, @@ -1171,7 +1170,7 @@ impl LoweringContext<'_> { // surrounding scope of the `match` since the `match` is not a terminating scope. // // Also, add the attributes to the outer returned expr node. - self.expr_drop_temps(head_sp, match_expr, e.attrs.clone()) + self.expr_drop_temps(desugared_span, match_expr, e.attrs.clone()) } /// Desugar `ExprKind::Try` from: `<expr>?` into: diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 42a4a9909f8..a1011697ef1 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -818,6 +818,32 @@ impl<'hir> Map<'hir> { CRATE_HIR_ID } + /// When on a match arm tail expression or on a match arm, give back the enclosing `match` + /// expression. + /// + /// Used by error reporting when there's a type error in a match arm caused by the `match` + /// expression needing to be unit. + pub fn get_match_if_cause(&self, hir_id: HirId) -> Option<&Expr> { + for (_, node) in ParentHirIterator::new(hir_id, &self) { + match node { + Node::Item(_) | + Node::ForeignItem(_) | + Node::TraitItem(_) | + Node::ImplItem(_) => break, + Node::Expr(expr) => match expr.kind { + ExprKind::Match(_, _, _) => return Some(expr), + _ => {} + }, + Node::Stmt(stmt) => match stmt.kind { + StmtKind::Local(_) => break, + _ => {} + } + _ => {} + } + } + None + } + /// Returns the nearest enclosing scope. A scope is roughly an item or block. pub fn get_enclosing_scope(&self, hir_id: HirId) -> Option<HirId> { for (hir_id, node) in ParentHirIterator::new(hir_id, &self) { |
