Repository: rust-lang/rust
File: compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs (Rust)

Code before:

        let tcx = self.tcx;

        let trait_ref = alias.trait_ref(tcx);
        let obligation =
            Obligation::new(tcx, ObligationCause::dummy(), param_env, ty::Binder::dummy(trait_ref));

        let applicable_impls = compute_applicable_impls_for_diagnostics(self.infcx, &obligation);

        for candidate in applicable_impls {
            let impl_def_id = match candidate {
                CandidateSource::DefId(did) => did,
                CandidateSource::ParamEnv(_) => continue,
            };

            let is_shadowed = self.infcx.probe(|_| {
                let impl_substs = self.infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);

                let leaf_def = match specialization_graph::assoc_def(tcx, impl_def_id, alias.def_id)
                {
                    Ok(leaf) => leaf,
                    Err(_) => return false,
                };

                let impl_item_def_id = leaf_def.item.def_id;
                let impl_assoc_ty = tcx.type_of(impl_item_def_id).instantiate(tcx, impl_substs);

                self.infcx.can_eq(param_env, impl_assoc_ty, concrete)
            });

            if is_shadowed {
                diag.note(format!(
                    "the associated type `{}` is defined as `{}` in the implementation, \
                    but the where-bound `{}` shadows this definition\n\
                    see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information",
                    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<'_>,
        cause: &ObligationCause<'tcx>,
        exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
        terr: TypeError<'tcx>,
        param_env: Option<ParamEnv<'tcx>>,

Review comment (bug):
this currently incorrectly emits the note for the following I think
```rust
trait Trait {
    type Assoc;
}

impl<T> Trait for T {
    type Assoc = T;
}

fn foo<T: Trait>(x: T::Assoc) -> u32 { x }
```
This also doesn't handle GATs and the following probably ICEs
```rust
trait Trait {
    type Assoc<T>;
}

impl<T> Trait for T {
    type Assoc<U> = U;
}

fn foo<T: Trait>(x: T::Assoc<T>) -> u32 { x }
```


Code after:
        };

        let tcx = self.tcx;

        let trait_ref = alias.trait_ref(tcx);
        let obligation =
            Obligation::new(tcx, ObligationCause::dummy(), param_env, ty::Binder::dummy(trait_ref));

        let applicable_impls = compute_applicable_impls_for_diagnostics(self.infcx, &obligation);

        for candidate in applicable_impls {
            let impl_def_id = match candidate {
                CandidateSource::DefId(did) => did,
                CandidateSource::ParamEnv(_) => continue,
            };

            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 let Err(_) = self.infcx.at(&ObligationCause::dummy(), param_env).eq(
                    DefineOpaqueTypes::No,
                    expected_trait_ref,
                    impl_trait_ref,
                ) {
                    return false;
                }

                let leaf_def = match specialization_graph::assoc_def(tcx, impl_def_id, alias.def_id)
                {
                    Ok(leaf) => leaf,
                    Err(_) => return false,
                };

                let trait_def_id = alias.trait_def_id(tcx);
                let rebased_args = alias.args.rebase_onto(tcx, trait_def_id, impl_substs);

                let impl_item_def_id = leaf_def.item.def_id;
                let impl_assoc_ty = tcx.type_of(impl_item_def_id).instantiate(tcx, rebased_args);

                self.infcx.can_eq(param_env, impl_assoc_ty, concrete)
            });

            if is_shadowed {
                diag.note(format!(
                    "the associated type `{}` is defined as `{}` in the implementation, \
                    but the where-bound `{}` shadows this definition\n\
                    see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information",
                    self.ty_to_string(tcx.mk_ty_from_kind(ty::Alias(ty::Projection, *alias))),