Rollup merge of #120315 - estebank:issue-102629-2, r=wesleywiser
On E0308 involving `dyn Trait`, mention trait objects When encountering a type mismatch error involving `dyn Trait`, mention the existence of boxed trait objects if the other type involved implements `Trait`. Fix #102629.
This commit is contained in:
commit
0cbef470d5
@ -294,6 +294,75 @@ fn foo(&self, x: T) -> T { 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() =>
|
||||||
|
{
|
||||||
|
let mut impl_def_ids = vec![];
|
||||||
|
tcx.for_each_relevant_impl(def_id, values.found, |did| {
|
||||||
|
impl_def_ids.push(did)
|
||||||
|
});
|
||||||
|
if let [_] = &impl_def_ids[..] {
|
||||||
|
let trait_name = tcx.item_name(def_id);
|
||||||
|
diag.help(format!(
|
||||||
|
"`{}` implements `{trait_name}` so you could box the found value \
|
||||||
|
and coerce it to the trait object `Box<dyn {trait_name}>`, you \
|
||||||
|
will have to change the expected type as well",
|
||||||
|
values.found,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(_, ty::Dynamic(t, _, ty::DynKind::Dyn))
|
||||||
|
if let Some(def_id) = t.principal_def_id() =>
|
||||||
|
{
|
||||||
|
let mut impl_def_ids = vec![];
|
||||||
|
tcx.for_each_relevant_impl(def_id, values.expected, |did| {
|
||||||
|
impl_def_ids.push(did)
|
||||||
|
});
|
||||||
|
if let [_] = &impl_def_ids[..] {
|
||||||
|
let trait_name = tcx.item_name(def_id);
|
||||||
|
diag.help(format!(
|
||||||
|
"`{}` implements `{trait_name}` so you could change the expected \
|
||||||
|
type to `Box<dyn {trait_name}>`",
|
||||||
|
values.expected,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(ty::Dynamic(t, _, ty::DynKind::DynStar), _)
|
||||||
|
if let Some(def_id) = t.principal_def_id() =>
|
||||||
|
{
|
||||||
|
let mut impl_def_ids = vec![];
|
||||||
|
tcx.for_each_relevant_impl(def_id, values.found, |did| {
|
||||||
|
impl_def_ids.push(did)
|
||||||
|
});
|
||||||
|
if let [_] = &impl_def_ids[..] {
|
||||||
|
let trait_name = tcx.item_name(def_id);
|
||||||
|
diag.help(format!(
|
||||||
|
"`{}` implements `{trait_name}`, `#[feature(dyn_star)]` is likely \
|
||||||
|
not enabled; that feature it is currently incomplete",
|
||||||
|
values.found,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
(_, ty::Alias(ty::Opaque, opaque_ty))
|
(_, ty::Alias(ty::Opaque, opaque_ty))
|
||||||
| (ty::Alias(ty::Opaque, opaque_ty), _) => {
|
| (ty::Alias(ty::Opaque, opaque_ty), _) => {
|
||||||
if opaque_ty.def_id.is_local()
|
if opaque_ty.def_id.is_local()
|
||||||
|
@ -8,6 +8,7 @@ LL | f5.2 = Bar1 {f: 36};
|
|||||||
|
|
|
|
||||||
= note: expected trait object `dyn ToBar`
|
= note: expected trait object `dyn ToBar`
|
||||||
found struct `Bar1`
|
found struct `Bar1`
|
||||||
|
= help: `Bar1` implements `ToBar` so you could box the found value and coerce it to the trait object `Box<dyn ToBar>`, you will have to change the expected type as well
|
||||||
|
|
||||||
error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time
|
error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time
|
||||||
--> $DIR/dst-bad-assign-3.rs:33:5
|
--> $DIR/dst-bad-assign-3.rs:33:5
|
||||||
|
@ -8,6 +8,7 @@ LL | f5.ptr = Bar1 {f: 36};
|
|||||||
|
|
|
|
||||||
= note: expected trait object `dyn ToBar`
|
= note: expected trait object `dyn ToBar`
|
||||||
found struct `Bar1`
|
found struct `Bar1`
|
||||||
|
= help: `Bar1` implements `ToBar` so you could box the found value and coerce it to the trait object `Box<dyn ToBar>`, you will have to change the expected type as well
|
||||||
|
|
||||||
error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time
|
error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time
|
||||||
--> $DIR/dst-bad-assign.rs:35:5
|
--> $DIR/dst-bad-assign.rs:35:5
|
||||||
|
@ -8,6 +8,7 @@ LL | dyn_star_foreign::require_dyn_star_display(1usize);
|
|||||||
|
|
|
|
||||||
= note: expected trait object `(dyn* std::fmt::Display + 'static)`
|
= note: expected trait object `(dyn* std::fmt::Display + 'static)`
|
||||||
found type `usize`
|
found type `usize`
|
||||||
|
= help: `usize` implements `Display`, `#[feature(dyn_star)]` is likely not enabled; that feature it is currently incomplete
|
||||||
note: function defined here
|
note: function defined here
|
||||||
--> $DIR/auxiliary/dyn-star-foreign.rs:6:8
|
--> $DIR/auxiliary/dyn-star-foreign.rs:6:8
|
||||||
|
|
|
|
||||||
|
@ -27,6 +27,7 @@ LL | type VRefCont<'a> = &'a V where Self: 'a;
|
|||||||
| ^^^^^
|
| ^^^^^
|
||||||
= note: expected trait object `(dyn RefCont<'_, u8> + 'static)`
|
= note: expected trait object `(dyn RefCont<'_, u8> + 'static)`
|
||||||
found reference `&u8`
|
found reference `&u8`
|
||||||
|
= help: `&u8` implements `RefCont` so you could box the found value and coerce it to the trait object `Box<dyn RefCont>`, you will have to change the expected type as well
|
||||||
= note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
|
= note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
18
tests/ui/impl-trait/dyn-impl-type-mismatch.rs
Normal file
18
tests/ui/impl-trait/dyn-impl-type-mismatch.rs
Normal file
@ -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
tests/ui/impl-trait/dyn-impl-type-mismatch.stderr
Normal file
43
tests/ui/impl-trait/dyn-impl-type-mismatch.stderr
Normal file
@ -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`.
|
@ -6,6 +6,7 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) }
|
|||||||
|
|
|
|
||||||
= note: expected trait object `(dyn Trait + 'static)`
|
= note: expected trait object `(dyn Trait + 'static)`
|
||||||
found struct `Struct`
|
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[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
|
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
|
||||||
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13
|
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13
|
||||||
@ -27,6 +28,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
|
|||||||
|
|
|
|
||||||
= note: expected trait object `(dyn Trait + 'static)`
|
= note: expected trait object `(dyn Trait + 'static)`
|
||||||
found struct `Struct`
|
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[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
|
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
|
||||||
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13
|
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13
|
||||||
|
@ -27,6 +27,7 @@ LL | 1.query::<dyn ToString>("")
|
|||||||
|
|
|
|
||||||
= note: expected trait object `dyn ToString`
|
= note: expected trait object `dyn ToString`
|
||||||
found reference `&'static str`
|
found reference `&'static str`
|
||||||
|
= help: `&'static str` implements `ToString` so you could box the found value and coerce it to the trait object `Box<dyn ToString>`, you will have to change the expected type as well
|
||||||
note: method defined here
|
note: method defined here
|
||||||
--> $DIR/issue-61525.rs:2:8
|
--> $DIR/issue-61525.rs:2:8
|
||||||
|
|
|
|
||||||
|
Loading…
Reference in New Issue
Block a user