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;
}
}
+// 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<NodeId>,
+}
+
+impl Segment {
+ fn from_path(path: &Path) -> Vec<Segment> {
+ 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::<Vec<_>>())
+ }
+}
+
+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<Span>,
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);
impl<'a> Rib<'a> {
fn new(kind: RibKind<'a>) -> Rib<'a> {
Rib {
- bindings: FxHashMap(),
+ bindings: Default::default(),
kind,
}
}
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()),
match self.kind {
NameBindingKind::Import {
directive: &ImportDirective {
- subclass: ImportDirectiveSubclass::ExternCrate(_), ..
+ subclass: ImportDirectiveSubclass::ExternCrate { .. }, ..
}, ..
} => true,
_ => false,
}
}
- 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(),
///
/// 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<Name, PrimTy>,
}
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);
}
}
+#[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.
graph_root: Module<'a>,
prelude: Option<Module<'a>>,
- pub extern_prelude: FxHashSet<Name>,
+ pub extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
/// n.b. This is used only for better diagnostics, not name resolution itself.
has_self: FxHashSet<DefId>,
}
/// Nothing really interesting here, it just provides memory for the rest of the crate.
+#[derive(Default)]
pub struct ResolverArenas<'a> {
modules: arena::TypedArena<ModuleData<'a>>,
local_modules: RefCell<Vec<Module<'a>>>,
/// 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<P<hir::GenericArgs>>,
+ is_value: bool,
+ ) -> hir::Path {
+ self.resolve_hir_path_cb(path, args, is_value,
|resolver, span, error| resolve_error(resolver, span, error))
}
args: Option<P<hir::GenericArgs>>,
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::<Vec<_>>();
+ ).map(|i| self.new_ast_path_segment(i)).collect::<Vec<_>>();
- 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<PathResolution> {
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 {
}
/// resolve_hir_path, but takes a callback in case there was an error
- fn resolve_hir_path_cb<F>(&mut self, path: &mut hir::Path, is_value: bool, error_callback: F)
+ fn resolve_hir_path_cb<F>(
+ &mut self,
+ path: &ast::Path,
+ args: Option<P<hir::GenericArgs>>,
+ 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> {
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<Name> =
- session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect();
+ let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry> =
+ 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 {
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(),
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(),
}),
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.
}
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,
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,
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 { .. } => {}
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,
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.
// 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 {
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);
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 {
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);
}
// 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);
source: PathSource,
crate_lint: CrateLint
) -> PathResolution {
- let segments = &path.segments.iter()
- .map(|seg| seg.ident)
- .collect::<Vec<_>>();
- 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 };
let report_errors = |this: &mut Self, def: Option<Def>| {
// 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];
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),
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<Ident> = ["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",
}
// 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 =
}
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(
// or `<T>::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);
}
);
}
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;
}
fn resolve_qpath_anywhere(&mut self,
id: NodeId,
qself: Option<&QSelf>,
- path: &[Ident],
+ path: &[Segment],
primary_ns: Namespace,
span: Span,
defer_to_typeck: bool,
}
}
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(
fn resolve_qpath(&mut self,
id: NodeId,
qself: Option<&QSelf>,
- path: &[Ident],
+ path: &[Segment],
ns: Namespace,
span: Span,
global_by_default: bool,
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)) =>
};
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,
fn resolve_path(
&mut self,
base_module: Option<ModuleOrUniformRoot<'a>>,
- path: &[Ident],
+ path: &[Segment],
opt_ns: Option<Namespace>, // `None` indicates a module path
record_used: bool,
path_span: Span,
fn resolve_path_with_parent_scope(
&mut self,
base_module: Option<ModuleOrUniformRoot<'a>>,
- path: &[Ident],
+ path: &[Segment],
opt_ns: Option<Namespace>, // `None` indicates a module path
parent_scope: &ParentScope<'a>,
record_used: bool,
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;
} 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)
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));
} 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);
}
fn lint_if_path_starts_with_module(
&self,
crate_lint: CrateLint,
- path: &[Ident],
+ path: &[Segment],
path_span: Span,
second_binding: Option<&NameBinding>,
) {
};
let first_name = match path.get(0) {
- Some(ident) => ident.name,
+ Some(ident) => ident.ident.name,
None => return,
};
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)
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
}
}
}
_ => {}
}
- return def;
+ def
}
fn lookup_assoc_candidate<FilterFn>(&mut self,
}
fn lookup_typo_candidate<FilterFn>(&mut self,
- path: &[Ident],
+ path: &[Segment],
ns: Namespace,
filter_fn: FilterFn,
span: Span)
} 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);
}
}
}
- 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) {
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);
}
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);
}
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);
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);
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::<ast::PathSegment>::new(), not_local_module));
+ let mut worklist = vec![(start_module, Vec::<ast::PathSegment>::new(), not_local_module)];
while let Some((in_module,
path_segments,
-> Vec<ImportSuggestion>
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));
}
}
}
-> 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
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::<Vec<_>>();
let def = self.smart_resolve_path_fragment(
id,
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 \
};
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 {
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);
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 {