Skip to content

Commit 0cbef47

Browse files
authored
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.
2 parents 72b70ec + 796814d commit 0cbef47

File tree

9 files changed

+137
-0
lines changed

9 files changed

+137
-0
lines changed

compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs

+69
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,75 @@ impl<T> Trait<T> for X {
294294
);
295295
}
296296
}
297+
(ty::Dynamic(t, _, ty::DynKind::Dyn), ty::Alias(ty::Opaque, alias))
298+
if let Some(def_id) = t.principal_def_id()
299+
&& tcx.explicit_item_bounds(alias.def_id).skip_binder().iter().any(
300+
|(pred, _span)| match pred.kind().skip_binder() {
301+
ty::ClauseKind::Trait(trait_predicate)
302+
if trait_predicate.polarity
303+
== ty::ImplPolarity::Positive =>
304+
{
305+
trait_predicate.def_id() == def_id
306+
}
307+
_ => false,
308+
},
309+
) =>
310+
{
311+
diag.help(format!(
312+
"you can box the `{}` to coerce it to `Box<{}>`, but you'll have to \
313+
change the expected type as well",
314+
values.found, values.expected,
315+
));
316+
}
317+
(ty::Dynamic(t, _, ty::DynKind::Dyn), _)
318+
if let Some(def_id) = t.principal_def_id() =>
319+
{
320+
let mut impl_def_ids = vec![];
321+
tcx.for_each_relevant_impl(def_id, values.found, |did| {
322+
impl_def_ids.push(did)
323+
});
324+
if let [_] = &impl_def_ids[..] {
325+
let trait_name = tcx.item_name(def_id);
326+
diag.help(format!(
327+
"`{}` implements `{trait_name}` so you could box the found value \
328+
and coerce it to the trait object `Box<dyn {trait_name}>`, you \
329+
will have to change the expected type as well",
330+
values.found,
331+
));
332+
}
333+
}
334+
(_, ty::Dynamic(t, _, ty::DynKind::Dyn))
335+
if let Some(def_id) = t.principal_def_id() =>
336+
{
337+
let mut impl_def_ids = vec![];
338+
tcx.for_each_relevant_impl(def_id, values.expected, |did| {
339+
impl_def_ids.push(did)
340+
});
341+
if let [_] = &impl_def_ids[..] {
342+
let trait_name = tcx.item_name(def_id);
343+
diag.help(format!(
344+
"`{}` implements `{trait_name}` so you could change the expected \
345+
type to `Box<dyn {trait_name}>`",
346+
values.expected,
347+
));
348+
}
349+
}
350+
(ty::Dynamic(t, _, ty::DynKind::DynStar), _)
351+
if let Some(def_id) = t.principal_def_id() =>
352+
{
353+
let mut impl_def_ids = vec![];
354+
tcx.for_each_relevant_impl(def_id, values.found, |did| {
355+
impl_def_ids.push(did)
356+
});
357+
if let [_] = &impl_def_ids[..] {
358+
let trait_name = tcx.item_name(def_id);
359+
diag.help(format!(
360+
"`{}` implements `{trait_name}`, `#[feature(dyn_star)]` is likely \
361+
not enabled; that feature it is currently incomplete",
362+
values.found,
363+
));
364+
}
365+
}
297366
(_, ty::Alias(ty::Opaque, opaque_ty))
298367
| (ty::Alias(ty::Opaque, opaque_ty), _) => {
299368
if opaque_ty.def_id.is_local()

tests/ui/dst/dst-bad-assign-3.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ LL | f5.2 = Bar1 {f: 36};
88
|
99
= note: expected trait object `dyn ToBar`
1010
found struct `Bar1`
11+
= 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
1112

1213
error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time
1314
--> $DIR/dst-bad-assign-3.rs:33:5

tests/ui/dst/dst-bad-assign.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ LL | f5.ptr = Bar1 {f: 36};
88
|
99
= note: expected trait object `dyn ToBar`
1010
found struct `Bar1`
11+
= 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
1112

1213
error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time
1314
--> $DIR/dst-bad-assign.rs:35:5

tests/ui/dyn-star/no-implicit-dyn-star.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ LL | dyn_star_foreign::require_dyn_star_display(1usize);
88
|
99
= note: expected trait object `(dyn* std::fmt::Display + 'static)`
1010
found type `usize`
11+
= help: `usize` implements `Display`, `#[feature(dyn_star)]` is likely not enabled; that feature it is currently incomplete
1112
note: function defined here
1213
--> $DIR/auxiliary/dyn-star-foreign.rs:6:8
1314
|

tests/ui/generic-associated-types/issue-79422.extended.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ LL | type VRefCont<'a> = &'a V where Self: 'a;
2727
| ^^^^^
2828
= note: expected trait object `(dyn RefCont<'_, u8> + 'static)`
2929
found reference `&u8`
30+
= 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
3031
= note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
3132

3233
error: aborting due to 2 previous errors
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
trait Trait {}
2+
struct Struct;
3+
impl Trait for Struct {}
4+
fn foo() -> impl Trait {
5+
Struct
6+
}
7+
fn main() {
8+
let a: Box<dyn Trait> = if true {
9+
Box::new(Struct)
10+
} else {
11+
foo() //~ ERROR E0308
12+
};
13+
let a: dyn Trait = if true {
14+
Struct //~ ERROR E0308
15+
} else {
16+
foo() //~ ERROR E0308
17+
};
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/dyn-impl-type-mismatch.rs:11:9
3+
|
4+
LL | fn foo() -> impl Trait {
5+
| ---------- the found opaque type
6+
...
7+
LL | foo()
8+
| ^^^^^ expected `Box<dyn Trait>`, found opaque type
9+
|
10+
= note: expected struct `Box<dyn Trait>`
11+
found opaque type `impl Trait`
12+
= 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
13+
help: store this in the heap by calling `Box::new`
14+
|
15+
LL | Box::new(foo())
16+
| +++++++++ +
17+
18+
error[E0308]: mismatched types
19+
--> $DIR/dyn-impl-type-mismatch.rs:14:9
20+
|
21+
LL | Struct
22+
| ^^^^^^ expected `dyn Trait`, found `Struct`
23+
|
24+
= note: expected trait object `dyn Trait`
25+
found struct `Struct`
26+
= 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
27+
28+
error[E0308]: mismatched types
29+
--> $DIR/dyn-impl-type-mismatch.rs:16:9
30+
|
31+
LL | fn foo() -> impl Trait {
32+
| ---------- the found opaque type
33+
...
34+
LL | foo()
35+
| ^^^^^ expected `dyn Trait`, found opaque type
36+
|
37+
= note: expected trait object `dyn Trait`
38+
found opaque type `impl Trait`
39+
= 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
40+
41+
error: aborting due to 3 previous errors
42+
43+
For more information about this error, try `rustc --explain E0308`.

tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) }
66
|
77
= note: expected trait object `(dyn Trait + 'static)`
88
found struct `Struct`
9+
= 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
910

1011
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
1112
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13
@@ -27,6 +28,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
2728
|
2829
= note: expected trait object `(dyn Trait + 'static)`
2930
found struct `Struct`
31+
= 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
3032

3133
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
3234
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13

tests/ui/methods/issues/issue-61525.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ LL | 1.query::<dyn ToString>("")
2727
|
2828
= note: expected trait object `dyn ToString`
2929
found reference `&'static str`
30+
= 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
3031
note: method defined here
3132
--> $DIR/issue-61525.rs:2:8
3233
|

0 commit comments

Comments
 (0)