From b6135e45ac4ecc9d90a7168e380902af8ac019bf Mon Sep 17 00:00:00 2001 From: Isaac Woods Date: Sun, 29 Apr 2018 17:42:22 +0100 Subject: [PATCH 1/5] Create ResolvePath abstraction in librustc_resolve --- src/librustc_resolve/lib.rs | 166 +++++++++++++++--------- src/librustc_resolve/macros.rs | 52 +++++--- src/librustc_resolve/resolve_imports.rs | 26 +++- 3 files changed, 157 insertions(+), 87 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 127331152c155..8694895e1e9e4 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -84,6 +84,13 @@ mod check_unused; mod build_reduced_graph; mod resolve_imports; +pub struct ResolvePath<'a> +{ + ident : &'a [Ident], + source : Option, // None if this path is speculative + speculative : bool, +} + /// A free importable items suggested in case of resolution failure. struct ImportSuggestion { path: Path, @@ -1654,12 +1661,18 @@ impl<'a> Resolver<'a> { let path: Vec = segments.iter() .map(|seg| Ident::new(seg.name, span)) .collect(); + + let resolve_path = ResolvePath { + ident : &path, + source : None, + speculative : true, + }; // FIXME (Manishearth): Intra doc links won't get warned of epoch changes - match self.resolve_path(&path, Some(namespace), true, span, None) { + match self.resolve_path(&resolve_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, None) { + PathResult::NonModule(..) => match self.resolve_path(&resolve_path, None, true, span) { PathResult::Failed(span, msg, _) => { error_callback(self, span, ResolutionError::FailedToResolve(&msg)); } @@ -2351,6 +2364,11 @@ impl<'a> Resolver<'a> { let path: Vec<_> = trait_ref.path.segments.iter() .map(|seg| seg.ident) .collect(); + let path = ResolvePath { + ident : &path, + source : Some(trait_ref.ref_id), + speculative : false, + }; let def = self.smart_resolve_path_fragment( trait_ref.ref_id, None, @@ -2361,8 +2379,7 @@ impl<'a> Resolver<'a> { if def != Def::Err { new_id = Some(def.def_id()); let span = trait_ref.path.span; - if let PathResult::Module(module) = self.resolve_path(&path, None, false, span, - Some(trait_ref.ref_id)) { + if let PathResult::Module(module) = self.resolve_path(&path, None, false, span) { new_val = Some((module, trait_ref.clone())); } } @@ -2787,17 +2804,22 @@ impl<'a> Resolver<'a> { let segments = &path.segments.iter() .map(|seg| seg.ident) .collect::>(); - self.smart_resolve_path_fragment(id, qself, segments, path.span, source) + let resolve_path = ResolvePath { + ident : &segments, + source : Some(id), + speculative : false, + }; + self.smart_resolve_path_fragment(id, qself, &resolve_path, path.span, source) } fn smart_resolve_path_fragment(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &ResolvePath, span: Span, source: PathSource) -> PathResolution { - let ident_span = path.last().map_or(span, |ident| ident.span); + let ident_span = path.ident.last().map_or(span, |ident| ident.span); let ns = source.namespace(); let is_expected = &|def| source.is_expected(def); let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false }; @@ -2806,27 +2828,31 @@ impl<'a> Resolver<'a> { let report_errors = |this: &mut Self, def: Option| { // Make the base error. let expected = source.descr_expected(); - let path_str = names_to_string(path); + let path_str = names_to_string(path.ident); let code = source.error_code(def.is_some()); let (base_msg, fallback_label, base_span) = if let Some(def) = def { (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str), format!("not a {}", expected), span) } else { - let item_str = path[path.len() - 1]; - let item_span = path[path.len() - 1].span; - let (mod_prefix, mod_str) = if path.len() == 1 { + let item_str = path.ident[path.ident.len() - 1]; + let item_span = path.ident[path.ident.len() - 1].span; + let (mod_prefix, mod_str) = if path.ident.len() == 1 { (format!(""), format!("this scope")) - } else if path.len() == 2 && path[0].name == keywords::CrateRoot.name() { + } else if path.ident.len() == 2 && path.ident[0].name == keywords::CrateRoot.name() { (format!(""), format!("the crate root")) } else { - let mod_path = &path[..path.len() - 1]; - let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), - false, span, None) { + let mod_path = ResolvePath { + ident : &path.ident[..path.ident.len() - 1], + source : Some(id), + speculative : false, + }; + 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())); - (mod_prefix, format!("`{}`", names_to_string(mod_path))) + (mod_prefix, format!("`{}`", names_to_string(mod_path.ident))) }; (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str), format!("not found in {}", mod_str), @@ -2836,13 +2862,13 @@ impl<'a> Resolver<'a> { let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code); // Emit special messages for unresolved `Self` and `self`. - if is_self_type(path, ns) { + if is_self_type(path.ident, ns) { __diagnostic_used!(E0411); err.code(DiagnosticId::Error("E0411".into())); err.span_label(span, "`Self` is only available in traits and impls"); return (err, Vec::new()); } - if is_self_value(path, ns) { + if is_self_value(path.ident, ns) { __diagnostic_used!(E0424); err.code(DiagnosticId::Error("E0424".into())); err.span_label(span, format!("`self` value is only available in \ @@ -2851,7 +2877,7 @@ impl<'a> Resolver<'a> { } // Try to lookup the name in more relaxed fashion for better error reporting. - let ident = *path.last().unwrap(); + let ident = *path.ident.last().unwrap(); let candidates = this.lookup_import_candidates(ident.name, ns, is_expected); if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { let enum_candidates = @@ -2872,9 +2898,9 @@ impl<'a> Resolver<'a> { } } } - if path.len() == 1 && this.self_type_is_available(span) { + if path.ident.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].span, span); + let self_is_available = this.self_value_is_available(path.ident[0].span, span); match candidate { AssocSuggestion::Field => { err.span_suggestion(span, "try", @@ -2900,7 +2926,7 @@ impl<'a> Resolver<'a> { let mut levenshtein_worked = false; // Try Levenshtein. - if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected, span) { + if let Some(candidate) = this.lookup_typo_candidate(path.ident, ns, is_expected, span) { err.span_label(ident_span, format!("did you mean `{}`?", candidate)); levenshtein_worked = true; } @@ -3028,7 +3054,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.ident.last().unwrap(); let traits = self.get_traits_containing_item(item_name, ns); self.trait_map.insert(id, traits); } @@ -3095,7 +3121,7 @@ impl<'a> Resolver<'a> { fn resolve_qpath_anywhere(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &ResolvePath, primary_ns: Namespace, span: Span, defer_to_typeck: bool, @@ -3115,10 +3141,10 @@ impl<'a> Resolver<'a> { }; } } - let is_global = self.global_macros.get(&path[0].name).cloned() + let is_global = self.global_macros.get(&path.ident[0].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())) { + self.macro_names.contains(&path.ident[0].modern())) { // Return some dummy definition, it's enough for error reporting. return Some( PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang)) @@ -3131,7 +3157,7 @@ impl<'a> Resolver<'a> { fn resolve_qpath(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &ResolvePath, ns: Namespace, span: Span, global_by_default: bool) @@ -3140,19 +3166,23 @@ impl<'a> Resolver<'a> { if qself.position == 0 { // FIXME: Create some fake resolution that can't possibly be a type. return Some(PathResolution::with_unresolved_segments( - Def::Mod(DefId::local(CRATE_DEF_INDEX)), path.len() + Def::Mod(DefId::local(CRATE_DEF_INDEX)), path.ident.len() )); } // Make sure `A::B` in `::B::C` is a trait item. - let ns = if qself.position + 1 == path.len() { ns } else { TypeNS }; - let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1], - span, PathSource::TraitItem(ns)); + let ns = if qself.position + 1 == path.ident.len() { ns } else { TypeNS }; + let resolve_path = ResolvePath { + ident : &path.ident[..qself.position + 1], + source : Some(id), + speculative : false, + }; + let res = self.smart_resolve_path_fragment(id, None, &resolve_path, span, PathSource::TraitItem(ns)); return Some(PathResolution::with_unresolved_segments( - res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1 + res.base_def(), res.unresolved_segments() + path.ident.len() - qself.position - 1 )); } - let result = match self.resolve_path(&path, Some(ns), true, span, Some(id)) { + 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()) @@ -3170,11 +3200,11 @@ impl<'a> Resolver<'a> { // Such behavior is required for backward compatibility. // The same fallback is used when `a` resolves to nothing. PathResult::Module(..) | PathResult::Failed(..) - if (ns == TypeNS || path.len() > 1) && + if (ns == TypeNS || path.ident.len() > 1) && self.primitive_type_table.primitive_types - .contains_key(&path[0].name) => { - let prim = self.primitive_type_table.primitive_types[&path[0].name]; - PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1) + .contains_key(&path.ident[0].name) => { + let prim = self.primitive_type_table.primitive_types[&path.ident[0].name]; + PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.ident.len() - 1) } PathResult::Module(module) => PathResolution::new(module.def().unwrap()), PathResult::Failed(span, msg, false) => { @@ -3185,11 +3215,16 @@ impl<'a> Resolver<'a> { PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), }; - if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && - path[0].name != keywords::CrateRoot.name() && - path[0].name != keywords::DollarCrate.name() { + if path.ident.len() > 1 && !global_by_default && result.base_def() != Def::Err && + path.ident[0].name != keywords::CrateRoot.name() && + path.ident[0].name != keywords::DollarCrate.name() { let unqualified_result = { - match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span, None) { + let resolve_path = ResolvePath { + ident : &[*path.ident.last().unwrap()], + source : None, + speculative : true, + }; + match self.resolve_path(&resolve_path, Some(ns), false, span) { PathResult::NonModule(path_res) => path_res.base_def(), PathResult::Module(module) => module.def().unwrap(), _ => return Some(result), @@ -3205,19 +3240,19 @@ impl<'a> Resolver<'a> { } fn resolve_path(&mut self, - path: &[Ident], + path: &ResolvePath, opt_ns: Option, // `None` indicates a module path record_used: bool, - path_span: Span, - node_id: Option) // None indicates that we don't care about linting + path_span: Span)//, + //node_id: Option) // None indicates that we don't care about linting // `::module` paths -> PathResult<'a> { let mut module = None; let mut allow_super = true; - for (i, &ident) in path.iter().enumerate() { + for (i, &ident) in path.ident.iter().enumerate() { debug!("resolve_path ident {} {:?}", i, ident); - let is_last = i == path.len() - 1; + let is_last = i == path.ident.len() - 1; let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; let name = ident.name; @@ -3247,7 +3282,7 @@ impl<'a> Resolver<'a> { if (i == 0 && name == keywords::CrateRoot.name()) || (i == 0 && name == keywords::Crate.name()) || (i == 1 && name == keywords::Crate.name() && - path[0].name == keywords::CrateRoot.name()) { + path.ident[0].name == keywords::CrateRoot.name()) { // `::a::b` or `::crate::a::b` module = Some(self.resolve_crate_root(ident.span.ctxt(), false)); continue @@ -3256,7 +3291,7 @@ impl<'a> Resolver<'a> { module = Some(self.resolve_crate_root(ident.span.ctxt(), true)); continue } else if i == 1 && !token::is_path_segment_keyword(ident) { - let prev_name = path[0].name; + let prev_name = path.ident[0].name; if prev_name == keywords::Extern.name() || prev_name == keywords::CrateRoot.name() && // Note: When this feature stabilizes, this should @@ -3282,14 +3317,14 @@ impl<'a> Resolver<'a> { name == keywords::Extern.name() && i != 0 || // we allow crate::foo and ::crate::foo but nothing else name == keywords::Crate.name() && i > 1 && - path[0].name != keywords::CrateRoot.name() || - name == keywords::Crate.name() && path.len() == 1 { + path.ident[0].name != keywords::CrateRoot.name() || + name == keywords::Crate.name() && path.ident.len() == 1 { let name_str = if name == keywords::CrateRoot.name() { format!("crate root") } else { format!("`{}`", name) }; - let msg = if i == 1 && path[0].name == keywords::CrateRoot.name() { + let msg = if i == 1 && path.ident[0].name == keywords::CrateRoot.name() { format!("global paths cannot start with {}", name_str) } else { format!("{} in paths can only be used in start position", name_str) @@ -3308,7 +3343,7 @@ impl<'a> Resolver<'a> { Some(LexicalScopeBinding::Def(def)) if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => { return PathResult::NonModule(PathResolution::with_unresolved_segments( - def, path.len() - 1 + def, path.ident.len() - 1 )); } _ => Err(if record_used { Determined } else { Undetermined }), @@ -3325,7 +3360,7 @@ impl<'a> Resolver<'a> { return PathResult::NonModule(err_path_resolution()); } else if opt_ns.is_some() && (is_last || maybe_assoc) { return PathResult::NonModule(PathResolution::with_unresolved_segments( - def, path.len() - i - 1 + def, path.ident.len() - i - 1 )); } else { return PathResult::Failed(ident.span, @@ -3333,10 +3368,10 @@ impl<'a> Resolver<'a> { is_last); } - if let Some(id) = node_id { + if let Some(id) = path.source { if i == 1 && self.session.features_untracked().crate_in_paths && !self.session.rust_2018() { - let prev_name = path[0].name; + let prev_name = path.ident[0].name; if prev_name == keywords::Extern.name() || prev_name == keywords::CrateRoot.name() { let mut is_crate = false; @@ -3365,7 +3400,7 @@ impl<'a> Resolver<'a> { if let Some(module) = module { if opt_ns.is_some() && !module.is_normal() { return PathResult::NonModule(PathResolution::with_unresolved_segments( - module.def().unwrap(), path.len() - i + module.def().unwrap(), path.ident.len() - i )); } } @@ -3384,7 +3419,7 @@ impl<'a> Resolver<'a> { } else if i == 0 { format!("Use of undeclared type or module `{}`", ident) } else { - format!("Could not find `{}` in `{}`", ident, path[i - 1]) + format!("Could not find `{}` in `{}`", ident, path.ident[i - 1]) }; return PathResult::Failed(ident.span, msg, is_last); } @@ -3604,9 +3639,13 @@ impl<'a> Resolver<'a> { } } else { // Search in module. - let mod_path = &path[..path.len() - 1]; - if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), - false, span, None) { + let mod_path = ResolvePath { + ident : &path[..path.len() - 1], + source : None, + speculative : true, + }; + if let PathResult::Module(module) = self.resolve_path(&mod_path, Some(TypeNS), + false, span) { add_module_candidates(module, &mut names); } } @@ -4024,7 +4063,12 @@ impl<'a> Resolver<'a> { let segments = path.make_root().iter().chain(path.segments.iter()) .map(|seg| seg.ident) .collect::>(); - let def = self.smart_resolve_path_fragment(id, None, &segments, path.span, + let resolve_path = ResolvePath { + ident : &segments, + source : None, + speculative : true, + }; + let def = self.smart_resolve_path_fragment(id, None, &resolve_path, path.span, PathSource::Visibility).base_def(); if def == Def::Err { ty::Visibility::Public diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index e72e02933e5e5..f1fe00b3badb2 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use {AmbiguityError, Resolver, ResolutionError, resolve_error}; +use {ResolvePath, AmbiguityError, Resolver, ResolutionError, resolve_error}; use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult}; use Namespace::{self, MacroNS}; use build_reduced_graph::BuildReducedGraphVisitor; @@ -439,25 +439,32 @@ impl<'a> Resolver<'a> { return Err(Determinacy::Determined); } - let def = match self.resolve_path(&path, Some(MacroNS), false, span, None) { - PathResult::NonModule(path_res) => match path_res.base_def() { - Def::Err => Err(Determinacy::Determined), - def @ _ => { - if path_res.unresolved_segments() > 0 { - self.found_unresolved_macro = true; - self.session.span_err(span, "fail to resolve non-ident macro path"); - Err(Determinacy::Determined) - } else { - Ok(def) + let def = { + let resolve_path = ResolvePath { + ident : &path, + source : None, + speculative : false, + }; + match self.resolve_path(&resolve_path, Some(MacroNS), false, span) { + PathResult::NonModule(path_res) => match path_res.base_def() { + Def::Err => Err(Determinacy::Determined), + def @ _ => { + if path_res.unresolved_segments() > 0 { + self.found_unresolved_macro = true; + self.session.span_err(span, "fail to resolve non-ident macro path"); + Err(Determinacy::Determined) + } else { + Ok(def) + } } - } - }, - PathResult::Module(..) => unreachable!(), - PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), - _ => { - self.found_unresolved_macro = true; - Err(Determinacy::Determined) - }, + }, + PathResult::Module(..) => unreachable!(), + PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), + _ => { + self.found_unresolved_macro = true; + Err(Determinacy::Determined) + }, + } }; self.current_module.nearest_item_scope().macro_resolutions.borrow_mut() .push((path.into_boxed_slice(), span)); @@ -617,7 +624,12 @@ 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, None) { + let resolve_path = ResolvePath { + ident : &path, + source : None, + speculative : true, + }; + match self.resolve_path(&resolve_path, Some(MacroNS), true, span) { PathResult::NonModule(_) => {}, PathResult::Failed(span, msg, _) => { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index e2a7f5668d251..acc5385586ffc 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -10,7 +10,7 @@ use self::ImportDirectiveSubclass::*; -use {AmbiguityError, Module, PerNS}; +use {ResolvePath, AmbiguityError, Module, PerNS}; use Namespace::{self, TypeNS, MacroNS}; use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError}; use Resolver; @@ -535,8 +535,12 @@ 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, Some(directive.id)); + let resolve_path = ResolvePath { + ident : &directive.module_path[..], + source : Some(directive.id), + speculative : false, + }; + let result = self.resolve_path(&resolve_path, None, false, directive.span); directive.vis.set(vis); match result { @@ -664,7 +668,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } } - let module_result = self.resolve_path(&module_path, None, true, span, Some(directive.id)); + let module_resolve_path = ResolvePath { + ident : &module_path, + source : Some(directive.id), + speculative : false, + }; + let module_result = self.resolve_path(&module_resolve_path, None, true, span); let module = match module_result { PathResult::Module(module) => module, PathResult::Failed(span, msg, false) => { @@ -678,8 +687,13 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if !self_path.is_empty() && !is_special(self_path[0]) && !(self_path.len() > 1 && is_special(self_path[1])) { self_path[0].name = keywords::SelfValue.name(); - self_result = Some(self.resolve_path(&self_path, None, false, - span, None)); + + let self_resolve_path = ResolvePath { + ident : &self_path, + source : None, + speculative : true, + }; + self_result = Some(self.resolve_path(&self_resolve_path, None, false, span)); } return if let Some(PathResult::Module(..)) = self_result { Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..])))) From 18571da340cd859981c95b8e01df4b05cdebda05 Mon Sep 17 00:00:00 2001 From: Isaac Woods Date: Sun, 29 Apr 2018 17:53:38 +0100 Subject: [PATCH 2/5] Fix Tidy errors --- src/librustc_resolve/lib.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 8694895e1e9e4..adfec84a6e43a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2839,7 +2839,8 @@ impl<'a> Resolver<'a> { let item_span = path.ident[path.ident.len() - 1].span; let (mod_prefix, mod_str) = if path.ident.len() == 1 { (format!(""), format!("this scope")) - } else if path.ident.len() == 2 && path.ident[0].name == keywords::CrateRoot.name() { + } else if path.ident.len() == 2 && + path.ident[0].name == keywords::CrateRoot.name() { (format!(""), format!("the crate root")) } else { let mod_path = ResolvePath { @@ -3176,7 +3177,8 @@ impl<'a> Resolver<'a> { source : Some(id), speculative : false, }; - let res = self.smart_resolve_path_fragment(id, None, &resolve_path, span, PathSource::TraitItem(ns)); + let res = self.smart_resolve_path_fragment(id, None, &resolve_path, + span, PathSource::TraitItem(ns)); return Some(PathResolution::with_unresolved_segments( res.base_def(), res.unresolved_segments() + path.ident.len() - qself.position - 1 )); @@ -3243,10 +3245,7 @@ impl<'a> Resolver<'a> { path: &ResolvePath, opt_ns: Option, // `None` indicates a module path record_used: bool, - path_span: Span)//, - //node_id: Option) // None indicates that we don't care about linting - // `::module` paths - -> PathResult<'a> { + path_span: Span) -> PathResult<'a> { let mut module = None; let mut allow_super = true; From af961c162bcb0c1edfe10eed70bd0e5df53482b9 Mon Sep 17 00:00:00 2001 From: Isaac Woods Date: Mon, 30 Apr 2018 17:42:04 +0100 Subject: [PATCH 3/5] Fix nits --- src/librustc_resolve/lib.rs | 89 ++++++++++++------------- src/librustc_resolve/macros.rs | 69 +++++++++---------- src/librustc_resolve/resolve_imports.rs | 45 ++++++------- 3 files changed, 95 insertions(+), 108 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index adfec84a6e43a..b8be27ef8bddb 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -84,11 +84,11 @@ mod check_unused; mod build_reduced_graph; mod resolve_imports; -pub struct ResolvePath<'a> -{ - ident : &'a [Ident], - source : Option, // None if this path is speculative - speculative : bool, +pub struct ResolvePath<'a> { + ident: &'a [Ident], + /// NodeId of the path that we are attempting to resolve. When None, this path is being + /// speculatively resolved and we should not emit errors or lints about it + source: Option, } /// A free importable items suggested in case of resolution failure. @@ -1662,17 +1662,16 @@ impl<'a> Resolver<'a> { .map(|seg| Ident::new(seg.name, span)) .collect(); - let resolve_path = ResolvePath { - ident : &path, - source : None, - speculative : true, - }; + let path = ResolvePath { + ident: &path, + source: None, + }; // FIXME (Manishearth): Intra doc links won't get warned of epoch changes - match self.resolve_path(&resolve_path, Some(namespace), true, 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(&resolve_path, None, true, span) { + PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span) { PathResult::Failed(span, msg, _) => { error_callback(self, span, ResolutionError::FailedToResolve(&msg)); } @@ -2365,10 +2364,9 @@ impl<'a> Resolver<'a> { .map(|seg| seg.ident) .collect(); let path = ResolvePath { - ident : &path, - source : Some(trait_ref.ref_id), - speculative : false, - }; + ident: &path, + source: Some(trait_ref.ref_id), + }; let def = self.smart_resolve_path_fragment( trait_ref.ref_id, None, @@ -2805,10 +2803,9 @@ impl<'a> Resolver<'a> { .map(|seg| seg.ident) .collect::>(); let resolve_path = ResolvePath { - ident : &segments, - source : Some(id), - speculative : false, - }; + ident: &segments, + source: Some(id), + }; self.smart_resolve_path_fragment(id, qself, &resolve_path, path.span, source) } @@ -2844,10 +2841,9 @@ impl<'a> Resolver<'a> { (format!(""), format!("the crate root")) } else { let mod_path = ResolvePath { - ident : &path.ident[..path.ident.len() - 1], - source : Some(id), - speculative : false, - }; + ident: &path.ident[..path.ident.len() - 1], + source: Some(id), + }; let mod_prefix = match this.resolve_path(&mod_path, Some(TypeNS), false, span) { PathResult::Module(module) => module.def(), @@ -3172,12 +3168,11 @@ impl<'a> Resolver<'a> { } // Make sure `A::B` in `::B::C` is a trait item. let ns = if qself.position + 1 == path.ident.len() { ns } else { TypeNS }; - let resolve_path = ResolvePath { - ident : &path.ident[..qself.position + 1], - source : Some(id), - speculative : false, - }; - let res = self.smart_resolve_path_fragment(id, None, &resolve_path, + let path = ResolvePath { + ident: &path.ident[..qself.position + 1], + source: Some(id), + }; + let res = self.smart_resolve_path_fragment(id, None, &path, span, PathSource::TraitItem(ns)); return Some(PathResolution::with_unresolved_segments( res.base_def(), res.unresolved_segments() + path.ident.len() - qself.position - 1 @@ -3221,12 +3216,11 @@ impl<'a> Resolver<'a> { path.ident[0].name != keywords::CrateRoot.name() && path.ident[0].name != keywords::DollarCrate.name() { let unqualified_result = { - let resolve_path = ResolvePath { - ident : &[*path.ident.last().unwrap()], - source : None, - speculative : true, - }; - match self.resolve_path(&resolve_path, Some(ns), false, span) { + let path = ResolvePath { + ident: &[*path.ident.last().unwrap()], + source: None, + }; + match self.resolve_path(&path, Some(ns), false, span) { PathResult::NonModule(path_res) => path_res.base_def(), PathResult::Module(module) => module.def().unwrap(), _ => return Some(result), @@ -3639,10 +3633,9 @@ impl<'a> Resolver<'a> { } else { // Search in module. let mod_path = ResolvePath { - ident : &path[..path.len() - 1], - source : None, - speculative : true, - }; + ident: &path[..path.len() - 1], + source: None, + }; if let PathResult::Module(module) = self.resolve_path(&mod_path, Some(TypeNS), false, span) { add_module_candidates(module, &mut names); @@ -4062,12 +4055,12 @@ impl<'a> Resolver<'a> { let segments = path.make_root().iter().chain(path.segments.iter()) .map(|seg| seg.ident) .collect::>(); - let resolve_path = ResolvePath { - ident : &segments, - source : None, - speculative : true, - }; - let def = self.smart_resolve_path_fragment(id, None, &resolve_path, path.span, + let span = path.span; + let path = ResolvePath { + ident: &segments, + source: None, + }; + let def = self.smart_resolve_path_fragment(id, None, &path, span, PathSource::Visibility).base_def(); if def == Def::Err { ty::Visibility::Public @@ -4076,8 +4069,8 @@ impl<'a> Resolver<'a> { if self.is_accessible(vis) { vis } else { - self.session.span_err(path.span, "visibilities can only be restricted \ - to ancestor modules"); + self.session.span_err(span, "visibilities can only be restricted \ + to ancestor modules"); ty::Visibility::Public } } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index f1fe00b3badb2..80f6499c66c72 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -426,11 +426,15 @@ impl<'a> Resolver<'a> { -> Result { let ast::Path { ref segments, span } = *path; let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect(); + let path = ResolvePath { + ident: &path, + source: None, + }; let invocation = self.invocations[&scope]; let module = invocation.module.get(); self.current_module = if module.is_trait() { module.parent.unwrap() } else { module }; - if path.len() > 1 { + if path.ident.len() > 1 { if !self.use_extern_macros && self.gated_errors.insert(span) { let msg = "non-ident macro paths are experimental"; let feature = "use_extern_macros"; @@ -439,43 +443,37 @@ impl<'a> Resolver<'a> { return Err(Determinacy::Determined); } - let def = { - let resolve_path = ResolvePath { - ident : &path, - source : None, - speculative : false, - }; - match self.resolve_path(&resolve_path, Some(MacroNS), false, span) { - PathResult::NonModule(path_res) => match path_res.base_def() { - Def::Err => Err(Determinacy::Determined), - def @ _ => { - if path_res.unresolved_segments() > 0 { - self.found_unresolved_macro = true; - self.session.span_err(span, "fail to resolve non-ident macro path"); - Err(Determinacy::Determined) - } else { - Ok(def) - } + 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 @ _ => { + if path_res.unresolved_segments() > 0 { + self.found_unresolved_macro = true; + self.session.span_err(span, "fail to resolve non-ident macro path"); + Err(Determinacy::Determined) + } else { + Ok(def) } - }, - PathResult::Module(..) => unreachable!(), - PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), - _ => { - self.found_unresolved_macro = true; - Err(Determinacy::Determined) - }, - } + } + }, + PathResult::Module(..) => unreachable!(), + PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), + _ => { + self.found_unresolved_macro = true; + Err(Determinacy::Determined) + }, }; self.current_module.nearest_item_scope().macro_resolutions.borrow_mut() - .push((path.into_boxed_slice(), span)); + .push((path_segments.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.ident[0], + 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.ident[0], MacroNS, false, span) { Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()), Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined), Err(_) => { @@ -486,7 +484,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.ident[0], span, kind)); result } @@ -624,12 +622,11 @@ 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() { - let resolve_path = ResolvePath { - ident : &path, - source : None, - speculative : true, - }; - match self.resolve_path(&resolve_path, Some(MacroNS), true, span) { + let path = ResolvePath { + ident: &path, + source: None, + }; + match self.resolve_path(&path, Some(MacroNS), true, span) { PathResult::NonModule(_) => {}, PathResult::Failed(span, msg, _) => { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index acc5385586ffc..0da58f9638820 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -535,12 +535,11 @@ 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 resolve_path = ResolvePath { - ident : &directive.module_path[..], - source : Some(directive.id), - speculative : false, - }; - let result = self.resolve_path(&resolve_path, None, false, directive.span); + let path = ResolvePath { + ident: &directive.module_path[..], + source: Some(directive.id), + }; + let result = self.resolve_path(&path, None, false, directive.span); directive.vis.set(vis); match result { @@ -668,12 +667,11 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } } - let module_resolve_path = ResolvePath { - ident : &module_path, - source : Some(directive.id), - speculative : false, - }; - let module_result = self.resolve_path(&module_resolve_path, None, true, span); + let module_path = ResolvePath { + ident: &module_path, + source: Some(directive.id), + }; + let module_result = self.resolve_path(&module_path, None, true, span); let module = match module_result { PathResult::Module(module) => module, PathResult::Failed(span, msg, false) => { @@ -681,22 +679,21 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { return None; } PathResult::Failed(span, msg, true) => { - let (mut self_path, mut self_result) = (module_path.clone(), None); + let (mut self_path_ident, mut self_result) = (module_path.ident.clone(), None); let is_special = |ident| token::is_path_segment_keyword(ident) && ident.name != keywords::CrateRoot.name(); - if !self_path.is_empty() && !is_special(self_path[0]) && - !(self_path.len() > 1 && is_special(self_path[1])) { - self_path[0].name = keywords::SelfValue.name(); - - let self_resolve_path = ResolvePath { - ident : &self_path, - source : None, - speculative : true, - }; - self_result = Some(self.resolve_path(&self_resolve_path, None, false, span)); + if !self_path_ident.is_empty() && !is_special(self_path_ident[0]) && + !(self_path_ident.len() > 1 && is_special(self_path_ident[1])) { + self_path_ident[0].name = keywords::SelfValue.name(); + let self_path = ResolvePath { + ident: self_path_ident, + source: None, + }; + self_result = Some(self.resolve_path(&self_path, None, false, span)); } return if let Some(PathResult::Module(..)) = self_result { - Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..])))) + Some((span, format!("Did you mean `{}`?", + names_to_string(&self_path_ident[..])))) } else { Some((span, msg)) }; From bfd2a75e22309f95239e58ad630f0ade1b441516 Mon Sep 17 00:00:00 2001 From: Isaac Woods Date: Mon, 30 Apr 2018 18:59:02 +0100 Subject: [PATCH 4/5] Rename ident to segments --- src/librustc_resolve/lib.rs | 98 +++++++++++++------------ src/librustc_resolve/macros.rs | 16 ++-- src/librustc_resolve/resolve_imports.rs | 16 ++-- 3 files changed, 66 insertions(+), 64 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b8be27ef8bddb..1dfd7a68db145 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -85,7 +85,7 @@ mod build_reduced_graph; mod resolve_imports; pub struct ResolvePath<'a> { - ident: &'a [Ident], + segments: &'a [Ident], /// NodeId of the path that we are attempting to resolve. When None, this path is being /// speculatively resolved and we should not emit errors or lints about it source: Option, @@ -1663,7 +1663,7 @@ impl<'a> Resolver<'a> { .collect(); let path = ResolvePath { - ident: &path, + segments: &path, source: None, }; // FIXME (Manishearth): Intra doc links won't get warned of epoch changes @@ -2364,7 +2364,7 @@ impl<'a> Resolver<'a> { .map(|seg| seg.ident) .collect(); let path = ResolvePath { - ident: &path, + segments: &path, source: Some(trait_ref.ref_id), }; let def = self.smart_resolve_path_fragment( @@ -2803,7 +2803,7 @@ impl<'a> Resolver<'a> { .map(|seg| seg.ident) .collect::>(); let resolve_path = ResolvePath { - ident: &segments, + segments: &segments, source: Some(id), }; self.smart_resolve_path_fragment(id, qself, &resolve_path, path.span, source) @@ -2816,7 +2816,7 @@ impl<'a> Resolver<'a> { span: Span, source: PathSource) -> PathResolution { - let ident_span = path.ident.last().map_or(span, |ident| ident.span); + let ident_span = path.segments.last().map_or(span, |ident| ident.span); let ns = source.namespace(); let is_expected = &|def| source.is_expected(def); let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false }; @@ -2825,23 +2825,23 @@ impl<'a> Resolver<'a> { let report_errors = |this: &mut Self, def: Option| { // Make the base error. let expected = source.descr_expected(); - let path_str = names_to_string(path.ident); + let path_str = names_to_string(path.segments); let code = source.error_code(def.is_some()); let (base_msg, fallback_label, base_span) = if let Some(def) = def { (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str), format!("not a {}", expected), span) } else { - let item_str = path.ident[path.ident.len() - 1]; - let item_span = path.ident[path.ident.len() - 1].span; - let (mod_prefix, mod_str) = if path.ident.len() == 1 { + let item_str = path.segments[path.segments.len() - 1]; + let item_span = path.segments[path.segments.len() - 1].span; + let (mod_prefix, mod_str) = if path.segments.len() == 1 { (format!(""), format!("this scope")) - } else if path.ident.len() == 2 && - path.ident[0].name == keywords::CrateRoot.name() { + } else if path.segments.len() == 2 && + path.segments[0].name == keywords::CrateRoot.name() { (format!(""), format!("the crate root")) } else { let mod_path = ResolvePath { - ident: &path.ident[..path.ident.len() - 1], + segments: &path.segments[..path.segments.len() - 1], source: Some(id), }; let mod_prefix = match this.resolve_path(&mod_path, Some(TypeNS), @@ -2849,7 +2849,7 @@ impl<'a> Resolver<'a> { PathResult::Module(module) => module.def(), _ => None, }.map_or(format!(""), |def| format!("{} ", def.kind_name())); - (mod_prefix, format!("`{}`", names_to_string(mod_path.ident))) + (mod_prefix, format!("`{}`", names_to_string(mod_path.segments))) }; (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str), format!("not found in {}", mod_str), @@ -2859,13 +2859,13 @@ impl<'a> Resolver<'a> { let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code); // Emit special messages for unresolved `Self` and `self`. - if is_self_type(path.ident, ns) { + if is_self_type(path.segments, ns) { __diagnostic_used!(E0411); err.code(DiagnosticId::Error("E0411".into())); err.span_label(span, "`Self` is only available in traits and impls"); return (err, Vec::new()); } - if is_self_value(path.ident, ns) { + if is_self_value(path.segments, ns) { __diagnostic_used!(E0424); err.code(DiagnosticId::Error("E0424".into())); err.span_label(span, format!("`self` value is only available in \ @@ -2874,7 +2874,7 @@ impl<'a> Resolver<'a> { } // Try to lookup the name in more relaxed fashion for better error reporting. - let ident = *path.ident.last().unwrap(); + let ident = *path.segments.last().unwrap(); let candidates = this.lookup_import_candidates(ident.name, ns, is_expected); if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { let enum_candidates = @@ -2895,9 +2895,10 @@ impl<'a> Resolver<'a> { } } } - if path.ident.len() == 1 && this.self_type_is_available(span) { + if path.segments.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.ident[0].span, span); + let self_is_available = this.self_value_is_available(path.segments[0].span, + span); match candidate { AssocSuggestion::Field => { err.span_suggestion(span, "try", @@ -2923,7 +2924,8 @@ impl<'a> Resolver<'a> { let mut levenshtein_worked = false; // Try Levenshtein. - if let Some(candidate) = this.lookup_typo_candidate(path.ident, ns, is_expected, span) { + if let Some(candidate) = this.lookup_typo_candidate(path.segments, ns, is_expected, + span) { err.span_label(ident_span, format!("did you mean `{}`?", candidate)); levenshtein_worked = true; } @@ -3051,7 +3053,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.ident.last().unwrap(); + let item_name = *path.segments.last().unwrap(); let traits = self.get_traits_containing_item(item_name, ns); self.trait_map.insert(id, traits); } @@ -3138,10 +3140,10 @@ impl<'a> Resolver<'a> { }; } } - let is_global = self.global_macros.get(&path.ident[0].name).cloned() + let is_global = self.global_macros.get(&path.segments[0].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.ident[0].modern())) { + self.macro_names.contains(&path.segments[0].modern())) { // Return some dummy definition, it's enough for error reporting. return Some( PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang)) @@ -3163,19 +3165,19 @@ impl<'a> Resolver<'a> { if qself.position == 0 { // FIXME: Create some fake resolution that can't possibly be a type. return Some(PathResolution::with_unresolved_segments( - Def::Mod(DefId::local(CRATE_DEF_INDEX)), path.ident.len() + Def::Mod(DefId::local(CRATE_DEF_INDEX)), path.segments.len() )); } // Make sure `A::B` in `::B::C` is a trait item. - let ns = if qself.position + 1 == path.ident.len() { ns } else { TypeNS }; + let ns = if qself.position + 1 == path.segments.len() { ns } else { TypeNS }; let path = ResolvePath { - ident: &path.ident[..qself.position + 1], + segments: &path.segments[..qself.position + 1], source: Some(id), }; let res = self.smart_resolve_path_fragment(id, None, &path, span, PathSource::TraitItem(ns)); return Some(PathResolution::with_unresolved_segments( - res.base_def(), res.unresolved_segments() + path.ident.len() - qself.position - 1 + res.base_def(), res.unresolved_segments() + path.segments.len() - qself.position - 1 )); } @@ -3197,11 +3199,11 @@ impl<'a> Resolver<'a> { // Such behavior is required for backward compatibility. // The same fallback is used when `a` resolves to nothing. PathResult::Module(..) | PathResult::Failed(..) - if (ns == TypeNS || path.ident.len() > 1) && + if (ns == TypeNS || path.segments.len() > 1) && self.primitive_type_table.primitive_types - .contains_key(&path.ident[0].name) => { - let prim = self.primitive_type_table.primitive_types[&path.ident[0].name]; - PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.ident.len() - 1) + .contains_key(&path.segments[0].name) => { + let prim = self.primitive_type_table.primitive_types[&path.segments[0].name]; + PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.segments.len() - 1) } PathResult::Module(module) => PathResolution::new(module.def().unwrap()), PathResult::Failed(span, msg, false) => { @@ -3212,12 +3214,12 @@ impl<'a> Resolver<'a> { PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), }; - if path.ident.len() > 1 && !global_by_default && result.base_def() != Def::Err && - path.ident[0].name != keywords::CrateRoot.name() && - path.ident[0].name != keywords::DollarCrate.name() { + if path.segments.len() > 1 && !global_by_default && result.base_def() != Def::Err && + path.segments[0].name != keywords::CrateRoot.name() && + path.segments[0].name != keywords::DollarCrate.name() { let unqualified_result = { let path = ResolvePath { - ident: &[*path.ident.last().unwrap()], + segments: &[*path.segments.last().unwrap()], source: None, }; match self.resolve_path(&path, Some(ns), false, span) { @@ -3243,9 +3245,9 @@ impl<'a> Resolver<'a> { let mut module = None; let mut allow_super = true; - for (i, &ident) in path.ident.iter().enumerate() { + for (i, &ident) in path.segments.iter().enumerate() { debug!("resolve_path ident {} {:?}", i, ident); - let is_last = i == path.ident.len() - 1; + let is_last = i == path.segments.len() - 1; let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; let name = ident.name; @@ -3275,7 +3277,7 @@ impl<'a> Resolver<'a> { if (i == 0 && name == keywords::CrateRoot.name()) || (i == 0 && name == keywords::Crate.name()) || (i == 1 && name == keywords::Crate.name() && - path.ident[0].name == keywords::CrateRoot.name()) { + path.segments[0].name == keywords::CrateRoot.name()) { // `::a::b` or `::crate::a::b` module = Some(self.resolve_crate_root(ident.span.ctxt(), false)); continue @@ -3284,7 +3286,7 @@ impl<'a> Resolver<'a> { module = Some(self.resolve_crate_root(ident.span.ctxt(), true)); continue } else if i == 1 && !token::is_path_segment_keyword(ident) { - let prev_name = path.ident[0].name; + let prev_name = path.segments[0].name; if prev_name == keywords::Extern.name() || prev_name == keywords::CrateRoot.name() && // Note: When this feature stabilizes, this should @@ -3310,14 +3312,14 @@ impl<'a> Resolver<'a> { name == keywords::Extern.name() && i != 0 || // we allow crate::foo and ::crate::foo but nothing else name == keywords::Crate.name() && i > 1 && - path.ident[0].name != keywords::CrateRoot.name() || - name == keywords::Crate.name() && path.ident.len() == 1 { + path.segments[0].name != keywords::CrateRoot.name() || + name == keywords::Crate.name() && path.segments.len() == 1 { let name_str = if name == keywords::CrateRoot.name() { format!("crate root") } else { format!("`{}`", name) }; - let msg = if i == 1 && path.ident[0].name == keywords::CrateRoot.name() { + let msg = if i == 1 && path.segments[0].name == keywords::CrateRoot.name() { format!("global paths cannot start with {}", name_str) } else { format!("{} in paths can only be used in start position", name_str) @@ -3336,7 +3338,7 @@ impl<'a> Resolver<'a> { Some(LexicalScopeBinding::Def(def)) if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => { return PathResult::NonModule(PathResolution::with_unresolved_segments( - def, path.ident.len() - 1 + def, path.segments.len() - 1 )); } _ => Err(if record_used { Determined } else { Undetermined }), @@ -3353,7 +3355,7 @@ impl<'a> Resolver<'a> { return PathResult::NonModule(err_path_resolution()); } else if opt_ns.is_some() && (is_last || maybe_assoc) { return PathResult::NonModule(PathResolution::with_unresolved_segments( - def, path.ident.len() - i - 1 + def, path.segments.len() - i - 1 )); } else { return PathResult::Failed(ident.span, @@ -3364,7 +3366,7 @@ impl<'a> Resolver<'a> { if let Some(id) = path.source { if i == 1 && self.session.features_untracked().crate_in_paths && !self.session.rust_2018() { - let prev_name = path.ident[0].name; + let prev_name = path.segments[0].name; if prev_name == keywords::Extern.name() || prev_name == keywords::CrateRoot.name() { let mut is_crate = false; @@ -3393,7 +3395,7 @@ impl<'a> Resolver<'a> { if let Some(module) = module { if opt_ns.is_some() && !module.is_normal() { return PathResult::NonModule(PathResolution::with_unresolved_segments( - module.def().unwrap(), path.ident.len() - i + module.def().unwrap(), path.segments.len() - i )); } } @@ -3412,7 +3414,7 @@ impl<'a> Resolver<'a> { } else if i == 0 { format!("Use of undeclared type or module `{}`", ident) } else { - format!("Could not find `{}` in `{}`", ident, path.ident[i - 1]) + format!("Could not find `{}` in `{}`", ident, path.segments[i - 1]) }; return PathResult::Failed(ident.span, msg, is_last); } @@ -3633,7 +3635,7 @@ impl<'a> Resolver<'a> { } else { // Search in module. let mod_path = ResolvePath { - ident: &path[..path.len() - 1], + segments: &path[..path.len() - 1], source: None, }; if let PathResult::Module(module) = self.resolve_path(&mod_path, Some(TypeNS), @@ -4057,7 +4059,7 @@ impl<'a> Resolver<'a> { .collect::>(); let span = path.span; let path = ResolvePath { - ident: &segments, + segments: &segments, source: None, }; let def = self.smart_resolve_path_fragment(id, None, &path, span, diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 80f6499c66c72..0f981ba5f209f 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -425,16 +425,16 @@ impl<'a> Resolver<'a> { kind: MacroKind, force: bool) -> Result { let ast::Path { ref segments, span } = *path; - let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect(); + let segments: Vec<_> = segments.iter().map(|seg| seg.ident).collect(); let path = ResolvePath { - ident: &path, + segments: &segments, source: None, }; let invocation = self.invocations[&scope]; let module = invocation.module.get(); self.current_module = if module.is_trait() { module.parent.unwrap() } else { module }; - if path.ident.len() > 1 { + if path.segments.len() > 1 { if !self.use_extern_macros && self.gated_errors.insert(span) { let msg = "non-ident macro paths are experimental"; let feature = "use_extern_macros"; @@ -468,12 +468,12 @@ impl<'a> Resolver<'a> { return def; } - let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path.ident[0], - false); + let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, + path.segments[0], 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.ident[0], MacroNS, false, span) { + match self.resolve_lexical_macro_path_segment(path.segments[0], MacroNS, false, span) { Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()), Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined), Err(_) => { @@ -484,7 +484,7 @@ impl<'a> Resolver<'a> { }; self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut() - .push((scope, path.ident[0], span, kind)); + .push((scope, path.segments[0], span, kind)); result } @@ -623,7 +623,7 @@ impl<'a> Resolver<'a> { let module = self.current_module; for &(ref path, span) in module.macro_resolutions.borrow().iter() { let path = ResolvePath { - ident: &path, + segments: &path, source: None, }; match self.resolve_path(&path, Some(MacroNS), true, span) { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 0da58f9638820..90d3e4b20f71b 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -536,7 +536,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { // while resolving its module path. directive.vis.set(ty::Visibility::Invisible); let path = ResolvePath { - ident: &directive.module_path[..], + segments: &directive.module_path[..], source: Some(directive.id), }; let result = self.resolve_path(&path, None, false, directive.span); @@ -668,7 +668,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } let module_path = ResolvePath { - ident: &module_path, + segments: &module_path, source: Some(directive.id), }; let module_result = self.resolve_path(&module_path, None, true, span); @@ -679,21 +679,21 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { return None; } PathResult::Failed(span, msg, true) => { - let (mut self_path_ident, mut self_result) = (module_path.ident.clone(), None); + let (mut self_path, mut self_result) = (module_path.segments.clone(), None); let is_special = |ident| token::is_path_segment_keyword(ident) && ident.name != keywords::CrateRoot.name(); - if !self_path_ident.is_empty() && !is_special(self_path_ident[0]) && - !(self_path_ident.len() > 1 && is_special(self_path_ident[1])) { - self_path_ident[0].name = keywords::SelfValue.name(); + if !self_path.is_empty() && !is_special(self_path[0]) && + !(self_path.len() > 1 && is_special(self_path[1])) { + self_path[0].name = keywords::SelfValue.name(); let self_path = ResolvePath { - ident: self_path_ident, + segments: self_path, source: None, }; self_result = Some(self.resolve_path(&self_path, None, false, span)); } return if let Some(PathResult::Module(..)) = self_result { Some((span, format!("Did you mean `{}`?", - names_to_string(&self_path_ident[..])))) + names_to_string(&self_path[..])))) } else { Some((span, msg)) }; From 20eaec5da241e1fe4a8b9c64d368834817f30ac5 Mon Sep 17 00:00:00 2001 From: Isaac Woods Date: Fri, 11 May 2018 15:50:23 +0100 Subject: [PATCH 5/5] Fix final few issues --- src/librustc_resolve/macros.rs | 57 +++++++++++++------------ src/librustc_resolve/resolve_imports.rs | 4 +- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 0f981ba5f209f..2e03ced679121 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -426,15 +426,11 @@ impl<'a> Resolver<'a> { -> Result { let ast::Path { ref segments, span } = *path; let segments: Vec<_> = segments.iter().map(|seg| seg.ident).collect(); - let path = ResolvePath { - segments: &segments, - source: None, - }; let invocation = self.invocations[&scope]; let module = invocation.module.get(); self.current_module = if module.is_trait() { module.parent.unwrap() } else { module }; - if path.segments.len() > 1 { + if segments.len() > 1 { if !self.use_extern_macros && self.gated_errors.insert(span) { let msg = "non-ident macro paths are experimental"; let feature = "use_extern_macros"; @@ -443,37 +439,44 @@ impl<'a> Resolver<'a> { return Err(Determinacy::Determined); } - 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 @ _ => { - if path_res.unresolved_segments() > 0 { - self.found_unresolved_macro = true; - self.session.span_err(span, "fail to resolve non-ident macro path"); - Err(Determinacy::Determined) - } else { - Ok(def) + let def = { + let path = ResolvePath { + segments: &segments, + source: None, + }; + + match self.resolve_path(&path, Some(MacroNS), false, span) { + PathResult::NonModule(path_res) => match path_res.base_def() { + Def::Err => Err(Determinacy::Determined), + def @ _ => { + if path_res.unresolved_segments() > 0 { + self.found_unresolved_macro = true; + self.session.span_err(span, "fail to resolve non-ident macro path"); + Err(Determinacy::Determined) + } else { + Ok(def) + } } - } - }, - PathResult::Module(..) => unreachable!(), - PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), - _ => { - self.found_unresolved_macro = true; - Err(Determinacy::Determined) - }, + }, + PathResult::Module(..) => unreachable!(), + PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), + _ => { + self.found_unresolved_macro = true; + Err(Determinacy::Determined) + }, + } }; self.current_module.nearest_item_scope().macro_resolutions.borrow_mut() - .push((path_segments.into_boxed_slice(), span)); + .push((segments.into_boxed_slice(), span)); return def; } let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, - path.segments[0], false); + segments[0], 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.segments[0], MacroNS, false, span) { + match self.resolve_lexical_macro_path_segment(segments[0], MacroNS, false, span) { Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()), Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined), Err(_) => { @@ -484,7 +487,7 @@ impl<'a> Resolver<'a> { }; self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut() - .push((scope, path.segments[0], span, kind)); + .push((scope, segments[0], span, kind)); result } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 90d3e4b20f71b..6c467f11b90a0 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -679,14 +679,14 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { return None; } PathResult::Failed(span, msg, true) => { - let (mut self_path, mut self_result) = (module_path.segments.clone(), None); + let (mut self_path, mut self_result) = (module_path.segments.to_vec(), None); let is_special = |ident| token::is_path_segment_keyword(ident) && ident.name != keywords::CrateRoot.name(); if !self_path.is_empty() && !is_special(self_path[0]) && !(self_path.len() > 1 && is_special(self_path[1])) { self_path[0].name = keywords::SelfValue.name(); let self_path = ResolvePath { - segments: self_path, + segments: &self_path, source: None, }; self_result = Some(self.resolve_path(&self_path, None, false, span));