Add note for param-env shadowing

This commit is contained in:
xonx4l 2025-12-27 14:41:19 +05:30 committed by xonx
parent d00ba92259
commit 5b1070b040
3 changed files with 98 additions and 2 deletions

View file

@ -149,11 +149,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
actual: Ty<'tcx>,
err: TypeError<'tcx>,
) -> Diag<'a> {
self.report_and_explain_type_error(
let mut diag = self.report_and_explain_type_error(
TypeTrace::types(cause, expected, actual),
param_env,
err,
)
);
self.suggest_param_env_shadowing(&mut diag, expected, actual);
diag
}
pub fn report_mismatched_consts(
@ -240,6 +244,63 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
false
}
fn suggest_param_env_shadowing(
&self,
diag: &mut Diag<'_>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
) {
let (alias, concrete) = match (expected.kind(), found.kind()) {
(ty::Alias(ty::Projection, proj), _) => (proj, found),
(_, ty::Alias(ty::Projection, proj)) => (proj, expected),
_ => return,
};
let tcx = self.tcx;
let trait_def_id = alias.trait_def_id(tcx);
let impls = tcx.trait_impls_of(trait_def_id);
let all_impls =
impls.blanket_impls().iter().chain(impls.non_blanket_impls().values().flatten());
for &impl_def_id in all_impls {
let is_shadowed = self.infcx.probe(|_| {
let impl_substs = self.infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_substs);
let expected_trait_ref = alias.trait_ref(tcx);
if self.infcx.can_eq(ty::ParamEnv::empty(), expected_trait_ref, impl_trait_ref) {
let name = tcx.item_name(alias.def_id);
let assoc_item = tcx
.associated_items(impl_def_id)
.filter_by_name_unhygienic(name)
.find(|item| matches!(item.kind, ty::AssocKind::Type { .. }));
if let Some(item) = assoc_item {
let impl_assoc_ty = tcx.type_of(item.def_id).instantiate(tcx, impl_substs);
if self.infcx.can_eq(ty::ParamEnv::empty(), impl_assoc_ty, concrete) {
return true;
}
}
}
false
});
if is_shadowed {
diag.note(format!(
"the associated type `{}` is defined as `{}` in the implementation, \
but the generic bound `{}` hides this definition",
self.ty_to_string(tcx.mk_ty_from_kind(ty::Alias(ty::Projection, *alias))),
self.ty_to_string(concrete),
self.ty_to_string(alias.self_ty())
));
return;
}
}
}
fn note_error_origin(
&self,
err: &mut Diag<'_>,