Skip to content

Commit

Permalink
Account for expected dyn Trait found impl Trait
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Jan 24, 2024
1 parent d992d9c commit 796814d
Showing 3 changed files with 81 additions and 0 deletions.
20 changes: 20 additions & 0 deletions compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
Original file line number Diff line number Diff line change
@@ -294,6 +294,26 @@ impl<T> Trait<T> 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() =>
{
18 changes: 18 additions & 0 deletions tests/ui/impl-trait/dyn-impl-type-mismatch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
trait Trait {}
struct Struct;
impl Trait for Struct {}
fn foo() -> impl Trait {
Struct
}
fn main() {
let a: Box<dyn Trait> = if true {
Box::new(Struct)
} else {
foo() //~ ERROR E0308
};
let a: dyn Trait = if true {
Struct //~ ERROR E0308
} else {
foo() //~ ERROR E0308
};
}
43 changes: 43 additions & 0 deletions tests/ui/impl-trait/dyn-impl-type-mismatch.stderr
Original file line number Diff line number Diff line change
@@ -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<dyn Trait>`, found opaque type
|
= note: expected struct `Box<dyn Trait>`
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<dyn Trait>`, 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<dyn Trait>`, 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`.

0 comments on commit 796814d

Please sign in to comment.