diff options
| author | Jonathan Brouwer <jonathantbrouwer@gmail.com> | 2025-05-31 18:34:26 +0200 |
|---|---|---|
| committer | Jonathan Brouwer <jonathantbrouwer@gmail.com> | 2025-05-31 18:34:35 +0200 |
| commit | b1a1df2efe0a2d3af7d71566d09d4724a89e039a (patch) | |
| tree | 7ad669f4bedc464ee1831e4e3f3b6450e0917122 | |
| parent | a261d167ac33c8fa9fc5fd46f70f46679fefb5b9 (diff) | |
| download | rust-b1a1df2efe0a2d3af7d71566d09d4724a89e039a.tar.gz rust-b1a1df2efe0a2d3af7d71566d09d4724a89e039a.zip | |
Fix consider borrowing for else-if
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 |
