Skip to content

Commit 20c833c

Browse files
committed
diagnostics: Box<dyn Trait> suggestion with multiple matching impl
The two altered expectation messages both seem like improvements: - `coerce-expect-unsized-ascribed.stderr` says you can go `Box<char> -> Box<dyn Debug>`, which you can. - `upcast_soundness_bug.stderr` used to say that you could go `Box<dyn Trait<u8, u8>> -> Box<dyn Trait>`, which you can't, because the type parameters are missing in the destination and the only ones that work aren't what's needed.
1 parent 1b587a6 commit 20c833c

File tree

3 files changed

+13
-16
lines changed

3 files changed

+13
-16
lines changed

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

+9-15
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,9 @@ impl<T> Trait<T> for X {
313313
(ty::Dynamic(t, _, ty::DynKind::Dyn), _)
314314
if let Some(def_id) = t.principal_def_id() =>
315315
{
316-
let mut impl_def_ids = vec![];
317-
tcx.for_each_relevant_impl(def_id, values.found, |did| {
318-
impl_def_ids.push(did)
319-
});
320-
if let [_] = &impl_def_ids[..] {
316+
let has_non_blanket_impl =
317+
tcx.non_blanket_impls_for_ty(def_id, values.found).next().is_some();
318+
if has_non_blanket_impl {
321319
let trait_name = tcx.item_name(def_id);
322320
diag.help(format!(
323321
"`{}` implements `{trait_name}` so you could box the found value \
@@ -330,11 +328,9 @@ impl<T> Trait<T> for X {
330328
(_, ty::Dynamic(t, _, ty::DynKind::Dyn))
331329
if let Some(def_id) = t.principal_def_id() =>
332330
{
333-
let mut impl_def_ids = vec![];
334-
tcx.for_each_relevant_impl(def_id, values.expected, |did| {
335-
impl_def_ids.push(did)
336-
});
337-
if let [_] = &impl_def_ids[..] {
331+
let has_non_blanket_impl =
332+
tcx.non_blanket_impls_for_ty(def_id, values.expected).next().is_some();
333+
if has_non_blanket_impl {
338334
let trait_name = tcx.item_name(def_id);
339335
diag.help(format!(
340336
"`{}` implements `{trait_name}` so you could change the expected \
@@ -346,11 +342,9 @@ impl<T> Trait<T> for X {
346342
(ty::Dynamic(t, _, ty::DynKind::DynStar), _)
347343
if let Some(def_id) = t.principal_def_id() =>
348344
{
349-
let mut impl_def_ids = vec![];
350-
tcx.for_each_relevant_impl(def_id, values.found, |did| {
351-
impl_def_ids.push(did)
352-
});
353-
if let [_] = &impl_def_ids[..] {
345+
let has_non_blanket_impl =
346+
tcx.non_blanket_impls_for_ty(def_id, values.found).next().is_some();
347+
if has_non_blanket_impl {
354348
let trait_name = tcx.item_name(def_id);
355349
diag.help(format!(
356350
"`{}` implements `{trait_name}`, `#[feature(dyn_star)]` is likely \

tests/ui/coercion/coerce-expect-unsized-ascribed.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ LL | let _ = type_ascribe!(Box::new( if true { false } else { true }), Box<d
4242
|
4343
= note: expected struct `Box<dyn Debug>`
4444
found struct `Box<bool>`
45+
= help: `bool` implements `Debug` so you could box the found value and coerce it to the trait object `Box<dyn Debug>`, you will have to change the expected type as well
4546

4647
error[E0308]: mismatched types
4748
--> $DIR/coerce-expect-unsized-ascribed.rs:16:27
@@ -51,6 +52,7 @@ LL | let _ = type_ascribe!(Box::new( match true { true => 'a', false => 'b'
5152
|
5253
= note: expected struct `Box<dyn Debug>`
5354
found struct `Box<char>`
55+
= help: `char` implements `Debug` so you could box the found value and coerce it to the trait object `Box<dyn Debug>`, you will have to change the expected type as well
5456

5557
error[E0308]: mismatched types
5658
--> $DIR/coerce-expect-unsized-ascribed.rs:18:27
@@ -96,6 +98,7 @@ LL | let _ = type_ascribe!(&if true { false } else { true }, &dyn Debug);
9698
|
9799
= note: expected reference `&dyn Debug`
98100
found reference `&bool`
101+
= help: `bool` implements `Debug` so you could box the found value and coerce it to the trait object `Box<dyn Debug>`, you will have to change the expected type as well
99102

100103
error[E0308]: mismatched types
101104
--> $DIR/coerce-expect-unsized-ascribed.rs:24:27
@@ -105,6 +108,7 @@ LL | let _ = type_ascribe!(&match true { true => 'a', false => 'b' }, &dyn D
105108
|
106109
= note: expected reference `&dyn Debug`
107110
found reference `&char`
111+
= help: `char` implements `Debug` so you could box the found value and coerce it to the trait object `Box<dyn Debug>`, you will have to change the expected type as well
108112

109113
error[E0308]: mismatched types
110114
--> $DIR/coerce-expect-unsized-ascribed.rs:26:27

tests/ui/traits/upcast_soundness_bug.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ LL | let p = p as *const dyn Trait<u8, u16>; // <- this is bad!
66
|
77
= note: expected trait object `dyn Trait<u8, u8>`
88
found trait object `dyn Trait<u8, u16>`
9-
= help: `dyn Trait<u8, u16>` 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
109

1110
error: aborting due to 1 previous error
1211

0 commit comments

Comments
 (0)