Suggest boxing if then expr if that solves divergent arms
When encountering ```rust let _ = if true { Struct } else { foo() // -> Box<dyn Trait> }; ``` if `Struct` implements `Trait`, suggest boxing the then arm tail expression. Part of #102629.
This commit is contained in:
parent
390ef9ba02
commit
ac56a2b564
4 changed files with 63 additions and 1 deletions
|
@ -330,6 +330,38 @@ impl<T> Trait<T> for X {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(ty::Adt(_, _), ty::Adt(def, args))
|
||||||
|
if let ObligationCauseCode::IfExpression(cause) = cause.code()
|
||||||
|
&& let hir::Node::Block(blk) = self.tcx.hir_node(cause.then_id)
|
||||||
|
&& let Some(then) = blk.expr
|
||||||
|
&& def.is_box()
|
||||||
|
&& let boxed_ty = args.type_at(0)
|
||||||
|
&& let ty::Dynamic(t, _, _) = boxed_ty.kind()
|
||||||
|
&& let Some(def_id) = t.principal_def_id()
|
||||||
|
&& let mut impl_def_ids = vec![]
|
||||||
|
&& let _ =
|
||||||
|
tcx.for_each_relevant_impl(def_id, values.expected, |did| {
|
||||||
|
impl_def_ids.push(did)
|
||||||
|
})
|
||||||
|
&& let [_] = &impl_def_ids[..] =>
|
||||||
|
{
|
||||||
|
// We have divergent if/else arms where the expected value is a type that
|
||||||
|
// implements the trait of the found boxed trait object.
|
||||||
|
diag.multipart_suggestion(
|
||||||
|
format!(
|
||||||
|
"`{}` implements `{}` so you can box it to coerce to the trait \
|
||||||
|
object `{}`",
|
||||||
|
values.expected,
|
||||||
|
tcx.item_name(def_id),
|
||||||
|
values.found,
|
||||||
|
),
|
||||||
|
vec![
|
||||||
|
(then.span.shrink_to_lo(), "Box::new(".to_string()),
|
||||||
|
(then.span.shrink_to_hi(), ")".to_string()),
|
||||||
|
],
|
||||||
|
MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
debug!(
|
debug!(
|
||||||
|
|
|
@ -6,6 +6,11 @@ fn foo() -> Box<dyn Trait> {
|
||||||
Box::new(Struct)
|
Box::new(Struct)
|
||||||
}
|
}
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let _ = if true {
|
||||||
|
Box::new(Struct)
|
||||||
|
} else {
|
||||||
|
foo() //~ ERROR E0308
|
||||||
|
};
|
||||||
let _ = if true {
|
let _ = if true {
|
||||||
foo()
|
foo()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -6,6 +6,11 @@ fn foo() -> Box<dyn Trait> {
|
||||||
Box::new(Struct)
|
Box::new(Struct)
|
||||||
}
|
}
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let _ = if true {
|
||||||
|
Struct
|
||||||
|
} else {
|
||||||
|
foo() //~ ERROR E0308
|
||||||
|
};
|
||||||
let _ = if true {
|
let _ = if true {
|
||||||
foo()
|
foo()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3,6 +3,26 @@ error[E0308]: `if` and `else` have incompatible types
|
||||||
|
|
|
|
||||||
LL | let _ = if true {
|
LL | let _ = if true {
|
||||||
| _____________-
|
| _____________-
|
||||||
|
LL | | Struct
|
||||||
|
| | ------ expected because of this
|
||||||
|
LL | | } else {
|
||||||
|
LL | | foo()
|
||||||
|
| | ^^^^^ expected `Struct`, found `Box<dyn Trait>`
|
||||||
|
LL | | };
|
||||||
|
| |_____- `if` and `else` have incompatible types
|
||||||
|
|
|
||||||
|
= note: expected struct `Struct`
|
||||||
|
found struct `Box<dyn Trait>`
|
||||||
|
help: `Struct` implements `Trait` so you can box it to coerce to the trait object `Box<dyn Trait>`
|
||||||
|
|
|
||||||
|
LL | Box::new(Struct)
|
||||||
|
| +++++++++ +
|
||||||
|
|
||||||
|
error[E0308]: `if` and `else` have incompatible types
|
||||||
|
--> $DIR/suggest-box-on-divergent-if-else-arms.rs:17:9
|
||||||
|
|
|
||||||
|
LL | let _ = if true {
|
||||||
|
| _____________-
|
||||||
LL | | foo()
|
LL | | foo()
|
||||||
| | ----- expected because of this
|
| | ----- expected because of this
|
||||||
LL | | } else {
|
LL | | } else {
|
||||||
|
@ -19,6 +39,6 @@ help: store this in the heap by calling `Box::new`
|
||||||
LL | Box::new(Struct)
|
LL | Box::new(Struct)
|
||||||
| +++++++++ +
|
| +++++++++ +
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue