Rollup merge of #141812 - JonathanBrouwer:fix-else-if-help, r=jdonszelmann
Fix "consider borrowing" for else-if Fixes rust-lang/rust#141810 When trying to suggest a borrow on a `if` or `block` expression, instead we now recurse into the `if` or `block`. The comments in the code should explain the goal of the new code. r? ``@jdonszelmann``
This commit is contained in:
commit
542dcbf6a2
9 changed files with 143 additions and 0 deletions
|
|
@ -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,
|
||||
|
|
|
|||
9
tests/ui/typeck/consider-borrowing-141810-1.rs
Normal file
9
tests/ui/typeck/consider-borrowing-141810-1.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
fn main() {
|
||||
let x = if true {
|
||||
&true
|
||||
} else if false { //~ ERROR `if` and `else` have incompatible types [E0308]
|
||||
true //~ HELP consider borrowing here
|
||||
} else {
|
||||
true
|
||||
};
|
||||
}
|
||||
28
tests/ui/typeck/consider-borrowing-141810-1.stderr
Normal file
28
tests/ui/typeck/consider-borrowing-141810-1.stderr
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
error[E0308]: `if` and `else` have incompatible types
|
||||
--> $DIR/consider-borrowing-141810-1.rs:4:12
|
||||
|
|
||||
LL | let x = if true {
|
||||
| ______________-
|
||||
LL | | &true
|
||||
| | ----- expected because of this
|
||||
LL | | } else if false {
|
||||
| | ____________^
|
||||
LL | || true
|
||||
LL | || } else {
|
||||
LL | || true
|
||||
LL | || };
|
||||
| || ^
|
||||
| ||_____|
|
||||
| |_____`if` and `else` have incompatible types
|
||||
| expected `&bool`, found `bool`
|
||||
|
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL ~ &true
|
||||
LL | } else {
|
||||
LL ~ &true
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
8
tests/ui/typeck/consider-borrowing-141810-2.rs
Normal file
8
tests/ui/typeck/consider-borrowing-141810-2.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fn main() {
|
||||
let x = if true {
|
||||
&()
|
||||
} else if false { //~ ERROR `if` and `else` have incompatible types [E0308]
|
||||
} else {
|
||||
};
|
||||
|
||||
}
|
||||
19
tests/ui/typeck/consider-borrowing-141810-2.stderr
Normal file
19
tests/ui/typeck/consider-borrowing-141810-2.stderr
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
error[E0308]: `if` and `else` have incompatible types
|
||||
--> $DIR/consider-borrowing-141810-2.rs:4:12
|
||||
|
|
||||
LL | let x = if true {
|
||||
| ______________-
|
||||
LL | | &()
|
||||
| | --- expected because of this
|
||||
LL | | } else if false {
|
||||
| | ____________^
|
||||
LL | || } else {
|
||||
LL | || };
|
||||
| || ^
|
||||
| ||_____|
|
||||
| |_____`if` and `else` have incompatible types
|
||||
| expected `&()`, found `()`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
7
tests/ui/typeck/consider-borrowing-141810-3.rs
Normal file
7
tests/ui/typeck/consider-borrowing-141810-3.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
fn main() {
|
||||
let x = if true {
|
||||
&()
|
||||
} else if false { //~ ERROR `if` and `else` have incompatible types [E0308]
|
||||
|
||||
};
|
||||
}
|
||||
22
tests/ui/typeck/consider-borrowing-141810-3.stderr
Normal file
22
tests/ui/typeck/consider-borrowing-141810-3.stderr
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
error[E0308]: `if` and `else` have incompatible types
|
||||
--> $DIR/consider-borrowing-141810-3.rs:4:12
|
||||
|
|
||||
LL | let x = if true {
|
||||
| ______________-
|
||||
LL | | &()
|
||||
| | --- expected because of this
|
||||
LL | | } else if false {
|
||||
| | ____________^
|
||||
LL | ||
|
||||
LL | || };
|
||||
| || ^
|
||||
| ||_____|
|
||||
| |_____`if` and `else` have incompatible types
|
||||
| expected `&()`, found `()`
|
||||
|
|
||||
= note: `if` expressions without `else` evaluate to `()`
|
||||
= note: consider adding an `else` block that evaluates to the expected type
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
11
tests/ui/typeck/consider-borrowing-141810-4.rs
Normal file
11
tests/ui/typeck/consider-borrowing-141810-4.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fn baz(x: &String) {}
|
||||
|
||||
fn bar() {
|
||||
baz({
|
||||
String::from("hi") //~ ERROR mismatched types
|
||||
});
|
||||
}
|
||||
|
||||
fn main() {
|
||||
bar();
|
||||
}
|
||||
14
tests/ui/typeck/consider-borrowing-141810-4.stderr
Normal file
14
tests/ui/typeck/consider-borrowing-141810-4.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/consider-borrowing-141810-4.rs:5:9
|
||||
|
|
||||
LL | String::from("hi")
|
||||
| ^^^^^^^^^^^^^^^^^^ expected `&String`, found `String`
|
||||
|
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | &String::from("hi")
|
||||
| +
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue