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

Code before:

            if trait_generics.count() != other_trait_generics.count() {
                return false;
            }
            trait_generics.own_params.iter().zip(other_trait_generics.own_params.iter()).all(
                |(a, b)| match (&a.kind, &b.kind) {
                    (ty::GenericParamDefKind::Lifetime, ty::GenericParamDefKind::Lifetime)
                    | (
                        ty::GenericParamDefKind::Type { .. },
                        ty::GenericParamDefKind::Type { .. },
                    )
                    | (
                        ty::GenericParamDefKind::Const { .. },
                        ty::GenericParamDefKind::Const { .. },
                    ) => true,
                    _ => false,
                },
            )
        };
        let trait_name = self.tcx.item_name(trait_def_id);
        if let Some(other_trait_def_id) = self.tcx.all_traits_including_private().find(|def_id| {
            trait_def_id != *def_id
                && trait_name == self.tcx.item_name(def_id)
                && trait_has_same_params(*def_id)
                // Skip `PointeeSized` here to avoid creating `PointeeSized` solver obligations during error reporting.
                && !self.tcx.is_lang_item(*def_id, LangItem::PointeeSized)
                && self.predicate_must_hold_modulo_regions(&Obligation::new(
                    self.tcx,
                    obligation.cause.clone(),
                    obligation.param_env,
                    trait_pred.map_bound(|tr| ty::TraitPredicate {
                        trait_ref: ty::TraitRef::new(self.tcx, *def_id, tr.trait_ref.args),
                        ..tr
                    }),
                ))
        }) {
            err.note(format!(
                "`{}` implements similarly named trait `{}`, but not `{}`",
                trait_pred.self_ty(),
                self.tcx.def_path_str(other_trait_def_id),
                trait_pred.print_modifiers_and_trait_path()
            ));
            suggested = true;
        }
        suggested
    }

    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
    /// with the same path as `trait_ref`, a help message about a multiple different
    /// versions of the same crate is added to `err`. Otherwise if it implements another
    /// trait with the same name, a note message about a similarly named trait is added to `err`.

Review comment (suggestion):
actually, doesn't really matter, but looking at #153100, it would be more correct to consider `PointeeSized` to always hold, instead of ignoring it. Don't think that's useful information for users, but 🤷 

Code after:
                    return None;
                }
                // Filter out e.g. constructors that often have the same path
                // str as the relevant ADT.
                if !self.tcx.def_kind(item).is_adt() {
                    return None;
                }
                let path = self.comparable_path(item);
                // We don't know if our item or the one we found is the re-exported one.
                // Check both cases.
                let is_similar = path.ends_with(&impl_self_path) || impl_self_path.ends_with(&path);
                is_similar.then_some((item, path))
            })
            .collect();

        let mut similar_items =
            similar_items.into_items().into_sorted_stable_ord_by_key(|(_, path)| path);
        similar_items.dedup();

        for (similar_item, _) in similar_items {
            err.span_help(self.tcx.def_span(similar_item), "item with same name found");
            self.note_two_crate_versions(similar_item.krate, MultiSpan::new(), err);
        }
    }

    fn check_same_name_different_path(
        &self,
        err: &mut Diag<'_>,
        obligation: &PredicateObligation<'tcx>,
        trait_pred: ty::PolyTraitPredicate<'tcx>,
    ) -> bool {
        let mut suggested = false;
        let trait_def_id = trait_pred.def_id();
        let trait_has_same_params = |other_trait_def_id: DefId| -> bool {
            let trait_generics = self.tcx.generics_of(trait_def_id);
            let other_trait_generics = self.tcx.generics_of(other_trait_def_id);

            if trait_generics.count() != other_trait_generics.count() {
                return false;
            }
            trait_generics.own_params.iter().zip(other_trait_generics.own_params.iter()).all(
                |(a, b)| match (&a.kind, &b.kind) {
                    (ty::GenericParamDefKind::Lifetime, ty::GenericParamDefKind::Lifetime)
                    | (
                        ty::GenericParamDefKind::Type { .. },
                        ty::GenericParamDefKind::Type { .. },
                    )
                    | (
                        ty::GenericParamDefKind::Const { .. },
                        ty::GenericParamDefKind::Const { .. },
                    ) => true,