diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 0c140f93d94b2..8bbc1466fdebc 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -4,6 +4,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; +use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::print::{FmtPrinter, Printer}; use rustc_middle::ty::{self, suggest_constraining_type_param, Ty}; use rustc_span::def_id::DefId; @@ -313,9 +314,15 @@ impl Trait for X { (ty::Dynamic(t, _, ty::DynKind::Dyn), _) if let Some(def_id) = t.principal_def_id() => { - let has_non_blanket_impl = - tcx.non_blanket_impls_for_ty(def_id, values.found).next().is_some(); - if has_non_blanket_impl { + let mut has_matching_impl = false; + tcx.for_each_relevant_impl(def_id, values.found, |did| { + if DeepRejectCtxt::new(tcx, TreatParams::AsCandidateKey) + .types_may_unify(values.found, tcx.type_of(did).skip_binder()) + { + has_matching_impl = true; + } + }); + if has_matching_impl { let trait_name = tcx.item_name(def_id); diag.help(format!( "`{}` implements `{trait_name}` so you could box the found value \ @@ -328,9 +335,15 @@ impl Trait for X { (_, ty::Dynamic(t, _, ty::DynKind::Dyn)) if let Some(def_id) = t.principal_def_id() => { - let has_non_blanket_impl = - tcx.non_blanket_impls_for_ty(def_id, values.expected).next().is_some(); - if has_non_blanket_impl { + let mut has_matching_impl = false; + tcx.for_each_relevant_impl(def_id, values.expected, |did| { + if DeepRejectCtxt::new(tcx, TreatParams::AsCandidateKey) + .types_may_unify(values.expected, tcx.type_of(did).skip_binder()) + { + has_matching_impl = true; + } + }); + if has_matching_impl { let trait_name = tcx.item_name(def_id); diag.help(format!( "`{}` implements `{trait_name}` so you could change the expected \ @@ -342,9 +355,15 @@ impl Trait for X { (ty::Dynamic(t, _, ty::DynKind::DynStar), _) if let Some(def_id) = t.principal_def_id() => { - let has_non_blanket_impl = - tcx.non_blanket_impls_for_ty(def_id, values.found).next().is_some(); - if has_non_blanket_impl { + let mut has_matching_impl = false; + tcx.for_each_relevant_impl(def_id, values.found, |did| { + if DeepRejectCtxt::new(tcx, TreatParams::AsCandidateKey) + .types_may_unify(values.found, tcx.type_of(did).skip_binder()) + { + has_matching_impl = true; + } + }); + if has_matching_impl { let trait_name = tcx.item_name(def_id); diag.help(format!( "`{}` implements `{trait_name}`, `#[feature(dyn_star)]` is likely \ diff --git a/tests/ui/cast/ptr-to-trait-obj-different-args.stderr b/tests/ui/cast/ptr-to-trait-obj-different-args.stderr index b04289ae74748..8e60ca42f0a52 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-args.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-args.stderr @@ -14,6 +14,7 @@ LL | let y: *const dyn Trait = x as _; | = note: expected trait object `dyn Trait` found trait object `dyn Trait` + = help: `dyn Trait` implements `Trait` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well error[E0308]: mismatched types --> $DIR/ptr-to-trait-obj-different-args.rs:27:34 @@ -25,6 +26,7 @@ LL | let _: *const dyn Trait = x as _; | = note: expected trait object `dyn Trait` found trait object `dyn Trait` + = help: `dyn Trait` implements `Trait` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well error[E0308]: mismatched types --> $DIR/ptr-to-trait-obj-different-args.rs:28:34 @@ -37,6 +39,7 @@ LL | let _: *const dyn Trait = t as _; | = note: expected trait object `dyn Trait` found trait object `dyn Trait` + = help: `dyn Trait` implements `Trait` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well error[E0308]: mismatched types --> $DIR/ptr-to-trait-obj-different-args.rs:36:5 diff --git a/tests/ui/traits/upcast_soundness_bug.stderr b/tests/ui/traits/upcast_soundness_bug.stderr index 31f77b52b5fbf..5864abcdb41f5 100644 --- a/tests/ui/traits/upcast_soundness_bug.stderr +++ b/tests/ui/traits/upcast_soundness_bug.stderr @@ -6,6 +6,7 @@ LL | let p = p as *const dyn Trait; // <- this is bad! | = note: expected trait object `dyn Trait` found trait object `dyn Trait` + = help: `dyn Trait` implements `Trait` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well error: aborting due to 1 previous error