diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 662903e30fc3..21ea48c6c83d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -294,6 +294,26 @@ impl Trait for X { ); } } + (ty::Dynamic(t, _, ty::DynKind::Dyn), ty::Alias(ty::Opaque, alias)) + if let Some(def_id) = t.principal_def_id() + && tcx.explicit_item_bounds(alias.def_id).skip_binder().iter().any( + |(pred, _span)| match pred.kind().skip_binder() { + ty::ClauseKind::Trait(trait_predicate) + if trait_predicate.polarity + == ty::ImplPolarity::Positive => + { + trait_predicate.def_id() == def_id + } + _ => false, + }, + ) => + { + diag.help(format!( + "you can box the `{}` to coerce it to `Box<{}>`, but you'll have to \ + change the expected type as well", + values.found, values.expected, + )); + } (ty::Dynamic(t, _, ty::DynKind::Dyn), _) if let Some(def_id) = t.principal_def_id() => { diff --git a/tests/ui/impl-trait/dyn-impl-type-mismatch.rs b/tests/ui/impl-trait/dyn-impl-type-mismatch.rs new file mode 100644 index 000000000000..c6170abb5828 --- /dev/null +++ b/tests/ui/impl-trait/dyn-impl-type-mismatch.rs @@ -0,0 +1,18 @@ +trait Trait {} +struct Struct; +impl Trait for Struct {} +fn foo() -> impl Trait { + Struct +} +fn main() { + let a: Box = if true { + Box::new(Struct) + } else { + foo() //~ ERROR E0308 + }; + let a: dyn Trait = if true { + Struct //~ ERROR E0308 + } else { + foo() //~ ERROR E0308 + }; +} diff --git a/tests/ui/impl-trait/dyn-impl-type-mismatch.stderr b/tests/ui/impl-trait/dyn-impl-type-mismatch.stderr new file mode 100644 index 000000000000..ddbdaf3eb4b0 --- /dev/null +++ b/tests/ui/impl-trait/dyn-impl-type-mismatch.stderr @@ -0,0 +1,43 @@ +error[E0308]: mismatched types + --> $DIR/dyn-impl-type-mismatch.rs:11:9 + | +LL | fn foo() -> impl Trait { + | ---------- the found opaque type +... +LL | foo() + | ^^^^^ expected `Box`, found opaque type + | + = note: expected struct `Box` + found opaque type `impl Trait` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(foo()) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-impl-type-mismatch.rs:14:9 + | +LL | Struct + | ^^^^^^ expected `dyn Trait`, found `Struct` + | + = note: expected trait object `dyn Trait` + found struct `Struct` + = help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well + +error[E0308]: mismatched types + --> $DIR/dyn-impl-type-mismatch.rs:16:9 + | +LL | fn foo() -> impl Trait { + | ---------- the found opaque type +... +LL | foo() + | ^^^^^ expected `dyn Trait`, found opaque type + | + = note: expected trait object `dyn Trait` + found opaque type `impl Trait` + = help: you can box the `impl Trait` to coerce it to `Box`, but you'll have to change the expected type as well + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`.