diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2fef7c2cc08..f4402843afc 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1577,6 +1577,14 @@ impl Expr<'_> { expr } + pub fn peel_blocks(&self) -> &Self { + let mut expr = self; + while let ExprKind::Block(Block { expr: Some(inner), .. }, _) = &expr.kind { + expr = inner; + } + expr + } + pub fn can_have_side_effects(&self) -> bool { match self.peel_drop_temps().kind { ExprKind::Path(_) | ExprKind::Lit(_) => false, diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 8d2004a543b..39b973ed371 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -616,10 +616,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ if sp == expr.span && !is_macro => { if let Some(steps) = self.deref_steps(checked_ty, expected) { + let expr = expr.peel_blocks(); + if steps == 1 { - // For a suggestion to make sense, the type would need to be `Copy`. - if self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp) { - if let Ok(code) = sm.span_to_snippet(sp) { + if let hir::ExprKind::AddrOf(_, mutbl, inner) = expr.kind { + // If the expression has `&`, removing it would fix the error + let prefix_span = expr.span.with_hi(inner.span.lo()); + let message = match mutbl { + hir::Mutability::Not => "consider removing the `&`", + hir::Mutability::Mut => "consider removing the `&mut`", + }; + let suggestion = String::new(); + return Some(( + prefix_span, + message, + suggestion, + Applicability::MachineApplicable, + )); + } else if self.infcx.type_is_copy_modulo_regions( + self.param_env, + expected, + sp, + ) { + // For this suggestion to make sense, the type would need to be `Copy`. + if let Ok(code) = sm.span_to_snippet(expr.span) { let message = if checked_ty.is_region_ptr() { "consider dereferencing the borrow" } else { @@ -631,7 +651,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("*{}", code) }; return Some(( - sp, + expr.span, message, suggestion, Applicability::MachineApplicable, diff --git a/src/test/ui/suggestions/issue-82361.fixed b/src/test/ui/suggestions/issue-82361.fixed new file mode 100644 index 00000000000..d72de982bf9 --- /dev/null +++ b/src/test/ui/suggestions/issue-82361.fixed @@ -0,0 +1,24 @@ +// run-rustfix + +fn main() { + let a: usize = 123; + let b: &usize = &a; + + if true { + a + } else { + *b //~ ERROR `if` and `else` have incompatible types [E0308] + }; + + if true { + 1 + } else { + 1 //~ ERROR `if` and `else` have incompatible types [E0308] + }; + + if true { + 1 + } else { + 1 //~ ERROR `if` and `else` have incompatible types [E0308] + }; +} diff --git a/src/test/ui/suggestions/issue-82361.rs b/src/test/ui/suggestions/issue-82361.rs new file mode 100644 index 00000000000..c068f6d22b4 --- /dev/null +++ b/src/test/ui/suggestions/issue-82361.rs @@ -0,0 +1,24 @@ +// run-rustfix + +fn main() { + let a: usize = 123; + let b: &usize = &a; + + if true { + a + } else { + b //~ ERROR `if` and `else` have incompatible types [E0308] + }; + + if true { + 1 + } else { + &1 //~ ERROR `if` and `else` have incompatible types [E0308] + }; + + if true { + 1 + } else { + &mut 1 //~ ERROR `if` and `else` have incompatible types [E0308] + }; +} diff --git a/src/test/ui/suggestions/issue-82361.stderr b/src/test/ui/suggestions/issue-82361.stderr new file mode 100644 index 00000000000..c19d59ccd4c --- /dev/null +++ b/src/test/ui/suggestions/issue-82361.stderr @@ -0,0 +1,48 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-82361.rs:10:9 + | +LL | / if true { +LL | | a + | | - expected because of this +LL | | } else { +LL | | b + | | ^ + | | | + | | expected `usize`, found `&usize` + | | help: consider dereferencing the borrow: `*b` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-82361.rs:16:9 + | +LL | / if true { +LL | | 1 + | | - expected because of this +LL | | } else { +LL | | &1 + | | -^ + | | | + | | expected integer, found `&{integer}` + | | help: consider removing the `&` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-82361.rs:22:9 + | +LL | / if true { +LL | | 1 + | | - expected because of this +LL | | } else { +LL | | &mut 1 + | | -----^ + | | | + | | expected integer, found `&mut {integer}` + | | help: consider removing the `&mut` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`.