- for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
- // Traits have pseudo-modules that can be used to search for the given ident.
- if let Some(module) = binding.module() {
- let mut ident = ident;
- if ident.span.glob_adjust(module.expansion, binding.span).is_none() {
- continue;
- }
- if self
- .resolve_ident_in_module_unadjusted(
- ModuleOrUniformRoot::Module(module),
- ident,
- ns,
- parent_scope,
- false,
- module.span,
- )
- .is_ok()
- {
- let import_ids = self.find_transitive_imports(&binding.kind, trait_name);
- let trait_def_id = module.def_id().unwrap();
- found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids });
- }
- } else if let Res::Def(DefKind::TraitAlias, _) = binding.res() {
- // For now, just treat all trait aliases as possible candidates, since we don't
- // know if the ident is somewhere in the transitive bounds.
- let import_ids = self.find_transitive_imports(&binding.kind, trait_name);
- let trait_def_id = binding.res().def_id();
- found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids });
- } else {
- bug!("candidate is not trait or trait alias?")
+ // List of traits in scope is pruned on best effort basis. We reject traits not having an
+ // associated item with the given name and namespace (if specified). This is a conservative
+ // optimization, proper hygienic type-based resolution of associated items is done in typeck.
+ // We don't reject trait aliases (`trait_module == None`) because we don't have access to their
+ // associated items.
+ fn trait_may_have_item(
+ &mut self,
+ trait_module: Option<Module<'a>>,
+ assoc_item: Option<(Symbol, Namespace)>,
+ ) -> bool {
+ match (trait_module, assoc_item) {
+ (Some(trait_module), Some((name, ns))) => {
+ self.resolutions(trait_module).borrow().iter().any(|resolution| {
+ let (&BindingKey { ident: assoc_ident, ns: assoc_ns, .. }, _) = resolution;
+ assoc_ns == ns && assoc_ident.name == name
+ })