From a54bbf2cb34d4a8bc28f99bb9a4677aa1dc2558c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 12 May 2017 11:21:11 +0200 Subject: [PATCH] Weave the span of an import through the resolve code --- src/librustc_resolve/build_reduced_graph.rs | 5 +- src/librustc_resolve/lib.rs | 80 ++++++++++++--------- src/librustc_resolve/macros.rs | 34 +++++---- src/librustc_resolve/resolve_imports.rs | 46 ++++++++---- 4 files changed, 101 insertions(+), 64 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 9d774b96325..57639a1ecef 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -608,7 +608,8 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expa } else { for (name, span) in legacy_imports.imports { let ident = Ident::with_empty_ctxt(name); - let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None); + let result = self.resolve_ident_in_module(module, ident, MacroNS, + false, false, span); if let Ok(binding) = result { let directive = macro_use_directive(span); self.potentially_unused_imports.push(directive); @@ -622,7 +623,7 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expa for (name, span) in legacy_imports.reexports { self.session.cstore.export_macros(module.def_id().unwrap().krate); let ident = Ident::with_empty_ctxt(name); - let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None); + let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span); if let Ok(binding) = result { self.macro_exports.push(Export { name: name, def: binding.def(), span: span }); } else { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 57d04bee92b..6011a680dcb 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -613,7 +613,7 @@ fn visit_ty(&mut self, ty: &'tcx Ty) { self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type); } else if let TyKind::ImplicitSelf = ty.node { let self_ty = keywords::SelfType.ident(); - let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.span)) + let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, true, ty.span) .map_or(Def::Err, |d| d.def()); self.record_def(ty.id, PathResolution::new(def)); } else if let TyKind::Array(ref element, ref length) = ty.node { @@ -1267,11 +1267,11 @@ fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) { let namespace = if is_value { ValueNS } else { TypeNS }; let hir::Path { ref segments, span, ref mut def } = *path; let path: Vec<_> = segments.iter().map(|seg| Ident::with_empty_ctxt(seg.name)).collect(); - match self.resolve_path(&path, Some(namespace), Some(span)) { + match self.resolve_path(&path, Some(namespace), true, span) { PathResult::Module(module) => *def = module.def().unwrap(), PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => *def = path_res.base_def(), - PathResult::NonModule(..) => match self.resolve_path(&path, None, Some(span)) { + PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span) { PathResult::Failed(msg, _) => { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); } @@ -1502,7 +1502,8 @@ fn add_to_glob_map(&mut self, id: NodeId, ident: Ident) { fn resolve_ident_in_lexical_scope(&mut self, mut ident: Ident, ns: Namespace, - record_used: Option) + record_used: bool, + path_span: Span) -> Option> { if ns == TypeNS { ident = ident.unhygienize(); @@ -1513,12 +1514,13 @@ fn resolve_ident_in_lexical_scope(&mut self, if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() { // The ident resolves to a type parameter or local variable. return Some(LexicalScopeBinding::Def( - self.adjust_local_def(ns, i, def, record_used) + self.adjust_local_def(ns, i, def, record_used, path_span) )); } if let ModuleRibKind(module) = self.ribs[ns][i].kind { - let item = self.resolve_ident_in_module(module, ident, ns, false, record_used); + let item = self.resolve_ident_in_module(module, ident, ns, false, + record_used, path_span); if let Ok(binding) = item { // The ident resolves to an item. return Some(LexicalScopeBinding::Item(binding)); @@ -1527,7 +1529,8 @@ fn resolve_ident_in_lexical_scope(&mut self, if let ModuleKind::Block(..) = module.kind { // We can see through blocks } else if !module.no_implicit_prelude { return self.prelude.and_then(|prelude| { - self.resolve_ident_in_module(prelude, ident, ns, false, None).ok() + self.resolve_ident_in_module(prelude, ident, ns, false, + false, path_span).ok() }).map(LexicalScopeBinding::Item) } else { return None; @@ -2147,7 +2150,8 @@ fn resolve_pattern(&mut self, PatKind::Ident(bmode, ref ident, ref opt_pat) => { // First try to resolve the identifier as some existing // entity, then fall back to a fresh binding. - let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS, None) + let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS, + false, pat.span) .and_then(LexicalScopeBinding::item); let resolution = binding.map(NameBinding::def).and_then(|def| { let always_binding = !pat_src.is_refutable() || opt_pat.is_some() || @@ -2253,7 +2257,7 @@ fn smart_resolve_path_fragment(&mut self, (format!(""), format!("the crate root")) } else { let mod_path = &path[..path.len() - 1]; - let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), None) { + let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), false, span) { PathResult::Module(module) => module.def(), _ => None, }.map_or(format!(""), |def| format!("{} ", def.kind_name())); @@ -2303,9 +2307,9 @@ fn smart_resolve_path_fragment(&mut self, } } } - if path.len() == 1 && this.self_type_is_available() { + if path.len() == 1 && this.self_type_is_available(span) { if let Some(candidate) = this.lookup_assoc_candidate(name, ns, is_expected) { - let self_is_available = this.self_value_is_available(path[0].ctxt); + let self_is_available = this.self_value_is_available(path[0].ctxt, span); match candidate { AssocSuggestion::Field => { err.span_label(span, format!("did you mean `self.{}`?", path_str)); @@ -2329,7 +2333,7 @@ fn smart_resolve_path_fragment(&mut self, let mut levenshtein_worked = false; // Try Levenshtein. - if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected) { + if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected, span) { err.span_label(ident_span, format!("did you mean `{}`?", candidate)); levenshtein_worked = true; } @@ -2434,14 +2438,15 @@ fn smart_resolve_path_fragment(&mut self, resolution } - fn self_type_is_available(&mut self) -> bool { - let binding = self.resolve_ident_in_lexical_scope(keywords::SelfType.ident(), TypeNS, None); + fn self_type_is_available(&mut self, span: Span) -> bool { + let binding = self.resolve_ident_in_lexical_scope(keywords::SelfType.ident(), + TypeNS, false, span); if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false } } - fn self_value_is_available(&mut self, ctxt: SyntaxContext) -> bool { + fn self_value_is_available(&mut self, ctxt: SyntaxContext, span: Span) -> bool { let ident = Ident { name: keywords::SelfValue.name(), ctxt: ctxt }; - let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None); + let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, false, span); if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false } } @@ -2505,7 +2510,7 @@ fn resolve_qpath(&mut self, )); } - let result = match self.resolve_path(&path, Some(ns), Some(span)) { + let result = match self.resolve_path(&path, Some(ns), true, span) { PathResult::NonModule(path_res) => path_res, PathResult::Module(module) if !module.is_normal() => { PathResolution::new(module.def().unwrap()) @@ -2551,7 +2556,7 @@ fn resolve_qpath(&mut self, if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && path[0].name != keywords::CrateRoot.name() && path[0].name != "$crate" { let unqualified_result = { - match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) { + match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) { PathResult::NonModule(path_res) => path_res.base_def(), PathResult::Module(module) => module.def().unwrap(), _ => return Some(result), @@ -2569,7 +2574,8 @@ fn resolve_qpath(&mut self, fn resolve_path(&mut self, path: &[Ident], opt_ns: Option, // `None` indicates a module path - record_used: Option) + record_used: bool, + path_span: Span) -> PathResult<'a> { let mut module = None; let mut allow_super = true; @@ -2603,12 +2609,12 @@ fn resolve_path(&mut self, } let binding = if let Some(module) = module { - self.resolve_ident_in_module(module, ident, ns, false, record_used) + self.resolve_ident_in_module(module, ident, ns, false, record_used, path_span) } else if opt_ns == Some(MacroNS) { - self.resolve_lexical_macro_path_segment(ident, ns, record_used) + self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span) .map(MacroBinding::binding) } else { - match self.resolve_ident_in_lexical_scope(ident, ns, record_used) { + match self.resolve_ident_in_lexical_scope(ident, ns, record_used, path_span) { Some(LexicalScopeBinding::Item(binding)) => Ok(binding), Some(LexicalScopeBinding::Def(def)) if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => { @@ -2616,7 +2622,7 @@ fn resolve_path(&mut self, def, path.len() - 1 )); } - _ => Err(if record_used.is_some() { Determined } else { Undetermined }), + _ => Err(if record_used { Determined } else { Undetermined }), } }; @@ -2673,12 +2679,13 @@ fn adjust_local_def(&mut self, ns: Namespace, rib_index: usize, mut def: Def, - record_used: Option) -> Def { + record_used: bool, + span: Span) -> Def { let ribs = &self.ribs[ns][rib_index + 1..]; // An invalid forward use of a type parameter from a previous default. if let ForwardTyParamBanRibKind = self.ribs[ns][rib_index].kind { - if let Some(span) = record_used { + if record_used { resolve_error(self, span, ResolutionError::ForwardDeclaredTyParam); } @@ -2688,7 +2695,7 @@ fn adjust_local_def(&mut self, match def { Def::Upvar(..) => { - span_bug!(record_used.unwrap_or(DUMMY_SP), "unexpected {:?} in bindings", def) + span_bug!(span, "unexpected {:?} in bindings", def) } Def::Local(def_id) => { for rib in ribs { @@ -2714,7 +2721,7 @@ fn adjust_local_def(&mut self, let depth = vec.len(); def = Def::Upvar(def_id, depth, function_id); - if let Some(span) = record_used { + if record_used { vec.push(Freevar { def: prev_def, span: span, @@ -2726,7 +2733,7 @@ fn adjust_local_def(&mut self, // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. - if let Some(span) = record_used { + if record_used { resolve_error(self, span, ResolutionError::CannotCaptureDynamicEnvironmentInFnItem); } @@ -2734,7 +2741,7 @@ fn adjust_local_def(&mut self, } ConstantItemRibKind => { // Still doesn't deal with upvars - if let Some(span) = record_used { + if record_used { resolve_error(self, span, ResolutionError::AttemptToUseNonConstantValueInConstant); } @@ -2753,7 +2760,7 @@ fn adjust_local_def(&mut self, ItemRibKind => { // This was an attempt to use a type parameter outside // its scope. - if let Some(span) = record_used { + if record_used { resolve_error(self, span, ResolutionError::TypeParametersFromOuterFunction); } @@ -2761,7 +2768,7 @@ fn adjust_local_def(&mut self, } ConstantItemRibKind => { // see #9186 - if let Some(span) = record_used { + if record_used { resolve_error(self, span, ResolutionError::OuterTypeParameterContext); } @@ -2857,7 +2864,8 @@ fn extract_node_id(t: &Ty) -> Option { fn lookup_typo_candidate(&mut self, path: &[Ident], ns: Namespace, - filter_fn: FilterFn) + filter_fn: FilterFn, + span: Span) -> Option where FilterFn: Fn(Def) -> bool { @@ -2909,7 +2917,8 @@ fn lookup_typo_candidate(&mut self, } else { // Search in module. let mod_path = &path[..path.len() - 1]; - if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), None) { + if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), + false, span) { add_module_candidates(module, &mut names); } } @@ -3410,7 +3419,10 @@ fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) { continue } let ident = attr.path.segments[0].identifier; - let result = self.resolve_lexical_macro_path_segment(ident, MacroNS, None); + let result = self.resolve_lexical_macro_path_segment(ident, + MacroNS, + false, + attr.path.span); if let Ok(binding) = result { if let SyntaxExtension::AttrProcMacro(..) = *binding.binding().get_macro(self) { attr::mark_known(attr); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index fffccada7d6..c08421cb937 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -379,7 +379,7 @@ fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKin return Err(Determinacy::Determined); } - let def = match self.resolve_path(&path, Some(MacroNS), None) { + let def = match self.resolve_path(&path, Some(MacroNS), false, span) { PathResult::NonModule(path_res) => match path_res.base_def() { Def::Err => Err(Determinacy::Determined), def @ _ => Ok(def), @@ -401,7 +401,7 @@ fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKin let result = if let Some(MacroBinding::Legacy(binding)) = legacy_resolution { Ok(Def::Macro(binding.def_id, MacroKind::Bang)) } else { - match self.resolve_lexical_macro_path_segment(path[0], MacroNS, None) { + match self.resolve_lexical_macro_path_segment(path[0], MacroNS, false, span) { Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()), Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined), Err(_) => { @@ -421,18 +421,19 @@ fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKin pub fn resolve_lexical_macro_path_segment(&mut self, ident: Ident, ns: Namespace, - record_used: Option) + record_used: bool, + path_span: Span) -> Result, Determinacy> { let mut module = Some(self.current_module); let mut potential_illegal_shadower = Err(Determinacy::Determined); let determinacy = - if record_used.is_some() { Determinacy::Determined } else { Determinacy::Undetermined }; + if record_used { Determinacy::Determined } else { Determinacy::Undetermined }; loop { let result = if let Some(module) = module { // Since expanded macros may not shadow the lexical scope and // globs may not shadow global macros (both enforced below), // we resolve with restricted shadowing (indicated by the penultimate argument). - self.resolve_ident_in_module(module, ident, ns, true, record_used) + self.resolve_ident_in_module(module, ident, ns, true, record_used, path_span) .map(MacroBinding::Modern) } else { self.global_macros.get(&ident.name).cloned().ok_or(determinacy) @@ -441,15 +442,18 @@ pub fn resolve_lexical_macro_path_segment(&mut self, match result.map(MacroBinding::binding) { Ok(binding) => { - let span = match record_used { - Some(span) => span, - None => return result, - }; + if !record_used { + return result; + } if let Ok(MacroBinding::Modern(shadower)) = potential_illegal_shadower { if shadower.def() != binding.def() { let name = ident.name; self.ambiguity_errors.push(AmbiguityError { - span: span, name: name, b1: shadower, b2: binding, lexical: true, + span: path_span, + name: name, + b1: shadower, + b2: binding, + lexical: true, legacy: false, }); return potential_illegal_shadower; @@ -543,7 +547,7 @@ pub fn resolve_legacy_scope(&mut self, pub fn finalize_current_module_macro_resolutions(&mut self) { let module = self.current_module; for &(ref path, span) in module.macro_resolutions.borrow().iter() { - match self.resolve_path(path, Some(MacroNS), Some(span)) { + match self.resolve_path(path, Some(MacroNS), true, span) { PathResult::NonModule(_) => {}, PathResult::Failed(msg, _) => { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); @@ -555,7 +559,7 @@ pub fn finalize_current_module_macro_resolutions(&mut self) { for &(mark, ident, span, kind) in module.legacy_macro_resolutions.borrow().iter() { let legacy_scope = &self.invocations[&mark].legacy_scope; let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident.name, true); - let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, Some(span)); + let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, true, span); match (legacy_resolution, resolution) { (Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => { let msg1 = format!("`{}` could refer to the macro defined here", ident); @@ -579,7 +583,7 @@ pub fn finalize_current_module_macro_resolutions(&mut self) { format!("cannot find derive macro `{}` in this scope", ident), }; let mut err = self.session.struct_span_err(span, &msg); - self.suggest_macro_name(&ident.name.as_str(), kind, &mut err); + self.suggest_macro_name(&ident.name.as_str(), kind, &mut err, span); err.emit(); }, _ => {}, @@ -588,7 +592,7 @@ pub fn finalize_current_module_macro_resolutions(&mut self) { } fn suggest_macro_name(&mut self, name: &str, kind: MacroKind, - err: &mut DiagnosticBuilder<'a>) { + err: &mut DiagnosticBuilder<'a>, span: Span) { // First check if this is a locally-defined bang macro. let suggestion = if let MacroKind::Bang = kind { find_best_match_for_name(self.macro_names.iter(), name, None) @@ -619,7 +623,7 @@ fn suggest_macro_name(&mut self, name: &str, kind: MacroKind, } }; let ident = Ident::from_str(name); - self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro) + self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro, span) }); if let Some(suggestion) = suggestion { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 804e1ea740f..1d4ba4ed100 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -146,7 +146,8 @@ pub fn resolve_ident_in_module(&mut self, ident: Ident, ns: Namespace, restricted_shadowing: bool, - record_used: Option) + record_used: bool, + path_span: Span) -> Result<&'a NameBinding<'a>, Determinacy> { self.populate_module_if_necessary(module); @@ -154,7 +155,7 @@ pub fn resolve_ident_in_module(&mut self, .try_borrow_mut() .map_err(|_| Determined)?; // This happens when there is a cycle of imports - if let Some(span) = record_used { + if record_used { if let Some(binding) = resolution.binding { if let Some(shadowed_glob) = resolution.shadows_glob { let name = ident.name; @@ -164,16 +165,20 @@ pub fn resolve_ident_in_module(&mut self, ns != MacroNS && // In MacroNS, `try_define` always forbids this shadowing binding.def() != shadowed_glob.def() { self.ambiguity_errors.push(AmbiguityError { - span: span, name: name, lexical: false, b1: binding, b2: shadowed_glob, + span: path_span, + name: name, + lexical: false, + b1: binding, + b2: shadowed_glob, legacy: false, }); } } - if self.record_use(ident, ns, binding, span) { + if self.record_use(ident, ns, binding, path_span) { return Ok(self.dummy_binding); } if !self.is_accessible(binding.vis) { - self.privacy_errors.push(PrivacyError(span, ident.name, binding)); + self.privacy_errors.push(PrivacyError(path_span, ident.name, binding)); } } @@ -205,7 +210,7 @@ pub fn resolve_ident_in_module(&mut self, SingleImport { source, .. } => source, _ => unreachable!(), }; - match self.resolve_ident_in_module(module, ident, ns, false, None) { + match self.resolve_ident_in_module(module, ident, ns, false, false, path_span) { Err(Determined) => {} _ => return Err(Undetermined), } @@ -230,7 +235,12 @@ pub fn resolve_ident_in_module(&mut self, for directive in module.globs.borrow().iter() { if self.is_accessible(directive.vis.get()) { if let Some(module) = directive.imported_module.get() { - let result = self.resolve_ident_in_module(module, ident, ns, false, None); + let result = self.resolve_ident_in_module(module, + ident, + ns, + false, + false, + path_span); if let Err(Undetermined) = result { return Err(Undetermined); } @@ -499,7 +509,7 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool { // For better failure detection, pretend that the import will not define any names // while resolving its module path. directive.vis.set(ty::Visibility::Invisible); - let result = self.resolve_path(&directive.module_path, None, None); + let result = self.resolve_path(&directive.module_path, None, false, directive.span); directive.vis.set(vis); match result { @@ -523,7 +533,12 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool { let mut indeterminate = false; self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { if let Err(Undetermined) = result[ns].get() { - result[ns].set(this.resolve_ident_in_module(module, source, ns, false, None)); + result[ns].set(this.resolve_ident_in_module(module, + source, + ns, + false, + false, + directive.span)); } else { return }; @@ -563,14 +578,14 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option module, PathResult::Failed(msg, _) => { let (mut self_path, mut self_result) = (module_path.clone(), None); if !self_path.is_empty() && !token::Ident(self_path[0]).is_path_segment_keyword() { self_path[0].name = keywords::SelfValue.name(); - self_result = Some(self.resolve_path(&self_path, None, None)); + self_result = Some(self.resolve_path(&self_path, None, false, span)); } return if let Some(PathResult::Module(..)) = self_result { Some(format!("Did you mean `{}`?", names_to_string(&self_path))) @@ -609,7 +624,12 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option) -> Option all_ns_failed = false, _ => {} } -- 2.44.0