about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJonathan Brouwer <jonathantbrouwer@gmail.com>2025-05-31 18:34:26 +0200
committerJonathan Brouwer <jonathantbrouwer@gmail.com>2025-05-31 18:34:35 +0200
commitb1a1df2efe0a2d3af7d71566d09d4724a89e039a (patch)
tree7ad669f4bedc464ee1831e4e3f3b6450e0917122
parenta261d167ac33c8fa9fc5fd46f70f46679fefb5b9 (diff)
downloadrust-b1a1df2efe0a2d3af7d71566d09d4724a89e039a.tar.gz
rust-b1a1df2efe0a2d3af7d71566d09d4724a89e039a.zip
Fix consider borrowing for else-if
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs25
-rw-r--r--tests/ui/typeck/consider-borrowing-141810-1.stderr6
-rw-r--r--tests/ui/typeck/consider-borrowing-141810-2.stderr5
-rw-r--r--tests/ui/typeck/consider-borrowing-141810-3.stderr4
4 files changed, 29 insertions, 11 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 43b662ca453..1c3bc338d85 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -2713,6 +2713,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ));
                     }
 
+                    // Don't try to suggest ref/deref on an `if` expression, because:
+                    // - The `if` could be part of a desugared `if else` statement,
+                    //   which would create impossible suggestions such as `if ... { ... } else &if { ... } else { ... }`.
+                    // - In general the suggestions it creates such as `&if ... { ... } else { ... }` are not very helpful.
+                    // We try to generate a suggestion such as `if ... { &... } else { &... }` instead.
+                    if let hir::ExprKind::If(_c, then, els) = expr.kind {
+                        // The `then` of a `Expr::If` always contains a block, and that block may have a final expression that we can borrow
+                        // If the block does not have a final expression, it will return () and we do not make a suggestion to borrow that.
+                        let ExprKind::Block(then, _) = then.kind else { return None };
+                        let Some(then) = then.expr else { return None };
+                        let (mut suggs, help, app, verbose, mutref) =
+                            self.suggest_deref_or_ref(then, checked_ty, expected)?;
+
+                        // If there is no `else`, the return type of this `if` will be (), so suggesting to change the `then` block is useless
+                        let els_expr = match els?.kind {
+                            ExprKind::Block(block, _) => block.expr?,
+                            _ => els?,
+                        };
+                        let (else_suggs, ..) =
+                            self.suggest_deref_or_ref(els_expr, checked_ty, expected)?;
+                        suggs.extend(else_suggs);
+
+                        return Some((suggs, help, app, verbose, mutref));
+                    }
+
                     if let Some((sugg, msg)) = self.can_use_as_ref(expr) {
                         return Some((
                             sugg,
diff --git a/tests/ui/typeck/consider-borrowing-141810-1.stderr b/tests/ui/typeck/consider-borrowing-141810-1.stderr
index 3cb5d23d3a7..9291721ac71 100644
--- a/tests/ui/typeck/consider-borrowing-141810-1.stderr
+++ b/tests/ui/typeck/consider-borrowing-141810-1.stderr
@@ -18,8 +18,10 @@ LL | ||     };
    |
 help: consider borrowing here
    |
-LL |     } else &if false {
-   |            +
+LL ~         &true
+LL |     } else {
+LL ~         &true
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/typeck/consider-borrowing-141810-2.stderr b/tests/ui/typeck/consider-borrowing-141810-2.stderr
index b00384d2d5a..dd229897283 100644
--- a/tests/ui/typeck/consider-borrowing-141810-2.stderr
+++ b/tests/ui/typeck/consider-borrowing-141810-2.stderr
@@ -13,11 +13,6 @@ LL | ||     };
    | ||_____|
    |  |_____`if` and `else` have incompatible types
    |        expected `&()`, found `()`
-   |
-help: consider borrowing here
-   |
-LL |     } else &if false {
-   |            +
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/typeck/consider-borrowing-141810-3.stderr b/tests/ui/typeck/consider-borrowing-141810-3.stderr
index f33920d1325..0b0c5f191a0 100644
--- a/tests/ui/typeck/consider-borrowing-141810-3.stderr
+++ b/tests/ui/typeck/consider-borrowing-141810-3.stderr
@@ -16,10 +16,6 @@ LL | ||     };
    |
    = note: `if` expressions without `else` evaluate to `()`
    = note: consider adding an `else` block that evaluates to the expected type
-help: consider borrowing here
-   |
-LL |     } else &if false {
-   |            +
 
 error: aborting due to 1 previous error