From 1cded8472ed034739ff31e314f5cf76ebe5d07c1 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sat, 18 Mar 2017 02:10:13 +0000 Subject: [PATCH] Remove `trait_item_map`, clean up `resolver.with_type_parameter_rib()`. --- src/librustc_resolve/build_reduced_graph.rs | 24 +++-- src/librustc_resolve/lib.rs | 106 +++++++++++--------- 2 files changed, 73 insertions(+), 57 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index b7b75f8af73..18798962df1 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -478,9 +478,10 @@ impl<'a> Resolver<'a> { self.define(module, ident, ns, (child.def, ty::Visibility::Public, DUMMY_SP, Mark::root())); - let has_self = self.session.cstore.associated_item_cloned(child.def.def_id()) - .method_has_self_argument; - self.trait_item_map.insert((def_id, child.name, ns), (child.def, has_self)); + if self.session.cstore.associated_item_cloned(child.def.def_id()) + .method_has_self_argument { + self.has_self.insert(child.def.def_id()); + } } module.populated.set(true); } @@ -773,7 +774,6 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { fn visit_trait_item(&mut self, item: &'a TraitItem) { let parent = self.resolver.current_module; - let def_id = parent.def_id().unwrap(); if let TraitItemKind::Macro(_) = item.node { self.visit_invoc(item.id); @@ -782,16 +782,18 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { // Add the item to the trait info. let item_def_id = self.resolver.definitions.local_def_id(item.id); - let (def, ns, has_self) = match item.node { - TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS, false), - TraitItemKind::Method(ref sig, _) => - (Def::Method(item_def_id), ValueNS, sig.decl.has_self()), - TraitItemKind::Type(..) => (Def::AssociatedTy(item_def_id), TypeNS, false), + let (def, ns) = match item.node { + TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS), + TraitItemKind::Method(ref sig, _) => { + if sig.decl.has_self() { + self.resolver.has_self.insert(item_def_id); + } + (Def::Method(item_def_id), ValueNS) + } + TraitItemKind::Type(..) => (Def::AssociatedTy(item_def_id), TypeNS), TraitItemKind::Macro(_) => bug!(), // handled above }; - self.resolver.trait_item_map.insert((def_id, item.ident.name, ns), (def, has_self)); - let vis = ty::Visibility::Public; self.resolver.define(parent, item.ident, ns, (def, vis, item.span, self.expansion)); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 500277e78e6..6d8ca09935c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1111,7 +1111,8 @@ pub struct Resolver<'a> { prelude: Option>, - trait_item_map: FxHashMap<(DefId, Name, Namespace), (Def, bool /* has self */)>, + // n.b. This is used only for better diagnostics, not name resolution itself. + has_self: FxHashSet, // Names of fields of an item `DefId` accessible with dot syntax. // Used for hints during error reporting. @@ -1134,7 +1135,7 @@ pub struct Resolver<'a> { label_ribs: Vec>, // The trait that the current context can refer to. - current_trait_ref: Option<(DefId, TraitRef)>, + current_trait_ref: Option<(Module<'a>, TraitRef)>, // The current self type if inside an impl (used for better errors). current_self_type: Option, @@ -1337,7 +1338,7 @@ impl<'a> Resolver<'a> { graph_root: graph_root, prelude: None, - trait_item_map: FxHashMap(), + has_self: FxHashSet(), field_names: FxHashMap(), determined_imports: Vec::new(), @@ -1750,22 +1751,21 @@ impl<'a> Resolver<'a> { let mut function_type_rib = Rib::new(rib_kind); let mut seen_bindings = FxHashMap(); for type_parameter in &generics.ty_params { - let name = type_parameter.ident.name; + let ident = type_parameter.ident.unhygienize(); debug!("with_type_parameter_rib: {}", type_parameter.id); - if seen_bindings.contains_key(&name) { - let span = seen_bindings.get(&name).unwrap(); - resolve_error(self, - type_parameter.span, - ResolutionError::NameAlreadyUsedInTypeParameterList(name, - span)); + if seen_bindings.contains_key(&ident) { + let span = seen_bindings.get(&ident).unwrap(); + let err = + ResolutionError::NameAlreadyUsedInTypeParameterList(ident.name, span); + resolve_error(self, type_parameter.span, err); } - seen_bindings.entry(name).or_insert(type_parameter.span); + seen_bindings.entry(ident).or_insert(type_parameter.span); // plain insert (no renaming) let def_id = self.definitions.local_def_id(type_parameter.id); let def = Def::TyParam(def_id); - function_type_rib.bindings.insert(Ident::with_empty_ctxt(name), def); + function_type_rib.bindings.insert(ident, def); self.record_def(type_parameter.id, PathResolution::new(def)); } self.ribs[TypeNS].push(function_type_rib); @@ -1825,11 +1825,20 @@ impl<'a> Resolver<'a> { let mut new_val = None; let mut new_id = None; if let Some(trait_ref) = opt_trait_ref { - let def = self.smart_resolve_path(trait_ref.ref_id, None, - &trait_ref.path, PathSource::Trait).base_def(); + let path: Vec<_> = trait_ref.path.segments.iter().map(|seg| seg.identifier).collect(); + let def = self.smart_resolve_path_fragment(trait_ref.ref_id, + None, + &path, + trait_ref.path.span, + trait_ref.path.segments.last().unwrap().span, + PathSource::Trait) + .base_def(); if def != Def::Err { - new_val = Some((def.def_id(), trait_ref.clone())); new_id = Some(def.def_id()); + let span = trait_ref.path.span; + if let PathResult::Module(module) = self.resolve_path(&path, None, false, span) { + new_val = Some((module, trait_ref.clone())); + } } } let original_trait_ref = replace(&mut self.current_trait_ref, new_val); @@ -1880,7 +1889,7 @@ impl<'a> Resolver<'a> { ImplItemKind::Const(..) => { // If this is a trait impl, ensure the const // exists in trait - this.check_trait_item(impl_item.ident.name, + this.check_trait_item(impl_item.ident, ValueNS, impl_item.span, |n, s| ResolutionError::ConstNotMemberOfTrait(n, s)); @@ -1889,7 +1898,7 @@ impl<'a> Resolver<'a> { ImplItemKind::Method(ref sig, _) => { // If this is a trait impl, ensure the method // exists in trait - this.check_trait_item(impl_item.ident.name, + this.check_trait_item(impl_item.ident, ValueNS, impl_item.span, |n, s| ResolutionError::MethodNotMemberOfTrait(n, s)); @@ -1906,7 +1915,7 @@ impl<'a> Resolver<'a> { ImplItemKind::Type(ref ty) => { // If this is a trait impl, ensure the type // exists in trait - this.check_trait_item(impl_item.ident.name, + this.check_trait_item(impl_item.ident, TypeNS, impl_item.span, |n, s| ResolutionError::TypeNotMemberOfTrait(n, s)); @@ -1924,15 +1933,15 @@ impl<'a> Resolver<'a> { }); } - fn check_trait_item(&self, name: Name, ns: Namespace, span: Span, err: F) + fn check_trait_item(&mut self, ident: Ident, ns: Namespace, span: Span, err: F) where F: FnOnce(Name, &str) -> ResolutionError { // If there is a TraitRef in scope for an impl, then the method must be in the // trait. - if let Some((did, ref trait_ref)) = self.current_trait_ref { - if !self.trait_item_map.contains_key(&(did, name, ns)) { - let path_str = path_names_to_string(&trait_ref.path); - resolve_error(self, span, err(name, &path_str)); + if let Some((module, _)) = self.current_trait_ref { + if self.resolve_ident_in_module(module, ident, ns, false, false, span).is_err() { + let path = &self.current_trait_ref.as_ref().unwrap().1.path; + resolve_error(self, span, err(ident.name, &path_names_to_string(path))); } } } @@ -2302,15 +2311,16 @@ impl<'a> Resolver<'a> { } // Try to lookup the name in more relaxed fashion for better error reporting. - let name = path.last().unwrap().name; - let candidates = this.lookup_import_candidates(name, ns, is_expected); + let ident = *path.last().unwrap(); + let candidates = this.lookup_import_candidates(ident.name, ns, is_expected); if !candidates.is_empty() { let mut module_span = this.current_module.span; module_span.hi = module_span.lo; // Report import candidates as help and proceed searching for labels. show_candidates(&mut err, module_span, &candidates, def.is_some()); } else if is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { - let enum_candidates = this.lookup_import_candidates(name, ns, is_enum_variant); + let enum_candidates = + this.lookup_import_candidates(ident.name, ns, is_enum_variant); let mut enum_candidates = enum_candidates.iter() .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::>(); enum_candidates.sort(); @@ -2326,7 +2336,7 @@ impl<'a> Resolver<'a> { } } if path.len() == 1 && this.self_type_is_available(span) { - if let Some(candidate) = this.lookup_assoc_candidate(name, ns, is_expected) { + if let Some(candidate) = this.lookup_assoc_candidate(ident, ns, is_expected) { let self_is_available = this.self_value_is_available(path[0].ctxt, span); match candidate { AssocSuggestion::Field => { @@ -2440,7 +2450,7 @@ impl<'a> Resolver<'a> { // or `::A::B`. If `B` should be resolved in value namespace then // it needs to be added to the trait map. if ns == ValueNS { - let item_name = path.last().unwrap().name; + let item_name = *path.last().unwrap(); let traits = self.get_traits_containing_item(item_name, ns); self.trait_map.insert(id, traits); } @@ -2819,7 +2829,7 @@ impl<'a> Resolver<'a> { } fn lookup_assoc_candidate(&mut self, - name: Name, + ident: Ident, ns: Namespace, filter_fn: FilterFn) -> Option @@ -2845,7 +2855,7 @@ impl<'a> Resolver<'a> { Def::Struct(did) | Def::Union(did) if resolution.unresolved_segments() == 0 => { if let Some(field_names) = self.field_names.get(&did) { - if field_names.iter().any(|&field_name| name == field_name) { + if field_names.iter().any(|&field_name| ident.name == field_name) { return Some(AssocSuggestion::Field); } } @@ -2857,10 +2867,12 @@ impl<'a> Resolver<'a> { } // Look for associated items in the current trait. - if let Some((trait_did, _)) = self.current_trait_ref { - if let Some(&(def, has_self)) = self.trait_item_map.get(&(trait_did, name, ns)) { + if let Some((module, _)) = self.current_trait_ref { + if let Ok(binding) = + self.resolve_ident_in_module(module, ident, ns, false, false, module.span) { + let def = binding.def(); if filter_fn(def) { - return Some(if has_self { + return Some(if self.has_self.contains(&def.def_id()) { AssocSuggestion::MethodWithSelf } else { AssocSuggestion::AssocItem @@ -3081,13 +3093,13 @@ impl<'a> Resolver<'a> { // field, we need to add any trait methods we find that match // the field name so that we can do some nice error reporting // later on in typeck. - let traits = self.get_traits_containing_item(name.node.name, ValueNS); + let traits = self.get_traits_containing_item(name.node, ValueNS); self.trait_map.insert(expr.id, traits); } ExprKind::MethodCall(name, ..) => { debug!("(recording candidate traits for expr) recording traits for {}", expr.id); - let traits = self.get_traits_containing_item(name.node.name, ValueNS); + let traits = self.get_traits_containing_item(name.node, ValueNS); self.trait_map.insert(expr.id, traits); } _ => { @@ -3096,20 +3108,21 @@ impl<'a> Resolver<'a> { } } - fn get_traits_containing_item(&mut self, name: Name, ns: Namespace) -> Vec { - debug!("(getting traits containing item) looking for '{}'", name); + fn get_traits_containing_item(&mut self, ident: Ident, ns: Namespace) -> Vec { + debug!("(getting traits containing item) looking for '{}'", ident.name); let mut found_traits = Vec::new(); // Look for the current trait. - if let Some((trait_def_id, _)) = self.current_trait_ref { - if self.trait_item_map.contains_key(&(trait_def_id, name, ns)) { - found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: None }); + if let Some((module, _)) = self.current_trait_ref { + if self.resolve_ident_in_module(module, ident, ns, false, false, module.span).is_ok() { + let def_id = module.def_id().unwrap(); + found_traits.push(TraitCandidate { def_id: def_id, import_id: None }); } } let mut search_module = self.current_module; loop { - self.get_traits_in_module_containing_item(name, ns, search_module, &mut found_traits); + self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits); match search_module.kind { ModuleKind::Block(..) => search_module = search_module.parent.unwrap(), _ => break, @@ -3118,7 +3131,7 @@ impl<'a> Resolver<'a> { if let Some(prelude) = self.prelude { if !search_module.no_implicit_prelude { - self.get_traits_in_module_containing_item(name, ns, prelude, &mut found_traits); + self.get_traits_in_module_containing_item(ident, ns, prelude, &mut found_traits); } } @@ -3126,9 +3139,9 @@ impl<'a> Resolver<'a> { } fn get_traits_in_module_containing_item(&mut self, - name: Name, + ident: Ident, ns: Namespace, - module: Module, + module: Module<'a>, found_traits: &mut Vec) { let mut traits = module.traits.borrow_mut(); if traits.is_none() { @@ -3143,8 +3156,8 @@ impl<'a> Resolver<'a> { } for &(trait_name, binding) in traits.as_ref().unwrap().iter() { - let trait_def_id = binding.def().def_id(); - if self.trait_item_map.contains_key(&(trait_def_id, name, ns)) { + let module = binding.module().unwrap(); + if self.resolve_ident_in_module(module, ident, ns, false, false, module.span).is_ok() { let import_id = match binding.kind { NameBindingKind::Import { directive, .. } => { self.maybe_unused_trait_imports.insert(directive.id); @@ -3153,6 +3166,7 @@ impl<'a> Resolver<'a> { } _ => None, }; + let trait_def_id = module.def_id().unwrap(); found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: import_id }); } }