Repository: rust-lang/rust
File: compiler/rustc_resolve/src/late/diagnostics.rs (Rust)

Code before:
                    continue;
                };

                // Only suggest for bounds that are explicitly on an in-scope type parameter.
                let Some(partial_res) = this.r.partial_res_map.get(&where_bound.bounded_ty.id)
                else {
                    continue;
                };
                if !matches!(partial_res.full_res(), Some(Res::Def(DefKind::TyParam, _))) {
                    continue;
                }

                for bound in &where_bound.bounds {
                    let ast::GenericBound::Trait(poly_trait_ref) = bound else { continue };
                    record_bound(this, ident.name, poly_trait_ref);
                }
            }
        };

        if let Some(item) = self.diag_metadata.current_item
            && let Some(generics) = item.kind.generics()
        {
            record_from_generics(self, generics);
        }

        if let Some(assoc) = self.diag_metadata.current_impl_item {
            let generics = match &assoc.kind {
                AssocItemKind::Const(box ast::ConstItem { generics, .. })
                | AssocItemKind::Fn(box ast::Fn { generics, .. })
                | AssocItemKind::Type(box ast::TyAlias { generics, .. }) => Some(generics),
                AssocItemKind::Delegation(..)
                | AssocItemKind::MacCall(..)
                | AssocItemKind::DelegationMac(..) => None,
            };
            if let Some(generics) = generics {
                record_from_generics(self, generics);
            }
        }

        let mut suggestions: FxIndexSet<String> = FxIndexSet::default();
        for (ty_param, traits) in matching_bounds {
            let ty_param = ty_param.to_ident_string();
            let trait_paths_len: usize = traits.values().map(|(_, paths)| paths.len()).sum();
            if traits.len() == 1 && trait_paths_len == 1 {
                let assoc_type_def_id = traits.values().next().unwrap().0;
                let assoc_segment = format!(
                    "{}{}",
                    assoc_name,
                    self.assoc_type_required_generic_args_suggestion(assoc_type_def_id)
                );
                suggestions.insert(format!("{ty_param}::{assoc_segment}"));

Review comment (bug):
Could we add a test case for an impl declared within an fn, and vice-versa? I'm intrigued if this would cause `record_from_generics` to then provide suggestions that would incorrectly mention outer type params. This would only happen if `diag_metadata` isn't being properly updated elsewhere, so this logic might still be right.

Code after:
                let Some(partial_res) = this.r.partial_res_map.get(&where_bound.bounded_ty.id)
                else {
                    continue;
                };
                if !matches!(partial_res.full_res(), Some(Res::Def(DefKind::TyParam, _))) {
                    continue;
                }

                for bound in &where_bound.bounds {
                    let ast::GenericBound::Trait(poly_trait_ref) = bound else { continue };
                    record_bound(this, ident.name, poly_trait_ref);
                }
            }
        };

        if let Some(item) = self.diag_metadata.current_item
            && let Some(generics) = item.kind.generics()
        {
            record_from_generics(self, generics);
        }

        if let Some(item) = self.diag_metadata.current_item
            && matches!(item.kind, ItemKind::Impl(..))
            && let Some(assoc) = self.diag_metadata.current_impl_item
        {
            let generics = match &assoc.kind {
                AssocItemKind::Const(box ast::ConstItem { generics, .. })
                | AssocItemKind::Fn(box ast::Fn { generics, .. })
                | AssocItemKind::Type(box ast::TyAlias { generics, .. }) => Some(generics),
                AssocItemKind::Delegation(..)
                | AssocItemKind::MacCall(..)
                | AssocItemKind::DelegationMac(..) => None,
            };
            if let Some(generics) = generics {
                record_from_generics(self, generics);
            }
        }

        let mut suggestions: FxIndexSet<String> = FxIndexSet::default();
        for (ty_param, traits) in matching_bounds {
            let ty_param = ty_param.to_ident_string();
            let trait_paths_len: usize = traits.values().map(|(_, paths)| paths.len()).sum();
            if traits.len() == 1 && trait_paths_len == 1 {
                let assoc_type_def_id = traits.values().next().unwrap().0;
                let assoc_segment = format!(
                    "{}{}",
                    assoc_name,
                    self.r.item_required_generic_args_suggestion(assoc_type_def_id)
                );
                suggestions.insert(format!("{ty_param}::{assoc_segment}"));
            } else {