diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 4b6b754dca6..a061484b5c4 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -35,6 +35,7 @@ use syntax::attr; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind}; use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind}; use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple}; +use syntax::codemap::respan; use syntax::ext::base::SyntaxExtension; use syntax::ext::base::Determinacy::Undetermined; use syntax::ext::hygiene::Mark; @@ -119,7 +120,7 @@ impl<'a> Resolver<'a> { .unwrap() .1 .iter() - .map(|seg| seg.identifier) + .map(|seg| respan(seg.span, seg.identifier)) .collect() } @@ -127,14 +128,16 @@ impl<'a> Resolver<'a> { ViewPathList(ref module_ident_path, _) => { module_ident_path.segments .iter() - .map(|seg| seg.identifier) + .map(|seg| respan(seg.span, seg.identifier)) .collect() } }; // This can be removed once warning cycle #36888 is complete. - if module_path.len() >= 2 && module_path[0].name == keywords::CrateRoot.name() && - token::Ident(module_path[1]).is_path_segment_keyword() { + if module_path.len() >= 2 && + module_path[0].node.name == keywords::CrateRoot.name() && + token::Ident(module_path[1].node).is_path_segment_keyword() + { module_path.remove(0); } @@ -202,10 +205,13 @@ impl<'a> Resolver<'a> { let (module_path, ident, rename, type_ns_only) = { if node.name.name != keywords::SelfValue.name() { let rename = node.rename.unwrap_or(node.name); - (module_path.clone(), node.name, rename, false) + (module_path.clone(), + respan(source_item.span, node.name), + rename, + false) } else { let ident = *module_path.last().unwrap(); - if ident.name == keywords::CrateRoot.name() { + if ident.node.name == keywords::CrateRoot.name() { resolve_error( self, source_item.span, @@ -215,13 +221,13 @@ impl<'a> Resolver<'a> { continue; } let module_path = module_path.split_last().unwrap().1; - let rename = node.rename.unwrap_or(ident); + let rename = node.rename.unwrap_or(ident.node); (module_path.to_vec(), ident, rename, true) } }; let subclass = SingleImport { target: rename, - source: ident, + source: ident.node, result: self.per_ns(|_, _| Cell::new(Err(Undetermined))), type_ns_only: type_ns_only, }; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 49e6929aeef..a339ee8a5ec 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -45,6 +45,7 @@ use rustc::ty; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; +use syntax::codemap::{dummy_spanned, respan}; use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy}; use syntax::ext::base::SyntaxExtension; @@ -149,7 +150,7 @@ enum ResolutionError<'a> { /// error E0431: `self` import can only appear in an import list with a non-empty prefix SelfImportOnlyInImportListWithNonEmptyPrefix, /// error E0432: unresolved import - UnresolvedImport(Option<(&'a str, &'a str)>), + UnresolvedImport(Option<(Span, &'a str, &'a str)>), /// error E0433: failed to resolve FailedToResolve(&'a str), /// error E0434: can't capture dynamic environment in a fn item @@ -297,12 +298,12 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, non-empty prefix") } ResolutionError::UnresolvedImport(name) => { - let msg = match name { - Some((n, _)) => format!("unresolved import `{}`", n), - None => "unresolved import".to_owned(), + let (span, msg) = match name { + Some((sp, n, _)) => (sp, format!("unresolved import `{}`", n)), + None => (span, "unresolved import".to_owned()), }; let mut err = struct_span_err!(resolver.session, span, E0432, "{}", msg); - if let Some((_, p)) = name { + if let Some((_, _, p)) = name { err.span_label(span, p); } err @@ -820,7 +821,7 @@ enum PathResult<'a> { Module(Module<'a>), NonModule(PathResolution), Indeterminate, - Failed(String, bool /* is the error from the last segment? */), + Failed(Span, String, bool /* is the error from the last segment? */), } enum ModuleKind { @@ -1276,19 +1277,21 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { 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(); + let path: Vec = segments.iter() + .map(|seg| respan(span, Ident::with_empty_ctxt(seg.name))) + .collect(); 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, true, span) { - PathResult::Failed(msg, _) => { + PathResult::Failed(span, msg, _) => { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); } _ => {} }, PathResult::Indeterminate => unreachable!(), - PathResult::Failed(msg, _) => { + PathResult::Failed(span, msg, _) => { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); } } @@ -1909,7 +1912,9 @@ impl<'a> Resolver<'a> { let mut new_val = None; let mut new_id = None; if let Some(trait_ref) = opt_trait_ref { - let path: Vec<_> = trait_ref.path.segments.iter().map(|seg| seg.identifier).collect(); + let path: Vec<_> = trait_ref.path.segments.iter() + .map(|seg| respan(seg.span, seg.identifier)) + .collect(); let def = self.smart_resolve_path_fragment(trait_ref.ref_id, None, &path, @@ -2334,7 +2339,9 @@ impl<'a> Resolver<'a> { path: &Path, source: PathSource) -> PathResolution { - let segments = &path.segments.iter().map(|seg| seg.identifier).collect::>(); + let segments = &path.segments.iter() + .map(|seg| respan(seg.span, seg.identifier)) + .collect::>(); let ident_span = path.segments.last().map_or(path.span, |seg| seg.span); self.smart_resolve_path_fragment(id, qself, segments, path.span, ident_span, source) } @@ -2342,7 +2349,7 @@ impl<'a> Resolver<'a> { fn smart_resolve_path_fragment(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &[SpannedIdent], span: Span, ident_span: Span, source: PathSource) @@ -2361,10 +2368,11 @@ impl<'a> Resolver<'a> { (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str), format!("not a {}", expected), span) } else { - let item_str = path[path.len() - 1]; + let item_str = path[path.len() - 1].node; + let item_span = path[path.len() - 1].span; let (mod_prefix, mod_str) = if path.len() == 1 { (format!(""), format!("this scope")) - } else if path.len() == 2 && path[0].name == keywords::CrateRoot.name() { + } else if path.len() == 2 && path[0].node.name == keywords::CrateRoot.name() { (format!(""), format!("the crate root")) } else { let mod_path = &path[..path.len() - 1]; @@ -2375,7 +2383,7 @@ impl<'a> Resolver<'a> { (mod_prefix, format!("`{}`", names_to_string(mod_path))) }; (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str), - format!("not found in {}", mod_str), ident_span) + format!("not found in {}", mod_str), item_span) }; let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code); @@ -2396,7 +2404,7 @@ impl<'a> Resolver<'a> { // Try to lookup the name in more relaxed fashion for better error reporting. let ident = *path.last().unwrap(); - let candidates = this.lookup_import_candidates(ident.name, ns, is_expected); + let candidates = this.lookup_import_candidates(ident.node.name, ns, is_expected); if !candidates.is_empty() { let mut module_span = this.current_module.span; module_span.hi = module_span.lo; @@ -2404,7 +2412,7 @@ impl<'a> Resolver<'a> { 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(ident.name, ns, is_enum_variant); + this.lookup_import_candidates(ident.node.name, ns, is_enum_variant); let mut enum_candidates = enum_candidates.iter() .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::>(); enum_candidates.sort(); @@ -2422,8 +2430,8 @@ impl<'a> Resolver<'a> { } } if path.len() == 1 && this.self_type_is_available(span) { - 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); + if let Some(candidate) = this.lookup_assoc_candidate(ident.node, ns, is_expected) { + let self_is_available = this.self_value_is_available(path[0].node.ctxt, span); match candidate { AssocSuggestion::Field => { err.span_suggestion(span, "try", @@ -2538,7 +2546,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(); + let item_name = path.last().unwrap().node; let traits = self.get_traits_containing_item(item_name, ns); self.trait_map.insert(id, traits); } @@ -2570,7 +2578,7 @@ impl<'a> Resolver<'a> { fn resolve_qpath_anywhere(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &[SpannedIdent], primary_ns: Namespace, span: Span, defer_to_typeck: bool, @@ -2590,9 +2598,10 @@ impl<'a> Resolver<'a> { }; } } - let is_global = self.global_macros.get(&path[0].name).cloned() + let is_global = self.global_macros.get(&path[0].node.name).cloned() .map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false); - if primary_ns != MacroNS && (is_global || self.macro_names.contains(&path[0].modern())) { + if primary_ns != MacroNS && (is_global || + self.macro_names.contains(&path[0].node.modern())) { // Return some dummy definition, it's enough for error reporting. return Some( PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang)) @@ -2605,7 +2614,7 @@ impl<'a> Resolver<'a> { fn resolve_qpath(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &[SpannedIdent], ns: Namespace, span: Span, global_by_default: bool) @@ -2645,8 +2654,9 @@ impl<'a> Resolver<'a> { // The same fallback is used when `a` resolves to nothing. PathResult::Module(..) | PathResult::Failed(..) if (ns == TypeNS || path.len() > 1) && - self.primitive_type_table.primitive_types.contains_key(&path[0].name) => { - let prim = self.primitive_type_table.primitive_types[&path[0].name]; + self.primitive_type_table.primitive_types + .contains_key(&path[0].node.name) => { + let prim = self.primitive_type_table.primitive_types[&path[0].node.name]; match prim { TyUint(UintTy::U128) | TyInt(IntTy::I128) => { if !self.session.features.borrow().i128_type { @@ -2661,7 +2671,7 @@ impl<'a> Resolver<'a> { PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1) } PathResult::Module(module) => PathResolution::new(module.def().unwrap()), - PathResult::Failed(msg, false) => { + PathResult::Failed(span, msg, false) => { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); err_path_resolution() } @@ -2670,8 +2680,8 @@ impl<'a> Resolver<'a> { }; if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && - path[0].name != keywords::CrateRoot.name() && - path[0].name != keywords::DollarCrate.name() { + path[0].node.name != keywords::CrateRoot.name() && + path[0].node.name != keywords::DollarCrate.name() { let unqualified_result = { match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) { PathResult::NonModule(path_res) => path_res.base_def(), @@ -2689,7 +2699,7 @@ impl<'a> Resolver<'a> { } fn resolve_path(&mut self, - path: &[Ident], + path: &[SpannedIdent], opt_ns: Option, // `None` indicates a module path record_used: bool, path_span: Span) @@ -2698,15 +2708,16 @@ impl<'a> Resolver<'a> { let mut allow_super = true; for (i, &ident) in path.iter().enumerate() { + debug!("resolve_path ident {} {:?}", i, ident); let is_last = i == path.len() - 1; let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; - if i == 0 && ns == TypeNS && ident.name == keywords::SelfValue.name() { - let mut ctxt = ident.ctxt.modern(); + if i == 0 && ns == TypeNS && ident.node.name == keywords::SelfValue.name() { + let mut ctxt = ident.node.ctxt.modern(); module = Some(self.resolve_self(&mut ctxt, self.current_module)); continue - } else if allow_super && ns == TypeNS && ident.name == keywords::Super.name() { - let mut ctxt = ident.ctxt.modern(); + } else if allow_super && ns == TypeNS && ident.node.name == keywords::Super.name() { + let mut ctxt = ident.node.ctxt.modern(); let self_module = match i { 0 => self.resolve_self(&mut ctxt, self.current_module), _ => module.unwrap(), @@ -2716,26 +2727,26 @@ impl<'a> Resolver<'a> { continue } else { let msg = "There are too many initial `super`s.".to_string(); - return PathResult::Failed(msg, false); + return PathResult::Failed(ident.span, msg, false); } } allow_super = false; - if i == 0 && ns == TypeNS && ident.name == keywords::CrateRoot.name() { - module = Some(self.resolve_crate_root(ident.ctxt.modern())); + if i == 0 && ns == TypeNS && ident.node.name == keywords::CrateRoot.name() { + module = Some(self.resolve_crate_root(ident.node.ctxt.modern())); continue - } else if i == 0 && ns == TypeNS && ident.name == keywords::DollarCrate.name() { - module = Some(self.resolve_crate_root(ident.ctxt)); + } else if i == 0 && ns == TypeNS && ident.node.name == keywords::DollarCrate.name() { + module = Some(self.resolve_crate_root(ident.node.ctxt)); continue } let binding = if let Some(module) = module { - self.resolve_ident_in_module(module, ident, ns, false, record_used, path_span) + self.resolve_ident_in_module(module, ident.node, ns, false, record_used, path_span) } else if opt_ns == Some(MacroNS) { - self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span) + self.resolve_lexical_macro_path_segment(ident.node, ns, record_used, path_span) .map(MacroBinding::binding) } else { - match self.resolve_ident_in_lexical_scope(ident, ns, record_used, path_span) { + match self.resolve_ident_in_lexical_scope(ident.node, ns, record_used, path_span) { Some(LexicalScopeBinding::Item(binding)) => Ok(binding), Some(LexicalScopeBinding::Def(def)) if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => { @@ -2760,7 +2771,9 @@ impl<'a> Resolver<'a> { def, path.len() - i - 1 )); } else { - return PathResult::Failed(format!("Not a module `{}`", ident), is_last); + return PathResult::Failed(ident.span, + format!("Not a module `{}`", ident.node), + is_last); } } Err(Undetermined) => return PathResult::Indeterminate, @@ -2775,19 +2788,19 @@ impl<'a> Resolver<'a> { let msg = if module.and_then(ModuleData::def) == self.graph_root.def() { let is_mod = |def| match def { Def::Mod(..) => true, _ => false }; let mut candidates = - self.lookup_import_candidates(ident.name, TypeNS, is_mod); + self.lookup_import_candidates(ident.node.name, TypeNS, is_mod); candidates.sort_by_key(|c| (c.path.segments.len(), c.path.to_string())); if let Some(candidate) = candidates.get(0) { format!("Did you mean `{}`?", candidate.path) } else { - format!("Maybe a missing `extern crate {};`?", ident) + format!("Maybe a missing `extern crate {};`?", ident.node) } } else if i == 0 { - format!("Use of undeclared type or module `{}`", ident) + format!("Use of undeclared type or module `{}`", ident.node) } else { - format!("Could not find `{}` in `{}`", ident, path[i - 1]) + format!("Could not find `{}` in `{}`", ident.node, path[i - 1].node) }; - return PathResult::Failed(msg, is_last); + return PathResult::Failed(ident.span, msg, is_last); } } } @@ -2807,8 +2820,7 @@ impl<'a> Resolver<'a> { // An invalid forward use of a type parameter from a previous default. if let ForwardTyParamBanRibKind = self.ribs[ns][rib_index].kind { if record_used { - resolve_error(self, span, - ResolutionError::ForwardDeclaredTyParam); + resolve_error(self, span, ResolutionError::ForwardDeclaredTyParam); } assert_eq!(def, Def::Err); return Def::Err; @@ -2978,7 +2990,7 @@ impl<'a> Resolver<'a> { } fn lookup_typo_candidate(&mut self, - path: &[Ident], + path: &[SpannedIdent], ns: Namespace, filter_fn: FilterFn, span: Span) @@ -3039,7 +3051,7 @@ impl<'a> Resolver<'a> { } } - let name = path[path.len() - 1].name; + let name = path[path.len() - 1].node.name; // Make sure error reporting is deterministic. names.sort_by_key(|name| name.as_str()); match find_best_match_for_name(names.iter(), &name.as_str(), None) { @@ -3573,27 +3585,31 @@ fn is_struct_like(def: Def) -> bool { } } -fn is_self_type(path: &[Ident], namespace: Namespace) -> bool { - namespace == TypeNS && path.len() == 1 && path[0].name == keywords::SelfType.name() +fn is_self_type(path: &[SpannedIdent], namespace: Namespace) -> bool { + namespace == TypeNS && path.len() == 1 && path[0].node.name == keywords::SelfType.name() } -fn is_self_value(path: &[Ident], namespace: Namespace) -> bool { - namespace == ValueNS && path.len() == 1 && path[0].name == keywords::SelfValue.name() +fn is_self_value(path: &[SpannedIdent], namespace: Namespace) -> bool { + namespace == ValueNS && path.len() == 1 && path[0].node.name == keywords::SelfValue.name() } -fn names_to_string(idents: &[Ident]) -> String { +fn names_to_string(idents: &[SpannedIdent]) -> String { let mut result = String::new(); - for (i, ident) in idents.iter().filter(|i| i.name != keywords::CrateRoot.name()).enumerate() { + for (i, ident) in idents.iter() + .filter(|i| i.node.name != keywords::CrateRoot.name()) + .enumerate() { if i > 0 { result.push_str("::"); } - result.push_str(&ident.name.as_str()); + result.push_str(&ident.node.name.as_str()); } result } fn path_names_to_string(path: &Path) -> String { - names_to_string(&path.segments.iter().map(|seg| seg.identifier).collect::>()) + names_to_string(&path.segments.iter() + .map(|seg| respan(seg.span, seg.identifier)) + .collect::>()) } /// Get the path for an enum and the variant from an `ImportSuggestion` for an enum variant. @@ -3661,7 +3677,10 @@ fn module_to_string(module: Module) -> String { if names.is_empty() { return "???".to_string(); } - names_to_string(&names.into_iter().rev().collect::>()) + names_to_string(&names.into_iter() + .rev() + .map(|n| dummy_spanned(n)) + .collect::>()) } fn err_path_resolution() -> PathResolution { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index a993aca92dd..18ec2b3cc1b 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -19,6 +19,7 @@ use rustc::hir::map::{self, DefCollector}; use rustc::{ty, lint}; use syntax::ast::{self, Name, Ident}; use syntax::attr::{self, HasAttrs}; +use syntax::codemap::respan; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator}; use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver}; @@ -393,7 +394,7 @@ impl<'a> Resolver<'a> { return Err(Determinacy::Determined); } - let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect(); + let path: Vec<_> = segments.iter().map(|seg| respan(seg.span, seg.identifier)).collect(); let invocation = self.invocations[&scope]; self.current_module = invocation.module.get(); @@ -418,16 +419,19 @@ impl<'a> Resolver<'a> { Err(Determinacy::Determined) }, }; + let path = path.iter().map(|p| p.node).collect::>(); self.current_module.nearest_item_scope().macro_resolutions.borrow_mut() .push((path.into_boxed_slice(), span)); return def; } - let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path[0], false); + let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, + path[0].node, + false); 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, false, span) { + match self.resolve_lexical_macro_path_segment(path[0].node, MacroNS, false, span) { Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()), Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined), Err(_) => { @@ -438,7 +442,7 @@ impl<'a> Resolver<'a> { }; self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut() - .push((scope, path[0], span, kind)); + .push((scope, path[0].node, span, kind)); result } @@ -576,9 +580,10 @@ impl<'a> Resolver<'a> { 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), true, span) { + let path = path.iter().map(|p| respan(span, *p)).collect::>(); + match self.resolve_path(&path, Some(MacroNS), true, span) { PathResult::NonModule(_) => {}, - PathResult::Failed(msg, _) => { + PathResult::Failed(span, msg, _) => { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); } _ => unreachable!(), @@ -652,7 +657,7 @@ impl<'a> Resolver<'a> { } }; let ident = Ident::from_str(name); - self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro, span) + self.lookup_typo_candidate(&vec![respan(span, 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 4bff5da3d6b..5e799b14f20 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -21,9 +21,9 @@ use rustc::ty; use rustc::lint::builtin::PUB_USE_OF_PRIVATE_EXTERN_CRATE; use rustc::hir::def_id::DefId; use rustc::hir::def::*; -use rustc::util::nodemap::FxHashMap; +use rustc::util::nodemap::{FxHashMap, FxHashSet}; -use syntax::ast::{Ident, NodeId}; +use syntax::ast::{Ident, SpannedIdent, NodeId}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::hygiene::Mark; use syntax::parse::token; @@ -57,7 +57,7 @@ pub enum ImportDirectiveSubclass<'a> { pub struct ImportDirective<'a> { pub id: NodeId, pub parent: Module<'a>, - pub module_path: Vec, + pub module_path: Vec, pub imported_module: Cell>>, // the resolution of `module_path` pub subclass: ImportDirectiveSubclass<'a>, pub span: Span, @@ -256,7 +256,7 @@ impl<'a> Resolver<'a> { // Add an import directive to the current module. pub fn add_import_directive(&mut self, - module_path: Vec, + module_path: Vec, subclass: ImportDirectiveSubclass<'a>, span: Span, id: NodeId, @@ -478,9 +478,10 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } let mut errors = false; + let mut seen_spans = FxHashSet(); for i in 0 .. self.determined_imports.len() { let import = self.determined_imports[i]; - if let Some(err) = self.finalize_import(import) { + if let Some((span, err)) = self.finalize_import(import) { errors = true; if let SingleImport { source, ref result, .. } = import.subclass { @@ -496,9 +497,14 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { // If the error is a single failed import then create a "fake" import // resolution for it so that later resolve stages won't complain. self.import_dummy_binding(import); - let path = import_path_to_string(&import.module_path, &import.subclass); - let error = ResolutionError::UnresolvedImport(Some((&path, &err))); - resolve_error(self.resolver, import.span, error); + if !seen_spans.contains(&span) { + let path = import_path_to_string(&import.module_path[..], + &import.subclass, + span); + let error = ResolutionError::UnresolvedImport(Some((span, &path, &err))); + resolve_error(self.resolver, span, error); + seen_spans.insert(span); + } } } @@ -516,7 +522,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { /// If successful, the resolved bindings are written into the module. fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool { debug!("(resolving import for module) resolving import `{}::...` in `{}`", - names_to_string(&directive.module_path), + names_to_string(&directive.module_path[..]), module_to_string(self.current_module)); self.current_module = directive.parent; @@ -528,7 +534,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { // 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, false, directive.span); + let result = self.resolve_path(&directive.module_path[..], None, false, directive.span); directive.vis.set(vis); match result { @@ -593,23 +599,25 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } // If appropriate, returns an error to report. - fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option { + fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> { self.current_module = directive.parent; let ImportDirective { ref module_path, span, .. } = *directive; let module_result = self.resolve_path(&module_path, None, true, span); let module = match module_result { PathResult::Module(module) => module, - PathResult::Failed(msg, _) => { + PathResult::Failed(span, 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(); + if !self_path.is_empty() && + !token::Ident(self_path[0].node).is_path_segment_keyword() + { + self_path[0].node.name = keywords::SelfValue.name(); 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))) + Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..])))) } else { - Some(msg) + Some((span, msg)) }; }, _ => return None, @@ -619,7 +627,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { SingleImport { source, ref result, type_ns_only, .. } => (source, result, type_ns_only), GlobImport { .. } if module.def_id() == directive.parent.def_id() => { // Importing a module into itself is not allowed. - return Some("Cannot glob-import a module into itself.".to_string()); + return Some((directive.span, + "Cannot glob-import a module into itself.".to_string())); } GlobImport { is_prelude, ref max_vis } => { if !is_prelude && @@ -708,7 +717,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } else { format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion) }; - Some(msg) + Some((span, msg)) } else { // `resolve_ident_in_module` reported a privacy error. self.import_dummy_binding(directive); @@ -888,16 +897,24 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } } -fn import_path_to_string(names: &[Ident], subclass: &ImportDirectiveSubclass) -> String { - let global = !names.is_empty() && names[0].name == keywords::CrateRoot.name(); - let names = if global { &names[1..] } else { names }; - if names.is_empty() { - import_directive_subclass_to_string(subclass) +fn import_path_to_string(names: &[SpannedIdent], + subclass: &ImportDirectiveSubclass, + span: Span) -> String { + let pos = names.iter() + .position(|p| span == p.span && p.node.name != keywords::CrateRoot.name()); + let global = !names.is_empty() && names[0].node.name == keywords::CrateRoot.name(); + if let Some(pos) = pos { + let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] }; + names_to_string(names) } else { - (format!("{}::{}", - names_to_string(names), - import_directive_subclass_to_string(subclass))) - .to_string() + let names = if global { &names[1..] } else { names }; + if names.is_empty() { + import_directive_subclass_to_string(subclass) + } else { + (format!("{}::{}", + names_to_string(names), + import_directive_subclass_to_string(subclass))) + } } } diff --git a/src/test/compile-fail/dollar-crate-is-keyword-2.rs b/src/test/compile-fail/dollar-crate-is-keyword-2.rs index e221fc6e9e0..ac96279d614 100644 --- a/src/test/compile-fail/dollar-crate-is-keyword-2.rs +++ b/src/test/compile-fail/dollar-crate-is-keyword-2.rs @@ -13,7 +13,7 @@ mod a {} macro_rules! m { () => { use a::$crate; //~ ERROR unresolved import `a::$crate` - use a::$crate::b; //~ ERROR unresolved import `a::$crate::b` + use a::$crate::b; //~ ERROR unresolved import `a::$crate` type A = a::$crate; //~ ERROR cannot find type `$crate` in module `a` } } diff --git a/src/test/compile-fail/import2.rs b/src/test/compile-fail/import2.rs index f5b03f9b2e9..c4bd9ff1e2a 100644 --- a/src/test/compile-fail/import2.rs +++ b/src/test/compile-fail/import2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use baz::zed::bar; //~ ERROR unresolved import `baz::zed::bar` [E0432] +use baz::zed::bar; //~ ERROR unresolved import `baz::zed` [E0432] //~^ Could not find `zed` in `baz` mod baz {} diff --git a/src/test/compile-fail/issue-1697.rs b/src/test/compile-fail/issue-1697.rs index 1375200271c..f8a68264339 100644 --- a/src/test/compile-fail/issue-1697.rs +++ b/src/test/compile-fail/issue-1697.rs @@ -10,7 +10,7 @@ // Testing that we don't fail abnormally after hitting the errors -use unresolved::*; //~ ERROR unresolved import `unresolved::*` [E0432] +use unresolved::*; //~ ERROR unresolved import `unresolved` [E0432] //~^ Maybe a missing `extern crate unresolved;`? fn main() {} diff --git a/src/test/compile-fail/issue-30560.rs b/src/test/compile-fail/issue-30560.rs index b0cfd8714fc..0b1afd75ca9 100644 --- a/src/test/compile-fail/issue-30560.rs +++ b/src/test/compile-fail/issue-30560.rs @@ -10,10 +10,10 @@ type Alias = (); use Alias::*; -//~^ ERROR unresolved import `Alias::*` [E0432] +//~^ ERROR unresolved import `Alias` [E0432] //~| Not a module `Alias` use std::io::Result::*; -//~^ ERROR unresolved import `std::io::Result::*` [E0432] +//~^ ERROR unresolved import `std::io::Result` [E0432] //~| Not a module `Result` trait T {} diff --git a/src/test/compile-fail/issue-33464.rs b/src/test/compile-fail/issue-33464.rs index 992bd33ea2e..b7dbaf20eca 100644 --- a/src/test/compile-fail/issue-33464.rs +++ b/src/test/compile-fail/issue-33464.rs @@ -11,13 +11,10 @@ // Make sure that the spans of import errors are correct. use abc::one_el; -//~^ ERROR 13:5: 13:16 +//~^ ERROR 13:5: 13:8 use abc::{a, bbb, cccccc}; -//~^ ERROR 15:11: 15:12 -//~^^ ERROR 15:14: 15:17 -//~^^^ ERROR 15:19: 15:25 +//~^ ERROR 15:5: 15:8 use a_very_long_name::{el, el2}; -//~^ ERROR 19:24: 19:26 -//~^^ ERROR 19:28: 19:31 +//~^ ERROR 17:5: 17:21 fn main() {} diff --git a/src/test/compile-fail/resolve_self_super_hint.rs b/src/test/compile-fail/resolve_self_super_hint.rs index d49f136f11f..09951348448 100644 --- a/src/test/compile-fail/resolve_self_super_hint.rs +++ b/src/test/compile-fail/resolve_self_super_hint.rs @@ -13,19 +13,19 @@ mod a { extern crate alloc; use alloc::HashMap; - //~^ ERROR unresolved import `alloc::HashMap` [E0432] + //~^ ERROR unresolved import `alloc` [E0432] //~| Did you mean `self::alloc`? mod b { use alloc::HashMap; - //~^ ERROR unresolved import `alloc::HashMap` [E0432] + //~^ ERROR unresolved import `alloc` [E0432] //~| Did you mean `a::alloc`? mod c { use alloc::HashMap; - //~^ ERROR unresolved import `alloc::HashMap` [E0432] + //~^ ERROR unresolved import `alloc` [E0432] //~| Did you mean `a::alloc`? mod d { use alloc::HashMap; - //~^ ERROR unresolved import `alloc::HashMap` [E0432] + //~^ ERROR unresolved import `alloc` [E0432] //~| Did you mean `a::alloc`? } } diff --git a/src/test/compile-fail/super-at-top-level.rs b/src/test/compile-fail/super-at-top-level.rs index 7d11ff6c9b5..4db673e2006 100644 --- a/src/test/compile-fail/super-at-top-level.rs +++ b/src/test/compile-fail/super-at-top-level.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::f; //~ ERROR unresolved import `super::f` [E0432] +use super::f; //~ ERROR unresolved import `super` [E0432] //~^ There are too many initial `super`s. fn main() { diff --git a/src/test/compile-fail/unresolved-import.rs b/src/test/compile-fail/unresolved-import.rs index 47490af0ff3..a3eeb6de96b 100644 --- a/src/test/compile-fail/unresolved-import.rs +++ b/src/test/compile-fail/unresolved-import.rs @@ -10,7 +10,7 @@ // ignore-tidy-linelength -use foo::bar; //~ ERROR unresolved import `foo::bar` [E0432] +use foo::bar; //~ ERROR unresolved import `foo` [E0432] //~^ Maybe a missing `extern crate foo;`? use bar::Baz as x; //~ ERROR unresolved import `bar::Baz` [E0432] @@ -41,7 +41,7 @@ mod m { MyVariant } - use MyEnum::*; //~ ERROR unresolved import `MyEnum::*` [E0432] + use MyEnum::*; //~ ERROR unresolved import `MyEnum` [E0432] //~^ Did you mean `self::MyEnum`? } @@ -50,7 +50,7 @@ mod items { Variant } - use Enum::*; //~ ERROR unresolved import `Enum::*` [E0432] + use Enum::*; //~ ERROR unresolved import `Enum` [E0432] //~^ Did you mean `self::Enum`? fn item() {} diff --git a/src/test/compile-fail/use-from-trait-xc.rs b/src/test/compile-fail/use-from-trait-xc.rs index a40fa233721..3848b6814d9 100644 --- a/src/test/compile-fail/use-from-trait-xc.rs +++ b/src/test/compile-fail/use-from-trait-xc.rs @@ -22,13 +22,13 @@ use use_from_trait_xc::Trait::CONST; //~^ ERROR `CONST` is not directly importable use use_from_trait_xc::Foo::new; //~ ERROR struct `Foo` is private -//~^ ERROR unresolved import `use_from_trait_xc::Foo::new` +//~^ ERROR unresolved import `use_from_trait_xc::Foo` use use_from_trait_xc::Foo::C; //~ ERROR struct `Foo` is private -//~^ ERROR unresolved import `use_from_trait_xc::Foo::C` +//~^ ERROR unresolved import `use_from_trait_xc::Foo` use use_from_trait_xc::Bar::new as bnew; -//~^ ERROR unresolved import `use_from_trait_xc::Bar::new` +//~^ ERROR unresolved import `use_from_trait_xc::Bar` use use_from_trait_xc::Baz::new as baznew; //~^ ERROR unresolved import `use_from_trait_xc::Baz::new` diff --git a/src/test/compile-fail/use-from-trait.rs b/src/test/compile-fail/use-from-trait.rs index 33adc2b5bfe..29db949acd0 100644 --- a/src/test/compile-fail/use-from-trait.rs +++ b/src/test/compile-fail/use-from-trait.rs @@ -17,11 +17,11 @@ use Trait::C; //~^ ERROR `C` is not directly importable use Foo::new; -//~^ ERROR unresolved import `Foo::new` [E0432] +//~^ ERROR unresolved import `Foo` [E0432] //~| Not a module `Foo` use Foo::C2; -//~^ ERROR unresolved import `Foo::C2` [E0432] +//~^ ERROR unresolved import `Foo` [E0432] //~| Not a module `Foo` pub trait Trait { diff --git a/src/test/compile-fail/use-mod-4.rs b/src/test/compile-fail/use-mod-4.rs index f102a68c2c5..275e5ff1da6 100644 --- a/src/test/compile-fail/use-mod-4.rs +++ b/src/test/compile-fail/use-mod-4.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use foo::self; //~ ERROR unresolved import `foo::self` +use foo::self; //~ ERROR unresolved import `foo` //~^ ERROR `self` imports are only allowed within a { } list use std::mem::self; diff --git a/src/test/ui/macros/macro_path_as_generic_bound.stderr b/src/test/ui/macros/macro_path_as_generic_bound.stderr index e4044f5aaf2..5c3bb66d83a 100644 --- a/src/test/ui/macros/macro_path_as_generic_bound.stderr +++ b/src/test/ui/macros/macro_path_as_generic_bound.stderr @@ -2,7 +2,7 @@ error[E0433]: failed to resolve. Use of undeclared type or module `m` --> $DIR/macro_path_as_generic_bound.rs:17:6 | 17 | foo!(m::m2::A); - | ^^^^^^^^ Use of undeclared type or module `m` + | ^ Use of undeclared type or module `m` error: cannot continue compilation due to previous error diff --git a/src/test/ui/span/non-existing-module-import.rs b/src/test/ui/span/non-existing-module-import.rs new file mode 100644 index 00000000000..3d45a94d531 --- /dev/null +++ b/src/test/ui/span/non-existing-module-import.rs @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::bar::{foo1, foo2}; + +fn main() {} diff --git a/src/test/ui/span/non-existing-module-import.stderr b/src/test/ui/span/non-existing-module-import.stderr new file mode 100644 index 00000000000..93339576f49 --- /dev/null +++ b/src/test/ui/span/non-existing-module-import.stderr @@ -0,0 +1,8 @@ +error[E0432]: unresolved import `std::bar` + --> $DIR/non-existing-module-import.rs:11:10 + | +11 | use std::bar::{foo1, foo2}; + | ^^^ Could not find `bar` in `std` + +error: aborting due to previous error +