about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-01-25 08:39:44 +0100
committerGitHub <noreply@github.com>2024-01-25 08:39:44 +0100
commit0cbef470d5e0cd8590236b7a9cbf1b0c3c7fc954 (patch)
treef22cfe9aa5dd3879f8e122c7714298c19638285d /compiler
parent72b70ec4746b6e1eb3ee8eabd84f31c61ad17ccf (diff)
parent796814d91627203444769a680c53ff59a7ff4696 (diff)
downloadrust-0cbef470d5e0cd8590236b7a9cbf1b0c3c7fc954.tar.gz
rust-0cbef470d5e0cd8590236b7a9cbf1b0c3c7fc954.zip
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.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs69
1 files changed, 69 insertions, 0 deletions
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 01cd3c57925..21ea48c6c83 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,75 @@ 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() =>
+                    {
+                        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), _) => {
                         if opaque_ty.def_id.is_local()