X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_resolve%2Flib.rs;h=0285a3c568cc1bd306e1df975ab30f27ba69bab4;hb=63ac2aae51034f93c23cffde7be711a86f9d139f;hp=86fe584dc3a40fe937c4199474e1958402d8602c;hpb=9ee49bbb88c2c7f4e06a14c95da2e0c0b843abd8;p=rust.git diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 86fe584dc3a..0285a3c568c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -58,6 +58,7 @@ use syntax::ext::base::SyntaxExtension; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::base::MacroKind; +use syntax::feature_gate::{emit_feature_err, GateIssue}; use syntax::symbol::{Symbol, keywords}; use syntax::util::lev_distance::find_best_match_for_name; @@ -631,6 +632,43 @@ fn error_code(self, has_unexpected_resolution: bool) -> &'static str { } } +// A minimal representation of a path segment. We use this in resolve because +// we synthesize 'path segments' which don't have the rest of an AST or HIR +// PathSegment. +#[derive(Clone, Copy, Debug)] +pub struct Segment { + ident: Ident, + id: Option, +} + +impl Segment { + fn from_path(path: &Path) -> Vec { + path.segments.iter().map(|s| s.into()).collect() + } + + fn from_ident(ident: Ident) -> Segment { + Segment { + ident, + id: None, + } + } + + fn names_to_string(segments: &[Segment]) -> String { + names_to_string(&segments.iter() + .map(|seg| seg.ident) + .collect::>()) + } +} + +impl<'a> From<&'a ast::PathSegment> for Segment { + fn from(seg: &'a ast::PathSegment) -> Segment { + Segment { + ident: seg.ident, + id: Some(seg.id), + } + } +} + struct UsePlacementFinder { target_module: NodeId, span: Option, @@ -780,7 +818,7 @@ fn visit_fn(&mut self, self.label_ribs.push(Rib::new(rib_kind)); // Add each argument to the rib. - let mut bindings_list = FxHashMap(); + let mut bindings_list = FxHashMap::default(); for argument in &declaration.inputs { self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list); @@ -930,7 +968,7 @@ struct Rib<'a> { impl<'a> Rib<'a> { fn new(kind: RibKind<'a>) -> Rib<'a> { Rib { - bindings: FxHashMap(), + bindings: Default::default(), kind, } } @@ -1053,11 +1091,11 @@ fn new(parent: Option>, parent, kind, normal_ancestor_id, - resolutions: RefCell::new(FxHashMap()), + resolutions: Default::default(), legacy_macro_resolutions: RefCell::new(Vec::new()), macro_resolutions: RefCell::new(Vec::new()), builtin_attrs: RefCell::new(Vec::new()), - unresolved_invocations: RefCell::new(FxHashSet()), + unresolved_invocations: Default::default(), no_implicit_prelude: false, glob_importers: RefCell::new(Vec::new()), globs: RefCell::new(Vec::new()), @@ -1234,7 +1272,7 @@ fn is_extern_crate(&self) -> bool { match self.kind { NameBindingKind::Import { directive: &ImportDirective { - subclass: ImportDirectiveSubclass::ExternCrate(_), .. + subclass: ImportDirectiveSubclass::ExternCrate { .. }, .. }, .. } => true, _ => false, @@ -1248,15 +1286,6 @@ fn is_import(&self) -> bool { } } - fn is_renamed_extern_crate(&self) -> bool { - if let NameBindingKind::Import { directive, ..} = self.kind { - if let ImportDirectiveSubclass::ExternCrate(Some(_)) = directive.subclass { - return true; - } - } - false - } - fn is_glob_import(&self) -> bool { match self.kind { NameBindingKind::Import { directive, .. } => directive.is_glob(), @@ -1315,13 +1344,14 @@ fn may_appear_after(&self, invoc_parent_expansion: Mark, binding: &NameBinding) /// /// All other types are defined somewhere and possibly imported, but the primitive ones need /// special handling, since they have no place of origin. +#[derive(Default)] struct PrimitiveTypeTable { primitive_types: FxHashMap, } impl PrimitiveTypeTable { fn new() -> PrimitiveTypeTable { - let mut table = PrimitiveTypeTable { primitive_types: FxHashMap() }; + let mut table = PrimitiveTypeTable::default(); table.intern("bool", Bool); table.intern("char", Char); @@ -1348,6 +1378,12 @@ fn intern(&mut self, string: &str, primitive_type: PrimTy) { } } +#[derive(Default, Clone)] +pub struct ExternPreludeEntry<'a> { + extern_crate_item: Option<&'a NameBinding<'a>>, + pub introduced_by_item: bool, +} + /// The main resolver class. /// /// This is the visitor that walks the whole crate. @@ -1360,7 +1396,7 @@ pub struct Resolver<'a, 'b: 'a> { graph_root: Module<'a>, prelude: Option>, - pub extern_prelude: FxHashSet, + pub extern_prelude: FxHashMap>, /// n.b. This is used only for better diagnostics, not name resolution itself. has_self: FxHashSet, @@ -1482,6 +1518,7 @@ pub struct Resolver<'a, 'b: 'a> { } /// Nothing really interesting here, it just provides memory for the rest of the crate. +#[derive(Default)] pub struct ResolverArenas<'a> { modules: arena::TypedArena>, local_modules: RefCell>>, @@ -1534,8 +1571,13 @@ fn parent(self, id: DefId) -> Option { /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that /// the resolver is no longer needed as all the relevant information is inline. impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> { - fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) { - self.resolve_hir_path_cb(path, is_value, + fn resolve_hir_path( + &mut self, + path: &ast::Path, + args: Option>, + is_value: bool, + ) -> hir::Path { + self.resolve_hir_path_cb(path, args, is_value, |resolver, span, error| resolve_error(resolver, span, error)) } @@ -1547,30 +1589,20 @@ fn resolve_str_path( args: Option>, is_value: bool ) -> hir::Path { - let mut segments = iter::once(keywords::CrateRoot.ident()) + let segments = iter::once(keywords::CrateRoot.ident()) .chain( crate_root.into_iter() .chain(components.iter().cloned()) .map(Ident::from_str) - ).map(hir::PathSegment::from_ident).collect::>(); + ).map(|i| self.new_ast_path_segment(i)).collect::>(); - if let Some(args) = args { - let ident = segments.last().unwrap().ident; - *segments.last_mut().unwrap() = hir::PathSegment { - ident, - args: Some(args), - infer_types: true, - }; - } - let mut path = hir::Path { + let path = ast::Path { span, - def: Def::Err, - segments: segments.into(), + segments, }; - self.resolve_hir_path(&mut path, is_value); - path + self.resolve_hir_path(&path, args, is_value) } fn get_resolution(&mut self, id: NodeId) -> Option { @@ -1596,23 +1628,27 @@ pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: b use std::iter; let mut errored = false; - let mut path = if path_str.starts_with("::") { - hir::Path { + let path = if path_str.starts_with("::") { + ast::Path { span, - def: Def::Err, - segments: iter::once(keywords::CrateRoot.ident()).chain({ - path_str.split("::").skip(1).map(Ident::from_str) - }).map(hir::PathSegment::from_ident).collect(), + segments: iter::once(keywords::CrateRoot.ident()) + .chain({ + path_str.split("::").skip(1).map(Ident::from_str) + }) + .map(|i| self.new_ast_path_segment(i)) + .collect(), } } else { - hir::Path { + ast::Path { span, - def: Def::Err, - segments: path_str.split("::").map(Ident::from_str) - .map(hir::PathSegment::from_ident).collect(), + segments: path_str + .split("::") + .map(Ident::from_str) + .map(|i| self.new_ast_path_segment(i)) + .collect(), } }; - self.resolve_hir_path_cb(&mut path, is_value, |_, _, _| errored = true); + let path = self.resolve_hir_path_cb(&path, None, is_value, |_, _, _| errored = true); if errored || path.def == Def::Err { Err(()) } else { @@ -1621,38 +1657,64 @@ pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: b } /// resolve_hir_path, but takes a callback in case there was an error - fn resolve_hir_path_cb(&mut self, path: &mut hir::Path, is_value: bool, error_callback: F) + fn resolve_hir_path_cb( + &mut self, + path: &ast::Path, + args: Option>, + is_value: bool, + error_callback: F, + ) -> hir::Path where F: for<'c, 'b> FnOnce(&'c mut Resolver, Span, ResolutionError<'b>) { 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| seg.ident).collect(); + let span = path.span; + let segments = &path.segments; + let path = Segment::from_path(&path); // FIXME (Manishearth): Intra doc links won't get warned of epoch changes - match self.resolve_path(None, &path, Some(namespace), true, span, CrateLint::No) { + let def = match self.resolve_path(None, &path, Some(namespace), true, span, CrateLint::No) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => - *def = module.def().unwrap(), + module.def().unwrap(), PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => - *def = path_res.base_def(), - PathResult::NonModule(..) => match self.resolve_path( - None, - &path, - None, - true, - span, - CrateLint::No, - ) { - PathResult::Failed(span, msg, _) => { + path_res.base_def(), + PathResult::NonModule(..) => { + if let PathResult::Failed(span, msg, _) = self.resolve_path( + None, + &path, + None, + true, + span, + CrateLint::No, + ) { error_callback(self, span, ResolutionError::FailedToResolve(&msg)); } - _ => {} - }, + Def::Err + } PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) | PathResult::Indeterminate => unreachable!(), PathResult::Failed(span, msg, _) => { error_callback(self, span, ResolutionError::FailedToResolve(&msg)); + Def::Err } + }; + + let mut segments: Vec<_> = segments.iter().map(|seg| { + let mut hir_seg = hir::PathSegment::from_ident(seg.ident); + hir_seg.def = Some(self.def_map.get(&seg.id).map_or(Def::Err, |p| p.base_def())); + hir_seg + }).collect(); + segments.last_mut().unwrap().args = args; + hir::Path { + span, + def, + segments: segments.into(), } } + + fn new_ast_path_segment(&self, ident: Ident) -> ast::PathSegment { + let mut seg = ast::PathSegment::from_ident(ident); + seg.id = self.session.next_node_id(); + seg + } } impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { @@ -1670,31 +1732,32 @@ pub fn new(session: &'a Session, no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"), ..ModuleData::new(None, root_module_kind, root_def_id, Mark::root(), krate.span) }); - let mut module_map = FxHashMap(); + let mut module_map = FxHashMap::default(); module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root); let mut definitions = Definitions::new(); DefCollector::new(&mut definitions, Mark::root()) .collect_root(crate_name, session.local_crate_disambiguator()); - let mut extern_prelude: FxHashSet = - session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect(); + let mut extern_prelude: FxHashMap = + session.opts.externs.iter().map(|kv| (Ident::from_str(kv.0), Default::default())) + .collect(); if !attr::contains_name(&krate.attrs, "no_core") { - extern_prelude.insert(Symbol::intern("core")); + extern_prelude.insert(Ident::from_str("core"), Default::default()); if !attr::contains_name(&krate.attrs, "no_std") { - extern_prelude.insert(Symbol::intern("std")); + extern_prelude.insert(Ident::from_str("std"), Default::default()); if session.rust_2018() { - extern_prelude.insert(Symbol::intern("meta")); + extern_prelude.insert(Ident::from_str("meta"), Default::default()); } } } - let mut invocations = FxHashMap(); + let mut invocations = FxHashMap::default(); invocations.insert(Mark::root(), arenas.alloc_invocation_data(InvocationData::root(graph_root))); - let mut macro_defs = FxHashMap(); + let mut macro_defs = FxHashMap::default(); macro_defs.insert(Mark::root(), root_def_id); Resolver { @@ -1710,8 +1773,8 @@ pub fn new(session: &'a Session, prelude: None, extern_prelude, - has_self: FxHashSet(), - field_names: FxHashMap(), + has_self: FxHashSet::default(), + field_names: FxHashMap::default(), determined_imports: Vec::new(), indeterminate_imports: Vec::new(), @@ -1734,21 +1797,21 @@ pub fn new(session: &'a Session, import_map: NodeMap(), freevars: NodeMap(), freevars_seen: NodeMap(), - export_map: FxHashMap(), + export_map: FxHashMap::default(), trait_map: NodeMap(), module_map, block_map: NodeMap(), - extern_module_map: FxHashMap(), - binding_parent_modules: FxHashMap(), + extern_module_map: FxHashMap::default(), + binding_parent_modules: FxHashMap::default(), make_glob_map: make_glob_map == MakeGlobMap::Yes, glob_map: NodeMap(), - used_imports: FxHashSet(), + used_imports: FxHashSet::default(), maybe_unused_trait_imports: NodeSet(), maybe_unused_extern_crates: Vec::new(), - unused_labels: FxHashMap(), + unused_labels: FxHashMap::default(), privacy_errors: Vec::new(), ambiguity_errors: Vec::new(), @@ -1764,35 +1827,27 @@ pub fn new(session: &'a Session, }), crate_loader, - macro_names: FxHashSet(), - builtin_macros: FxHashMap(), - macro_use_prelude: FxHashMap(), - all_macros: FxHashMap(), - macro_map: FxHashMap(), + macro_names: FxHashSet::default(), + builtin_macros: FxHashMap::default(), + macro_use_prelude: FxHashMap::default(), + all_macros: FxHashMap::default(), + macro_map: FxHashMap::default(), invocations, macro_defs, - local_macro_def_scopes: FxHashMap(), - name_already_seen: FxHashMap(), + local_macro_def_scopes: FxHashMap::default(), + name_already_seen: FxHashMap::default(), whitelisted_legacy_custom_derives: Vec::new(), potentially_unused_imports: Vec::new(), struct_constructors: DefIdMap(), found_unresolved_macro: false, - unused_macros: FxHashSet(), + unused_macros: FxHashSet::default(), current_type_ascription: Vec::new(), injected_crate: None, } } pub fn arenas() -> ResolverArenas<'a> { - ResolverArenas { - modules: arena::TypedArena::new(), - local_modules: RefCell::new(Vec::new()), - name_bindings: arena::TypedArena::new(), - import_directives: arena::TypedArena::new(), - name_resolutions: arena::TypedArena::new(), - invocation_data: arena::TypedArena::new(), - legacy_bindings: arena::TypedArena::new(), - } + Default::default() } /// Runs the function on each namespace. @@ -1980,15 +2035,10 @@ fn resolve_ident_in_lexical_scope(&mut self, } if !module.no_implicit_prelude { - // `record_used` means that we don't try to load crates during speculative resolution - if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) { - let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); - let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); - self.populate_module_if_necessary(&crate_root); - - let binding = (crate_root, ty::Visibility::Public, - ident.span, Mark::root()).to_name_binding(self.arenas); - return Some(LexicalScopeBinding::Item(binding)); + if ns == TypeNS { + if let Some(binding) = self.extern_prelude_get(ident, !record_used, false) { + return Some(LexicalScopeBinding::Item(binding)); + } } if ns == TypeNS && is_known_tool(ident.name) { let binding = (Def::ToolMod, ty::Visibility::Public, @@ -2351,7 +2401,7 @@ fn resolve_use_tree( span: prefix.span.to(use_tree.prefix.span), }; - if items.len() == 0 { + if items.is_empty() { // Resolve prefix of an import with empty braces (issue #28388). self.smart_resolve_path_with_crate_lint( id, @@ -2377,7 +2427,7 @@ fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters< match type_parameters { HasTypeParameters(generics, rib_kind) => { let mut function_type_rib = Rib::new(rib_kind); - let mut seen_bindings = FxHashMap(); + let mut seen_bindings = FxHashMap::default(); for param in &generics.params { match param.kind { GenericParamKind::Lifetime { .. } => {} @@ -2471,9 +2521,7 @@ fn with_optional_trait_ref(&mut self, opt_trait_ref: Option<&TraitRef>, f: 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.ident) - .collect(); + let path: Vec<_> = Segment::from_path(&trait_ref.path); let def = self.smart_resolve_path_fragment( trait_ref.ref_id, None, @@ -2645,7 +2693,7 @@ fn resolve_local(&mut self, local: &Local) { walk_list!(self, visit_expr, &local.init); // Resolve the pattern. - self.resolve_pattern(&local.pat, PatternSource::Let, &mut FxHashMap()); + self.resolve_pattern(&local.pat, PatternSource::Let, &mut FxHashMap::default()); } // build a map from pattern identifiers to binding-info's. @@ -2653,7 +2701,7 @@ fn resolve_local(&mut self, local: &Local) { // that expands into an or-pattern where one 'x' was from the // user and one 'x' came from the macro. fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap { - let mut binding_map = FxHashMap(); + let mut binding_map = FxHashMap::default(); pat.walk(&mut |pat| { if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node { @@ -2678,8 +2726,8 @@ fn check_consistent_bindings(&mut self, pats: &[P]) { return; } - let mut missing_vars = FxHashMap(); - let mut inconsistent_vars = FxHashMap(); + let mut missing_vars = FxHashMap::default(); + let mut inconsistent_vars = FxHashMap::default(); for (i, p) in pats.iter().enumerate() { let map_i = self.binding_mode_map(&p); @@ -2690,7 +2738,7 @@ fn check_consistent_bindings(&mut self, pats: &[P]) { let map_j = self.binding_mode_map(&q); for (&key, &binding_i) in &map_i { - if map_j.len() == 0 { // Account for missing bindings when + if map_j.is_empty() { // Account for missing bindings when let binding_error = missing_vars // map_j has none. .entry(key.name) .or_insert(BindingError { @@ -2743,7 +2791,7 @@ fn check_consistent_bindings(&mut self, pats: &[P]) { fn resolve_arm(&mut self, arm: &Arm) { self.ribs[ValueNS].push(Rib::new(NormalRibKind)); - let mut bindings_list = FxHashMap(); + let mut bindings_list = FxHashMap::default(); for pattern in &arm.pats { self.resolve_pattern(&pattern, PatternSource::Match, &mut bindings_list); } @@ -2751,9 +2799,8 @@ fn resolve_arm(&mut self, arm: &Arm) { // This has to happen *after* we determine which pat_idents are variants self.check_consistent_bindings(&arm.pats); - match arm.guard { - Some(ast::Guard::If(ref expr)) => self.visit_expr(expr), - _ => {} + if let Some(ast::Guard::If(ref expr)) = arm.guard { + self.visit_expr(expr) } self.visit_expr(&arm.body); @@ -2970,21 +3017,25 @@ fn smart_resolve_path_with_crate_lint( source: PathSource, crate_lint: CrateLint ) -> PathResolution { - let segments = &path.segments.iter() - .map(|seg| seg.ident) - .collect::>(); - self.smart_resolve_path_fragment(id, qself, segments, path.span, source, crate_lint) + self.smart_resolve_path_fragment( + id, + qself, + &Segment::from_path(path), + path.span, + source, + crate_lint, + ) } fn smart_resolve_path_fragment(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &[Segment], span: Span, source: PathSource, crate_lint: CrateLint) -> PathResolution { - let ident_span = path.last().map_or(span, |ident| ident.span); + let ident_span = path.last().map_or(span, |ident| 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 }; @@ -2993,18 +3044,18 @@ fn smart_resolve_path_fragment(&mut self, 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 item_str = path[path.len() - 1]; + let path_str = Segment::names_to_string(path); + let item_str = path.last().unwrap().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_span = path[path.len() - 1].span; + let item_span = path.last().unwrap().ident.span; let (mod_prefix, mod_str) = if path.len() == 1 { (String::new(), "this scope".to_string()) - } else if path.len() == 2 && path[0].name == keywords::CrateRoot.name() { + } else if path.len() == 2 && path[0].ident.name == keywords::CrateRoot.name() { (String::new(), "the crate root".to_string()) } else { let mod_path = &path[..path.len() - 1]; @@ -3014,7 +3065,7 @@ fn smart_resolve_path_fragment(&mut self, module.def(), _ => None, }.map_or(String::new(), |def| format!("{} ", def.kind_name())); - (mod_prefix, format!("`{}`", names_to_string(mod_path))) + (mod_prefix, format!("`{}`", Segment::names_to_string(mod_path))) }; (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str), format!("not found in {}", mod_str), @@ -3024,11 +3075,8 @@ fn smart_resolve_path_fragment(&mut self, let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code); // Emit help message for fake-self from other languages like `this`(javascript) - let fake_self: Vec = ["this", "my"].iter().map( - |s| Ident::from_str(*s) - ).collect(); - if fake_self.contains(&item_str) - && this.self_value_is_available(path[0].span, span) { + if ["this", "my"].contains(&&*item_str.as_str()) + && this.self_value_is_available(path[0].ident.span, span) { err.span_suggestion_with_applicability( span, "did you mean", @@ -3063,7 +3111,7 @@ fn smart_resolve_path_fragment(&mut self, } // Try to lookup the name in more relaxed fashion for better error reporting. - let ident = *path.last().unwrap(); + let ident = path.last().unwrap().ident; 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 = @@ -3090,7 +3138,7 @@ fn smart_resolve_path_fragment(&mut self, } 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].span, span); + let self_is_available = this.self_value_is_available(path[0].ident.span, span); match candidate { AssocSuggestion::Field => { err.span_suggestion_with_applicability( @@ -3325,7 +3373,7 @@ fn smart_resolve_path_fragment(&mut self, // 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().ident; let traits = self.get_traits_containing_item(item_name, ns); self.trait_map.insert(id, traits); } @@ -3368,7 +3416,7 @@ fn type_ascription_suggestion(&self, ); } break; - } else if snippet.trim().len() != 0 { + } else if !snippet.trim().is_empty() { debug!("tried to find type ascription `:` token, couldn't find it"); break; } @@ -3395,7 +3443,7 @@ fn self_value_is_available(&mut self, self_span: Span, path_span: Span) -> bool fn resolve_qpath_anywhere(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &[Segment], primary_ns: Namespace, span: Span, defer_to_typeck: bool, @@ -3417,10 +3465,10 @@ fn resolve_qpath_anywhere(&mut self, } } if primary_ns != MacroNS && - (self.macro_names.contains(&path[0].modern()) || - self.builtin_macros.get(&path[0].name).cloned() + (self.macro_names.contains(&path[0].ident.modern()) || + self.builtin_macros.get(&path[0].ident.name).cloned() .and_then(NameBinding::macro_kind) == Some(MacroKind::Bang) || - self.macro_use_prelude.get(&path[0].name).cloned() + self.macro_use_prelude.get(&path[0].ident.name).cloned() .and_then(NameBinding::macro_kind) == Some(MacroKind::Bang)) { // Return some dummy definition, it's enough for error reporting. return Some( @@ -3434,7 +3482,7 @@ fn resolve_qpath_anywhere(&mut self, fn resolve_qpath(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &[Segment], ns: Namespace, span: Span, global_by_default: bool, @@ -3524,8 +3572,8 @@ fn resolve_qpath(&mut self, 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]; + .contains_key(&path[0].ident.name) => { + let prim = self.primitive_type_table.primitive_types[&path[0].ident.name]; PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1) } PathResult::Module(ModuleOrUniformRoot::Module(module)) => @@ -3540,8 +3588,8 @@ fn resolve_qpath(&mut self, }; if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && - path[0].name != keywords::CrateRoot.name() && - path[0].name != keywords::DollarCrate.name() { + path[0].ident.name != keywords::CrateRoot.name() && + path[0].ident.name != keywords::DollarCrate.name() { let unqualified_result = { match self.resolve_path( None, @@ -3569,7 +3617,7 @@ fn resolve_qpath(&mut self, fn resolve_path( &mut self, base_module: Option>, - path: &[Ident], + path: &[Segment], opt_ns: Option, // `None` indicates a module path record_used: bool, path_span: Span, @@ -3583,7 +3631,7 @@ fn resolve_path( fn resolve_path_with_parent_scope( &mut self, base_module: Option>, - path: &[Ident], + path: &[Segment], opt_ns: Option, // `None` indicates a module path parent_scope: &ParentScope<'a>, record_used: bool, @@ -3605,8 +3653,9 @@ fn resolve_path_with_parent_scope( crate_lint, ); - for (i, &ident) in path.iter().enumerate() { + for (i, &Segment { ident, id }) 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 }; let name = ident.name; @@ -3666,7 +3715,7 @@ fn resolve_path_with_parent_scope( } else { format!("`{}`", name) }; - let msg = if i == 1 && path[0].name == keywords::CrateRoot.name() { + let msg = if i == 1 && path[0].ident.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) @@ -3706,6 +3755,14 @@ fn resolve_path_with_parent_scope( let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def); if let Some(next_module) = binding.module() { module = Some(ModuleOrUniformRoot::Module(next_module)); + if record_used { + if let Some(id) = id { + if !self.def_map.contains_key(&id) { + assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id"); + self.record_def(id, PathResolution::new(def)); + } + } + } } else if def == Def::ToolMod && i + 1 != path.len() { let def = Def::NonMacroAttr(NonMacroAttrKind::Tool); return PathResult::NonModule(PathResolution::new(def)); @@ -3755,7 +3812,7 @@ fn resolve_path_with_parent_scope( } 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[i - 1].ident) }; return PathResult::Failed(ident.span, msg, is_last); } @@ -3773,7 +3830,7 @@ fn resolve_path_with_parent_scope( fn lint_if_path_starts_with_module( &self, crate_lint: CrateLint, - path: &[Ident], + path: &[Segment], path_span: Span, second_binding: Option<&NameBinding>, ) { @@ -3790,7 +3847,7 @@ fn lint_if_path_starts_with_module( }; let first_name = match path.get(0) { - Some(ident) => ident.name, + Some(ident) => ident.ident.name, None => return, }; @@ -3802,7 +3859,7 @@ fn lint_if_path_starts_with_module( match path.get(1) { // If this import looks like `crate::...` it's already good - Some(ident) if ident.name == keywords::Crate.name() => return, + Some(Segment { ident, .. }) if ident.name == keywords::Crate.name() => return, // Otherwise go below to see if it's an extern crate Some(_) => {} // If the path has length one (and it's `CrateRoot` most likely) @@ -3818,7 +3875,7 @@ fn lint_if_path_starts_with_module( if let NameBindingKind::Import { directive: d, .. } = binding.kind { // Careful: we still want to rewrite paths from // renamed extern crates. - if let ImportDirectiveSubclass::ExternCrate(None) = d.subclass { + if let ImportDirectiveSubclass::ExternCrate { source: None, .. } = d.subclass { return } } @@ -3930,7 +3987,7 @@ fn adjust_local_def(&mut self, } _ => {} } - return def; + def } fn lookup_assoc_candidate(&mut self, @@ -3995,7 +4052,7 @@ fn extract_node_id(t: &Ty) -> Option { } fn lookup_typo_candidate(&mut self, - path: &[Ident], + path: &[Segment], ns: Namespace, filter_fn: FilterFn, span: Span) @@ -4033,7 +4090,7 @@ fn lookup_typo_candidate(&mut self, } else { // Items from the prelude if !module.no_implicit_prelude { - names.extend(self.extern_prelude.iter().cloned()); + names.extend(self.extern_prelude.iter().map(|(ident, _)| ident.name)); if let Some(prelude) = self.prelude { add_module_candidates(prelude, &mut names); } @@ -4059,7 +4116,7 @@ fn lookup_typo_candidate(&mut self, } } - let name = path[path.len() - 1].name; + let name = path[path.len() - 1].ident.name; // Make sure error reporting is deterministic. names.sort_by_cached_key(|name| name.as_str()); match find_best_match_for_name(names.iter(), &name.as_str(), None) { @@ -4143,7 +4200,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) { self.visit_expr(subexpression); self.ribs[ValueNS].push(Rib::new(NormalRibKind)); - let mut bindings_list = FxHashMap(); + let mut bindings_list = FxHashMap::default(); for pat in pats { self.resolve_pattern(pat, PatternSource::IfLet, &mut bindings_list); } @@ -4168,7 +4225,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) { self.with_resolved_label(label, expr.id, |this| { this.visit_expr(subexpression); this.ribs[ValueNS].push(Rib::new(NormalRibKind)); - let mut bindings_list = FxHashMap(); + let mut bindings_list = FxHashMap::default(); for pat in pats { this.resolve_pattern(pat, PatternSource::WhileLet, &mut bindings_list); } @@ -4182,7 +4239,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) { ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => { self.visit_expr(subexpression); self.ribs[ValueNS].push(Rib::new(NormalRibKind)); - self.resolve_pattern(pattern, PatternSource::For, &mut FxHashMap()); + self.resolve_pattern(pattern, PatternSource::For, &mut FxHashMap::default()); self.resolve_labeled_block(label, expr.id, block); @@ -4235,7 +4292,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) { self.ribs[ValueNS].push(Rib::new(rib_kind)); self.label_ribs.push(Rib::new(rib_kind)); // Resolve arguments: - let mut bindings_list = FxHashMap(); + let mut bindings_list = FxHashMap::default(); for argument in &fn_decl.inputs { self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list); self.visit_ty(&argument.ty); @@ -4380,10 +4437,9 @@ fn lookup_import_candidates_from_module(&mut self, where FilterFn: Fn(Def) -> bool { let mut candidates = Vec::new(); - let mut worklist = Vec::new(); - let mut seen_modules = FxHashSet(); + let mut seen_modules = FxHashSet::default(); let not_local_module = crate_name != keywords::Crate.ident(); - worklist.push((start_module, Vec::::new(), not_local_module)); + let mut worklist = vec![(start_module, Vec::::new(), not_local_module)]; while let Some((in_module, path_segments, @@ -4470,33 +4526,22 @@ fn lookup_import_candidates(&mut self, -> Vec where FilterFn: Fn(Def) -> bool { - let mut suggestions = vec![]; - - suggestions.extend( - self.lookup_import_candidates_from_module( - lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn - ) - ); + let mut suggestions = self.lookup_import_candidates_from_module( + lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn); if self.session.rust_2018() { let extern_prelude_names = self.extern_prelude.clone(); - for &name in extern_prelude_names.iter() { - let ident = Ident::with_empty_ctxt(name); - match self.crate_loader.maybe_process_path_extern(name, ident.span) { - Some(crate_id) => { - let crate_root = self.get_module(DefId { - krate: crate_id, - index: CRATE_DEF_INDEX, - }); - self.populate_module_if_necessary(&crate_root); + for (ident, _) in extern_prelude_names.into_iter() { + if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name, + ident.span) { + let crate_root = self.get_module(DefId { + krate: crate_id, + index: CRATE_DEF_INDEX, + }); + self.populate_module_if_necessary(&crate_root); - suggestions.extend( - self.lookup_import_candidates_from_module( - lookup_name, namespace, crate_root, ident, &filter_fn - ) - ); - } - None => {} + suggestions.extend(self.lookup_import_candidates_from_module( + lookup_name, namespace, crate_root, ident, &filter_fn)); } } } @@ -4509,9 +4554,8 @@ fn find_module(&mut self, -> Option<(Module<'a>, ImportSuggestion)> { let mut result = None; - let mut worklist = Vec::new(); - let mut seen_modules = FxHashSet(); - worklist.push((self.graph_root, Vec::new())); + let mut seen_modules = FxHashSet::default(); + let mut worklist = vec![(self.graph_root, Vec::new())]; while let Some((in_module, path_segments)) = worklist.pop() { // abort if the module is already found @@ -4589,7 +4633,7 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility { ast::VisibilityKind::Restricted { ref path, id, .. } => { // Visibilities are resolved as global by default, add starting root segment. let segments = path.make_root().iter().chain(path.segments.iter()) - .map(|seg| seg.ident) + .map(|seg| Segment { ident: seg.ident, id: Some(seg.id) }) .collect::>(); let def = self.smart_resolve_path_fragment( id, @@ -4684,7 +4728,7 @@ fn report_ambiguity_error(&self, ident: Ident, b1: &NameBinding, b2: &NameBindin fn report_errors(&mut self, krate: &Crate) { self.report_with_use_injections(krate); - let mut reported_spans = FxHashSet(); + let mut reported_spans = FxHashSet::default(); for &(span_use, span_def) in &self.macro_expanded_macro_export_errors { let msg = "macro-expanded `macro_export` macros from the current crate \ @@ -4799,10 +4843,17 @@ fn report_conflict<'b>(&mut self, }; let cm = self.session.source_map(); - let rename_msg = "You can use `as` to change the binding name of the import"; - - if let (Ok(snippet), false) = (cm.span_to_snippet(binding.span), - binding.is_renamed_extern_crate()) { + let rename_msg = "you can use `as` to change the binding name of the import"; + + if let ( + Ok(snippet), + NameBindingKind::Import { directive, ..}, + _dummy @ false, + ) = ( + cm.span_to_snippet(binding.span), + binding.kind.clone(), + binding.span.is_dummy(), + ) { let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { format!("Other{}", name) } else { @@ -4811,13 +4862,30 @@ fn report_conflict<'b>(&mut self, err.span_suggestion_with_applicability( binding.span, - rename_msg, - if snippet.ends_with(';') { - format!("{} as {};", &snippet[..snippet.len() - 1], suggested_name) - } else { - format!("{} as {}", snippet, suggested_name) + &rename_msg, + match (&directive.subclass, snippet.as_ref()) { + (ImportDirectiveSubclass::SingleImport { .. }, "self") => + format!("self as {}", suggested_name), + (ImportDirectiveSubclass::SingleImport { source, .. }, _) => + format!( + "{} as {}{}", + &snippet[..((source.span.hi().0 - binding.span.lo().0) as usize)], + suggested_name, + if snippet.ends_with(";") { + ";" + } else { + "" + } + ), + (ImportDirectiveSubclass::ExternCrate { source, target, .. }, _) => + format!( + "extern crate {} as {};", + source.unwrap_or(target.name), + suggested_name, + ), + (_, _) => unreachable!(), }, - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); } else { err.span_label(binding.span, rename_msg); @@ -4827,14 +4895,43 @@ fn report_conflict<'b>(&mut self, err.emit(); self.name_already_seen.insert(name, span); } + + fn extern_prelude_get(&mut self, ident: Ident, speculative: bool, skip_feature_gate: bool) + -> Option<&'a NameBinding<'a>> { + self.extern_prelude.get(&ident.modern()).cloned().and_then(|entry| { + if let Some(binding) = entry.extern_crate_item { + if !speculative && !skip_feature_gate && entry.introduced_by_item && + !self.session.features_untracked().extern_crate_item_prelude { + emit_feature_err(&self.session.parse_sess, "extern_crate_item_prelude", + ident.span, GateIssue::Language, + "use of extern prelude names introduced \ + with `extern crate` items is unstable"); + } + Some(binding) + } else { + let crate_id = if !speculative { + self.crate_loader.process_path_extern(ident.name, ident.span) + } else if let Some(crate_id) = + self.crate_loader.maybe_process_path_extern(ident.name, ident.span) { + crate_id + } else { + return None; + }; + let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); + self.populate_module_if_necessary(&crate_root); + Some((crate_root, ty::Visibility::Public, ident.span, Mark::root()) + .to_name_binding(self.arenas)) + } + }) + } } -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: &[Segment], namespace: Namespace) -> bool { + namespace == TypeNS && path.len() == 1 && path[0].ident.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: &[Segment], namespace: Namespace) -> bool { + namespace == ValueNS && path.len() == 1 && path[0].ident.name == keywords::SelfValue.name() } fn names_to_string(idents: &[Ident]) -> String {