diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index c43d4932fb9..2e0ab1560f4 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2326,14 +2326,6 @@ pub(crate) fn suggest_deref_or_ref( )); } - let needs_parens = match expr.kind { - // parenthesize if needed (Issue #46756) - hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true, - // parenthesize borrows of range literals (Issue #54505) - _ if is_range_literal(expr) => true, - _ => false, - }; - if let Some((sugg, msg)) = self.can_use_as_ref(expr) { return Some(( sugg, @@ -2361,18 +2353,48 @@ pub(crate) fn suggest_deref_or_ref( } } - let sugg = mutability.ref_prefix_str(); - let (sugg, verbose) = if needs_parens { - ( - vec![ - (sp.shrink_to_lo(), format!("{prefix}{sugg}(")), - (sp.shrink_to_hi(), ")".to_string()), - ], - false, - ) - } else { - (vec![(sp.shrink_to_lo(), format!("{prefix}{sugg}"))], true) + let make_sugg = |expr: &Expr<'_>, span: Span, sugg: &str| { + let needs_parens = match expr.kind { + // parenthesize if needed (Issue #46756) + hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true, + // parenthesize borrows of range literals (Issue #54505) + _ if is_range_literal(expr) => true, + _ => false, + }; + + if needs_parens { + ( + vec![ + (span.shrink_to_lo(), format!("{prefix}{sugg}(")), + (span.shrink_to_hi(), ")".to_string()), + ], + false, + ) + } else { + (vec![(span.shrink_to_lo(), format!("{prefix}{sugg}"))], true) + } }; + + // Suggest dereferencing the lhs for expressions such as `&T == T` + if let Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Binary(_, lhs, ..), + .. + })) = self.tcx.hir().find_parent(expr.hir_id) + && let &ty::Ref(..) = self.check_expr(lhs).kind() + { + let (sugg, verbose) = make_sugg(lhs, lhs.span, "*"); + + return Some(( + sugg, + "consider dereferencing the borrow".to_string(), + Applicability::MachineApplicable, + verbose, + false, + )); + } + + let sugg = mutability.ref_prefix_str(); + let (sugg, verbose) = make_sugg(expr, sp, sugg); return Some(( sugg, format!("consider {}borrowing here", mutability.mutably_str()), diff --git a/tests/ui/binop/binary-op-suggest-deref.fixed b/tests/ui/binop/binary-op-suggest-deref.fixed new file mode 100644 index 00000000000..1ff3599137b --- /dev/null +++ b/tests/ui/binop/binary-op-suggest-deref.fixed @@ -0,0 +1,8 @@ +// Issue #52544 +// run-rustfix + +fn main() { + let i: &i64 = &1; + if *i < 0 {} + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/binop/binary-op-suggest-deref.rs b/tests/ui/binop/binary-op-suggest-deref.rs new file mode 100644 index 00000000000..12505a9ac27 --- /dev/null +++ b/tests/ui/binop/binary-op-suggest-deref.rs @@ -0,0 +1,8 @@ +// Issue #52544 +// run-rustfix + +fn main() { + let i: &i64 = &1; + if i < 0 {} + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/binop/binary-op-suggest-deref.stderr b/tests/ui/binop/binary-op-suggest-deref.stderr new file mode 100644 index 00000000000..1b7e45c7724 --- /dev/null +++ b/tests/ui/binop/binary-op-suggest-deref.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/binary-op-suggest-deref.rs:6:12 + | +LL | if i < 0 {} + | ^ expected `&i64`, found integer + | +help: consider dereferencing the borrow + | +LL | if *i < 0 {} + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.