Skip to content

Commit

Permalink
Rollup merge of rust-lang#83489 - LeSeulArtichaut:deref-else, r=david…
Browse files Browse the repository at this point in the history
…twco

Properly suggest deref in else block

Continues rust-lang#79755, fixes rust-lang#79736
r? `@davidtwco`
  • Loading branch information
JohnTitor committed Apr 5, 2021
2 parents e5edded + fb7cf09 commit d9f123a
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 1 deletion.
28 changes: 28 additions & 0 deletions compiler/rustc_typeck/src/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
false
}

/// If the given `HirId` corresponds to a block with a trailing expression, return that expression
crate fn maybe_get_block_expr(&self, hir_id: hir::HirId) -> Option<&'tcx hir::Expr<'tcx>> {
match self.tcx.hir().find(hir_id)? {
Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, ..), .. }) => block.expr,
_ => None,
}
}

/// Returns whether the given expression is an `else if`.
crate fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool {
if let hir::ExprKind::If(..) = expr.kind {
let parent_id = self.tcx.hir().get_parent_node(expr.hir_id);
if let Some(Node::Expr(hir::Expr {
kind: hir::ExprKind::If(_, _, Some(else_expr)),
..
})) = self.tcx.hir().find(parent_id)
{
return else_expr.hir_id == expr.hir_id;
}
}
false
}

/// This function is used to determine potential "simple" improvements or users' errors and
/// provide them useful help. For example:
///
Expand Down Expand Up @@ -652,6 +675,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let suggestion = if is_struct_pat_shorthand_field {
format!("{}: *{}", code, code)
} else if self.is_else_if_block(expr) {
// Don't suggest nonsense like `else *if`
return None;
} else if let Some(expr) = self.maybe_get_block_expr(expr.hir_id) {
format!("*{}", sm.span_to_snippet(expr.span).unwrap_or(code))
} else {
format!("*{}", code)
};
Expand Down
26 changes: 26 additions & 0 deletions src/test/ui/deref-suggestion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,30 @@ fn main() {
//~^ ERROR mismatched types
let r = R { i: i };
//~^ ERROR mismatched types


let a = &1;
let b = &2;
let val: i32 = if true {
a + 1
} else {
b
//~^ ERROR mismatched types
};
let val: i32 = if true {
let _ = 2;
a + 1
} else {
let _ = 2;
b
//~^ ERROR mismatched types
};
let val = if true {
*a
} else if true {
//~^ ERROR incompatible types
b
} else {
&0
};
}
39 changes: 38 additions & 1 deletion src/test/ui/deref-suggestion.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,43 @@ LL | let r = R { i: i };
| expected `u32`, found `&{integer}`
| help: consider dereferencing the borrow: `*i`

error: aborting due to 10 previous errors
error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:55:9
|
LL | b
| ^
| |
| expected `i32`, found `&{integer}`
| help: consider dereferencing the borrow: `*b`

error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:63:9
|
LL | b
| ^
| |
| expected `i32`, found `&{integer}`
| help: consider dereferencing the borrow: `*b`

error[E0308]: `if` and `else` have incompatible types
--> $DIR/deref-suggestion.rs:68:12
|
LL | let val = if true {
| _______________-
LL | | *a
| | -- expected because of this
LL | | } else if true {
| |____________^
LL | ||
LL | || b
LL | || } else {
LL | || &0
LL | || };
| || ^
| ||_____|
| |______`if` and `else` have incompatible types
| expected `i32`, found `&{integer}`

error: aborting due to 13 previous errors

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

0 comments on commit d9f123a

Please sign in to comment.