1
Fork 0

diagnostics: use DeepRejectCtxt for check

This makes more things match, particularly applicable blankets.
This commit is contained in:
Michael Howell 2024-08-13 09:33:12 -07:00
parent 3312f5d652
commit c6fb0f344e
3 changed files with 32 additions and 9 deletions

View file

@ -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<T> Trait<T> 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::ForLookup)
.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<T> Trait<T> 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::ForLookup)
.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<T> Trait<T> 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::ForLookup)
.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 \