Skip to content

Commit d9f123a

Browse files
authored
Rollup merge of #83489 - LeSeulArtichaut:deref-else, r=davidtwco
Properly suggest deref in else block Continues #79755, fixes #79736 r? `@davidtwco`
2 parents e5edded + fb7cf09 commit d9f123a

File tree

3 files changed

+92
-1
lines changed

3 files changed

+92
-1
lines changed

compiler/rustc_typeck/src/check/demand.rs

+28
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
366366
false
367367
}
368368

369+
/// If the given `HirId` corresponds to a block with a trailing expression, return that expression
370+
crate fn maybe_get_block_expr(&self, hir_id: hir::HirId) -> Option<&'tcx hir::Expr<'tcx>> {
371+
match self.tcx.hir().find(hir_id)? {
372+
Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, ..), .. }) => block.expr,
373+
_ => None,
374+
}
375+
}
376+
377+
/// Returns whether the given expression is an `else if`.
378+
crate fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool {
379+
if let hir::ExprKind::If(..) = expr.kind {
380+
let parent_id = self.tcx.hir().get_parent_node(expr.hir_id);
381+
if let Some(Node::Expr(hir::Expr {
382+
kind: hir::ExprKind::If(_, _, Some(else_expr)),
383+
..
384+
})) = self.tcx.hir().find(parent_id)
385+
{
386+
return else_expr.hir_id == expr.hir_id;
387+
}
388+
}
389+
false
390+
}
391+
369392
/// This function is used to determine potential "simple" improvements or users' errors and
370393
/// provide them useful help. For example:
371394
///
@@ -652,6 +675,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
652675
};
653676
let suggestion = if is_struct_pat_shorthand_field {
654677
format!("{}: *{}", code, code)
678+
} else if self.is_else_if_block(expr) {
679+
// Don't suggest nonsense like `else *if`
680+
return None;
681+
} else if let Some(expr) = self.maybe_get_block_expr(expr.hir_id) {
682+
format!("*{}", sm.span_to_snippet(expr.span).unwrap_or(code))
655683
} else {
656684
format!("*{}", code)
657685
};

src/test/ui/deref-suggestion.rs

+26
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,30 @@ fn main() {
4545
//~^ ERROR mismatched types
4646
let r = R { i: i };
4747
//~^ ERROR mismatched types
48+
49+
50+
let a = &1;
51+
let b = &2;
52+
let val: i32 = if true {
53+
a + 1
54+
} else {
55+
b
56+
//~^ ERROR mismatched types
57+
};
58+
let val: i32 = if true {
59+
let _ = 2;
60+
a + 1
61+
} else {
62+
let _ = 2;
63+
b
64+
//~^ ERROR mismatched types
65+
};
66+
let val = if true {
67+
*a
68+
} else if true {
69+
//~^ ERROR incompatible types
70+
b
71+
} else {
72+
&0
73+
};
4874
}

src/test/ui/deref-suggestion.stderr

+38-1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,43 @@ LL | let r = R { i: i };
8989
| expected `u32`, found `&{integer}`
9090
| help: consider dereferencing the borrow: `*i`
9191

92-
error: aborting due to 10 previous errors
92+
error[E0308]: mismatched types
93+
--> $DIR/deref-suggestion.rs:55:9
94+
|
95+
LL | b
96+
| ^
97+
| |
98+
| expected `i32`, found `&{integer}`
99+
| help: consider dereferencing the borrow: `*b`
100+
101+
error[E0308]: mismatched types
102+
--> $DIR/deref-suggestion.rs:63:9
103+
|
104+
LL | b
105+
| ^
106+
| |
107+
| expected `i32`, found `&{integer}`
108+
| help: consider dereferencing the borrow: `*b`
109+
110+
error[E0308]: `if` and `else` have incompatible types
111+
--> $DIR/deref-suggestion.rs:68:12
112+
|
113+
LL | let val = if true {
114+
| _______________-
115+
LL | | *a
116+
| | -- expected because of this
117+
LL | | } else if true {
118+
| |____________^
119+
LL | ||
120+
LL | || b
121+
LL | || } else {
122+
LL | || &0
123+
LL | || };
124+
| || ^
125+
| ||_____|
126+
| |______`if` and `else` have incompatible types
127+
| expected `i32`, found `&{integer}`
128+
129+
error: aborting due to 13 previous errors
93130

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

0 commit comments

Comments
 (0)