mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
resolve: Move some more code around
Move methods logically belonging to build-reduced-graph into `impl BuildReducedGraphVisitor` and `build_reduced_graph.rs` Move types mostly specific to late resolution closer to the late resolution visitor
This commit is contained in:
parent
9c86ce76e5
commit
f360d795f1
@ -3,13 +3,13 @@
|
||||
//! Here we build the "reduced graph": the graph of the module tree without
|
||||
//! any imports resolved.
|
||||
|
||||
use crate::macros::{InvocationData, LegacyScope};
|
||||
use crate::macros::{InvocationData, LegacyBinding, LegacyScope};
|
||||
use crate::resolve_imports::ImportDirective;
|
||||
use crate::resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
|
||||
use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
|
||||
use crate::{ModuleOrUniformRoot, ParentScope, PerNS, Resolver, ResolverArenas, ExternPreludeEntry};
|
||||
use crate::Namespace::{self, TypeNS, ValueNS, MacroNS};
|
||||
use crate::{ResolutionError, Determinacy};
|
||||
use crate::{ResolutionError, Determinacy, PathResult, CrateLint};
|
||||
|
||||
use rustc::bug;
|
||||
use rustc::hir::def::{self, *};
|
||||
@ -29,11 +29,11 @@ use syntax::attr;
|
||||
|
||||
use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
|
||||
use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant};
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension};
|
||||
use syntax::ext::hygiene::ExpnId;
|
||||
use syntax::feature_gate::is_builtin_attr;
|
||||
use syntax::parse::token::{self, Token};
|
||||
use syntax::span_err;
|
||||
use syntax::{span_err, struct_span_err};
|
||||
use syntax::symbol::{kw, sym};
|
||||
use syntax::visit::{self, Visitor};
|
||||
|
||||
@ -93,14 +93,195 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Name>) {
|
||||
if !field_names.is_empty() {
|
||||
self.field_names.insert(def_id, field_names);
|
||||
pub fn get_module(&mut self, def_id: DefId) -> Module<'a> {
|
||||
if def_id.krate == LOCAL_CRATE {
|
||||
return self.module_map[&def_id]
|
||||
}
|
||||
|
||||
let macros_only = self.cstore.dep_kind_untracked(def_id.krate).macros_only();
|
||||
if let Some(&module) = self.extern_module_map.get(&(def_id, macros_only)) {
|
||||
return module;
|
||||
}
|
||||
|
||||
let (name, parent) = if def_id.index == CRATE_DEF_INDEX {
|
||||
(self.cstore.crate_name_untracked(def_id.krate).as_interned_str(), None)
|
||||
} else {
|
||||
let def_key = self.cstore.def_key(def_id);
|
||||
(def_key.disambiguated_data.data.get_opt_name().unwrap(),
|
||||
Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })))
|
||||
};
|
||||
|
||||
let kind = ModuleKind::Def(DefKind::Mod, def_id, name.as_symbol());
|
||||
let module = self.arenas.alloc_module(ModuleData::new(
|
||||
parent, kind, def_id, ExpnId::root(), DUMMY_SP
|
||||
));
|
||||
self.extern_module_map.insert((def_id, macros_only), module);
|
||||
module
|
||||
}
|
||||
|
||||
pub fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
|
||||
let def_id = match self.macro_defs.get(&expn_id) {
|
||||
Some(def_id) => *def_id,
|
||||
None => return self.graph_root,
|
||||
};
|
||||
if let Some(id) = self.definitions.as_local_node_id(def_id) {
|
||||
self.local_macro_def_scopes[&id]
|
||||
} else if self.is_builtin_macro(Some(def_id)) {
|
||||
self.injected_crate.unwrap_or(self.graph_root)
|
||||
} else {
|
||||
let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
|
||||
self.get_module(module_def_id)
|
||||
}
|
||||
}
|
||||
|
||||
crate fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
|
||||
match res {
|
||||
Res::Def(DefKind::Macro(..), def_id) => self.get_macro_by_def_id(def_id),
|
||||
Res::NonMacroAttr(attr_kind) =>
|
||||
Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
crate fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option<Lrc<SyntaxExtension>> {
|
||||
if let Some(ext) = self.macro_map.get(&def_id) {
|
||||
return Some(ext.clone());
|
||||
}
|
||||
|
||||
let macro_def = match self.cstore.load_macro_untracked(def_id, &self.session) {
|
||||
LoadedMacro::MacroDef(macro_def) => macro_def,
|
||||
LoadedMacro::ProcMacro(ext) => return Some(ext),
|
||||
};
|
||||
|
||||
let ext = self.compile_macro(¯o_def, self.cstore.crate_edition_untracked(def_id.krate));
|
||||
self.macro_map.insert(def_id, ext.clone());
|
||||
Some(ext)
|
||||
}
|
||||
|
||||
/// Ensures that the reduced graph rooted at the given external module
|
||||
/// is built, building it if it is not.
|
||||
pub fn populate_module_if_necessary(&mut self, module: Module<'a>) {
|
||||
if module.populated.get() { return }
|
||||
let def_id = module.def_id().unwrap();
|
||||
for child in self.cstore.item_children_untracked(def_id, self.session) {
|
||||
let child = child.map_id(|_| panic!("unexpected id"));
|
||||
BuildReducedGraphVisitor { parent_scope: self.dummy_parent_scope(), r: self }
|
||||
.build_reduced_graph_for_external_crate_res(module, child);
|
||||
}
|
||||
module.populated.set(true)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
pub struct BuildReducedGraphVisitor<'a, 'b> {
|
||||
pub r: &'b mut Resolver<'a>,
|
||||
pub parent_scope: ParentScope<'a>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
||||
fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
|
||||
let parent_scope = &self.parent_scope;
|
||||
match vis.node {
|
||||
ast::VisibilityKind::Public => ty::Visibility::Public,
|
||||
ast::VisibilityKind::Crate(..) => {
|
||||
ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
|
||||
}
|
||||
ast::VisibilityKind::Inherited => {
|
||||
ty::Visibility::Restricted(parent_scope.module.normal_ancestor_id)
|
||||
}
|
||||
ast::VisibilityKind::Restricted { ref path, id, .. } => {
|
||||
// For visibilities we are not ready to provide correct implementation of "uniform
|
||||
// paths" right now, so on 2018 edition we only allow module-relative paths for now.
|
||||
// On 2015 edition visibilities are resolved as crate-relative by default,
|
||||
// so we are prepending a root segment if necessary.
|
||||
let ident = path.segments.get(0).expect("empty path in visibility").ident;
|
||||
let crate_root = if ident.is_path_segment_keyword() {
|
||||
None
|
||||
} else if ident.span.rust_2018() {
|
||||
let msg = "relative paths are not supported in visibilities on 2018 edition";
|
||||
self.r.session.struct_span_err(ident.span, msg)
|
||||
.span_suggestion(
|
||||
path.span,
|
||||
"try",
|
||||
format!("crate::{}", path),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
return ty::Visibility::Public;
|
||||
} else {
|
||||
let ctxt = ident.span.ctxt();
|
||||
Some(Segment::from_ident(Ident::new(
|
||||
kw::PathRoot, path.span.shrink_to_lo().with_ctxt(ctxt)
|
||||
)))
|
||||
};
|
||||
|
||||
let segments = crate_root.into_iter()
|
||||
.chain(path.segments.iter().map(|seg| seg.into())).collect::<Vec<_>>();
|
||||
let expected_found_error = |this: &Self, res: Res| {
|
||||
let path_str = Segment::names_to_string(&segments);
|
||||
struct_span_err!(this.r.session, path.span, E0577,
|
||||
"expected module, found {} `{}`", res.descr(), path_str)
|
||||
.span_label(path.span, "not a module").emit();
|
||||
};
|
||||
match self.r.resolve_path(
|
||||
&segments,
|
||||
Some(TypeNS),
|
||||
parent_scope,
|
||||
true,
|
||||
path.span,
|
||||
CrateLint::SimplePath(id),
|
||||
) {
|
||||
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
|
||||
let res = module.res().expect("visibility resolved to unnamed block");
|
||||
self.r.record_partial_res(id, PartialRes::new(res));
|
||||
if module.is_normal() {
|
||||
if res == Res::Err {
|
||||
ty::Visibility::Public
|
||||
} else {
|
||||
let vis = ty::Visibility::Restricted(res.def_id());
|
||||
if self.r.is_accessible_from(vis, parent_scope.module) {
|
||||
vis
|
||||
} else {
|
||||
let msg =
|
||||
"visibilities can only be restricted to ancestor modules";
|
||||
self.r.session.span_err(path.span, msg);
|
||||
ty::Visibility::Public
|
||||
}
|
||||
}
|
||||
} else {
|
||||
expected_found_error(self, res);
|
||||
ty::Visibility::Public
|
||||
}
|
||||
}
|
||||
PathResult::Module(..) => {
|
||||
self.r.session.span_err(path.span, "visibility must resolve to a module");
|
||||
ty::Visibility::Public
|
||||
}
|
||||
PathResult::NonModule(partial_res) => {
|
||||
expected_found_error(self, partial_res.base_res());
|
||||
ty::Visibility::Public
|
||||
}
|
||||
PathResult::Failed { span, label, suggestion, .. } => {
|
||||
self.r.report_error(
|
||||
span, ResolutionError::FailedToResolve { label, suggestion }
|
||||
);
|
||||
ty::Visibility::Public
|
||||
}
|
||||
PathResult::Indeterminate => {
|
||||
span_err!(self.r.session, path.span, E0578,
|
||||
"cannot determine resolution for the visibility");
|
||||
ty::Visibility::Public
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Name>) {
|
||||
if !field_names.is_empty() {
|
||||
self.r.field_names.insert(def_id, field_names);
|
||||
}
|
||||
}
|
||||
|
||||
fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
|
||||
// If any statements are items, we need to create an anonymous module
|
||||
block.stmts.iter().any(|statement| match statement.node {
|
||||
@ -109,6 +290,54 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
})
|
||||
}
|
||||
|
||||
// Add an import directive to the current module.
|
||||
fn add_import_directive(
|
||||
&mut self,
|
||||
module_path: Vec<Segment>,
|
||||
subclass: ImportDirectiveSubclass<'a>,
|
||||
span: Span,
|
||||
id: NodeId,
|
||||
item: &ast::Item,
|
||||
root_span: Span,
|
||||
root_id: NodeId,
|
||||
vis: ty::Visibility,
|
||||
) {
|
||||
let parent_scope = &self.parent_scope;
|
||||
let current_module = parent_scope.module;
|
||||
let directive = self.r.arenas.alloc_import_directive(ImportDirective {
|
||||
parent_scope: parent_scope.clone(),
|
||||
module_path,
|
||||
imported_module: Cell::new(None),
|
||||
subclass,
|
||||
span,
|
||||
id,
|
||||
use_span: item.span,
|
||||
use_span_with_attributes: item.span_with_attributes(),
|
||||
has_attributes: !item.attrs.is_empty(),
|
||||
root_span,
|
||||
root_id,
|
||||
vis: Cell::new(vis),
|
||||
used: Cell::new(false),
|
||||
});
|
||||
|
||||
debug!("add_import_directive({:?})", directive);
|
||||
|
||||
self.r.indeterminate_imports.push(directive);
|
||||
match directive.subclass {
|
||||
SingleImport { target, type_ns_only, .. } => {
|
||||
self.r.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
|
||||
let mut resolution = this.resolution(current_module, target, ns).borrow_mut();
|
||||
resolution.add_single_import(directive);
|
||||
});
|
||||
}
|
||||
// We don't add prelude imports to the globs since they only affect lexical scopes,
|
||||
// which are not relevant to import resolution.
|
||||
GlobImport { is_prelude: true, .. } => {}
|
||||
GlobImport { .. } => current_module.globs.borrow_mut().push(directive),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_reduced_graph_for_use_tree(
|
||||
&mut self,
|
||||
// This particular use tree
|
||||
@ -117,7 +346,6 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
parent_prefix: &[Segment],
|
||||
nested: bool,
|
||||
// The whole `use` item
|
||||
parent_scope: &ParentScope<'a>,
|
||||
item: &Item,
|
||||
vis: ty::Visibility,
|
||||
root_span: Span,
|
||||
@ -250,7 +478,6 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
root_span,
|
||||
item.id,
|
||||
vis,
|
||||
parent_scope.clone(),
|
||||
);
|
||||
}
|
||||
ast::UseTreeKind::Glob => {
|
||||
@ -267,7 +494,6 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
root_span,
|
||||
item.id,
|
||||
vis,
|
||||
parent_scope.clone(),
|
||||
);
|
||||
}
|
||||
ast::UseTreeKind::Nested(ref items) => {
|
||||
@ -298,7 +524,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
// This particular use tree
|
||||
tree, id, &prefix, true,
|
||||
// The whole `use` item
|
||||
parent_scope, item, vis, root_span,
|
||||
item, vis, root_span,
|
||||
);
|
||||
}
|
||||
|
||||
@ -322,7 +548,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
// This particular use tree
|
||||
&tree, id, &prefix, true,
|
||||
// The whole `use` item
|
||||
parent_scope, item, ty::Visibility::Invisible, root_span,
|
||||
item, ty::Visibility::Invisible, root_span,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -331,12 +557,12 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
|
||||
/// Constructs the reduced graph for one item.
|
||||
fn build_reduced_graph_for_item(&mut self, item: &Item) {
|
||||
let parent_scope = &self.parent_scope.clone();
|
||||
let parent_scope = &self.parent_scope;
|
||||
let parent = parent_scope.module;
|
||||
let expansion = parent_scope.expansion;
|
||||
let ident = item.ident.gensym_if_underscore();
|
||||
let sp = item.span;
|
||||
let vis = self.r.resolve_visibility(&item.vis, parent_scope);
|
||||
let vis = self.resolve_visibility(&item.vis);
|
||||
|
||||
match item.node {
|
||||
ItemKind::Use(ref use_tree) => {
|
||||
@ -344,7 +570,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
// This particular use tree
|
||||
use_tree, item.id, &[], false,
|
||||
// The whole `use` item
|
||||
parent_scope, item, vis, use_tree.span,
|
||||
item, vis, use_tree.span,
|
||||
);
|
||||
}
|
||||
|
||||
@ -376,13 +602,13 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
}
|
||||
}
|
||||
|
||||
let used = self.process_legacy_macro_imports(item, module, parent_scope);
|
||||
let used = self.process_legacy_macro_imports(item, module);
|
||||
let binding =
|
||||
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
|
||||
let directive = self.r.arenas.alloc_import_directive(ImportDirective {
|
||||
root_id: item.id,
|
||||
id: item.id,
|
||||
parent_scope: parent_scope.clone(),
|
||||
parent_scope: self.parent_scope.clone(),
|
||||
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
|
||||
subclass: ImportDirectiveSubclass::ExternCrate {
|
||||
source: orig_name,
|
||||
@ -459,7 +685,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
|
||||
// Functions introducing procedural macros reserve a slot
|
||||
// in the macro namespace as well (see #52225).
|
||||
self.r.define_macro(item, parent_scope);
|
||||
self.define_macro(item);
|
||||
}
|
||||
|
||||
// These items live in the type namespace.
|
||||
@ -515,14 +741,14 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
|
||||
// Record field names for error reporting.
|
||||
let field_names = struct_def.fields().iter().filter_map(|field| {
|
||||
let field_vis = self.r.resolve_visibility(&field.vis, parent_scope);
|
||||
let field_vis = self.resolve_visibility(&field.vis);
|
||||
if ctor_vis.is_at_least(field_vis, &*self.r) {
|
||||
ctor_vis = field_vis;
|
||||
}
|
||||
field.ident.map(|ident| ident.name)
|
||||
}).collect();
|
||||
let item_def_id = self.r.definitions.local_def_id(item.id);
|
||||
self.r.insert_field_names(item_def_id, field_names);
|
||||
self.insert_field_names(item_def_id, field_names);
|
||||
|
||||
// If this is a tuple or unit struct, define a name
|
||||
// in the value namespace as well.
|
||||
@ -542,14 +768,18 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
|
||||
// Record field names for error reporting.
|
||||
let field_names = vdata.fields().iter().filter_map(|field| {
|
||||
self.r.resolve_visibility(&field.vis, parent_scope);
|
||||
self.resolve_visibility(&field.vis);
|
||||
field.ident.map(|ident| ident.name)
|
||||
}).collect();
|
||||
let item_def_id = self.r.definitions.local_def_id(item.id);
|
||||
self.r.insert_field_names(item_def_id, field_names);
|
||||
self.insert_field_names(item_def_id, field_names);
|
||||
}
|
||||
|
||||
ItemKind::Impl(..) => {}
|
||||
ItemKind::Impl(.., ref impl_items) => {
|
||||
for impl_item in impl_items {
|
||||
self.resolve_visibility(&impl_item.vis);
|
||||
}
|
||||
}
|
||||
|
||||
ItemKind::Trait(..) => {
|
||||
let def_id = self.r.definitions.local_def_id(item.id);
|
||||
@ -619,7 +849,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
};
|
||||
let parent = self.parent_scope.module;
|
||||
let expansion = self.parent_scope.expansion;
|
||||
let vis = self.r.resolve_visibility(&item.vis, &self.parent_scope);
|
||||
let vis = self.resolve_visibility(&item.vis);
|
||||
self.r.define(parent, item.ident, ns, (res, vis, item.span, expansion));
|
||||
}
|
||||
|
||||
@ -636,9 +866,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
self.parent_scope.module = module; // Descend into the block.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Resolver<'a> {
|
||||
/// Builds the reduced graph for a single item in an external crate.
|
||||
fn build_reduced_graph_for_external_crate_res(
|
||||
&mut self,
|
||||
@ -654,12 +882,12 @@ impl<'a> Resolver<'a> {
|
||||
match res {
|
||||
Res::Def(kind @ DefKind::Mod, def_id)
|
||||
| Res::Def(kind @ DefKind::Enum, def_id) => {
|
||||
let module = self.new_module(parent,
|
||||
let module = self.r.new_module(parent,
|
||||
ModuleKind::Def(kind, def_id, ident.name),
|
||||
def_id,
|
||||
expansion,
|
||||
span);
|
||||
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
|
||||
self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
|
||||
}
|
||||
Res::Def(DefKind::Variant, _)
|
||||
| Res::Def(DefKind::TyAlias, _)
|
||||
@ -668,140 +896,61 @@ impl<'a> Resolver<'a> {
|
||||
| Res::Def(DefKind::TraitAlias, _)
|
||||
| Res::PrimTy(..)
|
||||
| Res::ToolMod => {
|
||||
self.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
|
||||
self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
|
||||
}
|
||||
Res::Def(DefKind::Fn, _)
|
||||
| Res::Def(DefKind::Static, _)
|
||||
| Res::Def(DefKind::Const, _)
|
||||
| Res::Def(DefKind::Ctor(CtorOf::Variant, ..), _) => {
|
||||
self.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));
|
||||
self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));
|
||||
}
|
||||
Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => {
|
||||
self.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));
|
||||
self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));
|
||||
|
||||
if let Some(struct_def_id) =
|
||||
self.cstore.def_key(def_id).parent
|
||||
self.r.cstore.def_key(def_id).parent
|
||||
.map(|index| DefId { krate: def_id.krate, index: index }) {
|
||||
self.struct_constructors.insert(struct_def_id, (res, vis));
|
||||
self.r.struct_constructors.insert(struct_def_id, (res, vis));
|
||||
}
|
||||
}
|
||||
Res::Def(DefKind::Trait, def_id) => {
|
||||
let module_kind = ModuleKind::Def(DefKind::Trait, def_id, ident.name);
|
||||
let module = self.new_module(parent,
|
||||
let module = self.r.new_module(parent,
|
||||
module_kind,
|
||||
parent.normal_ancestor_id,
|
||||
expansion,
|
||||
span);
|
||||
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
|
||||
self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
|
||||
|
||||
for child in self.cstore.item_children_untracked(def_id, self.session) {
|
||||
for child in self.r.cstore.item_children_untracked(def_id, self.r.session) {
|
||||
let res = child.res.map_id(|_| panic!("unexpected id"));
|
||||
let ns = if let Res::Def(DefKind::AssocTy, _) = res {
|
||||
TypeNS
|
||||
} else { ValueNS };
|
||||
self.define(module, child.ident, ns,
|
||||
self.r.define(module, child.ident, ns,
|
||||
(res, ty::Visibility::Public, DUMMY_SP, expansion));
|
||||
|
||||
if self.cstore.associated_item_cloned_untracked(child.res.def_id())
|
||||
if self.r.cstore.associated_item_cloned_untracked(child.res.def_id())
|
||||
.method_has_self_argument {
|
||||
self.has_self.insert(res.def_id());
|
||||
self.r.has_self.insert(res.def_id());
|
||||
}
|
||||
}
|
||||
module.populated.set(true);
|
||||
}
|
||||
Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => {
|
||||
self.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
|
||||
self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
|
||||
|
||||
// Record field names for error reporting.
|
||||
let field_names = self.cstore.struct_field_names_untracked(def_id);
|
||||
let field_names = self.r.cstore.struct_field_names_untracked(def_id);
|
||||
self.insert_field_names(def_id, field_names);
|
||||
}
|
||||
Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => {
|
||||
self.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion));
|
||||
self.r.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion));
|
||||
}
|
||||
_ => bug!("unexpected resolution: {:?}", res)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_module(&mut self, def_id: DefId) -> Module<'a> {
|
||||
if def_id.krate == LOCAL_CRATE {
|
||||
return self.module_map[&def_id]
|
||||
}
|
||||
|
||||
let macros_only = self.cstore.dep_kind_untracked(def_id.krate).macros_only();
|
||||
if let Some(&module) = self.extern_module_map.get(&(def_id, macros_only)) {
|
||||
return module;
|
||||
}
|
||||
|
||||
let (name, parent) = if def_id.index == CRATE_DEF_INDEX {
|
||||
(self.cstore.crate_name_untracked(def_id.krate).as_interned_str(), None)
|
||||
} else {
|
||||
let def_key = self.cstore.def_key(def_id);
|
||||
(def_key.disambiguated_data.data.get_opt_name().unwrap(),
|
||||
Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })))
|
||||
};
|
||||
|
||||
let kind = ModuleKind::Def(DefKind::Mod, def_id, name.as_symbol());
|
||||
let module = self.arenas.alloc_module(ModuleData::new(
|
||||
parent, kind, def_id, ExpnId::root(), DUMMY_SP
|
||||
));
|
||||
self.extern_module_map.insert((def_id, macros_only), module);
|
||||
module
|
||||
}
|
||||
|
||||
pub fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
|
||||
let def_id = match self.macro_defs.get(&expn_id) {
|
||||
Some(def_id) => *def_id,
|
||||
None => return self.graph_root,
|
||||
};
|
||||
if let Some(id) = self.definitions.as_local_node_id(def_id) {
|
||||
self.local_macro_def_scopes[&id]
|
||||
} else if self.is_builtin_macro(Some(def_id)) {
|
||||
self.injected_crate.unwrap_or(self.graph_root)
|
||||
} else {
|
||||
let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
|
||||
self.get_module(module_def_id)
|
||||
}
|
||||
}
|
||||
|
||||
crate fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
|
||||
match res {
|
||||
Res::Def(DefKind::Macro(..), def_id) => self.get_macro_by_def_id(def_id),
|
||||
Res::NonMacroAttr(attr_kind) =>
|
||||
Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
crate fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option<Lrc<SyntaxExtension>> {
|
||||
if let Some(ext) = self.macro_map.get(&def_id) {
|
||||
return Some(ext.clone());
|
||||
}
|
||||
|
||||
let macro_def = match self.cstore.load_macro_untracked(def_id, &self.session) {
|
||||
LoadedMacro::MacroDef(macro_def) => macro_def,
|
||||
LoadedMacro::ProcMacro(ext) => return Some(ext),
|
||||
};
|
||||
|
||||
let ext = self.compile_macro(¯o_def, self.cstore.crate_edition_untracked(def_id.krate));
|
||||
self.macro_map.insert(def_id, ext.clone());
|
||||
Some(ext)
|
||||
}
|
||||
|
||||
/// Ensures that the reduced graph rooted at the given external module
|
||||
/// is built, building it if it is not.
|
||||
pub fn populate_module_if_necessary(&mut self, module: Module<'a>) {
|
||||
if module.populated.get() { return }
|
||||
let def_id = module.def_id().unwrap();
|
||||
for child in self.cstore.item_children_untracked(def_id, self.session) {
|
||||
let child = child.map_id(|_| panic!("unexpected id"));
|
||||
self.build_reduced_graph_for_external_crate_res(module, child);
|
||||
}
|
||||
module.populated.set(true)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
fn legacy_import_macro(&mut self,
|
||||
name: Name,
|
||||
binding: &'a NameBinding<'a>,
|
||||
@ -816,8 +965,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
}
|
||||
|
||||
/// Returns `true` if we should consider the underlying `extern crate` to be used.
|
||||
fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>,
|
||||
parent_scope: &ParentScope<'a>) -> bool {
|
||||
fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>) -> bool {
|
||||
let mut import_all = None;
|
||||
let mut single_imports = Vec::new();
|
||||
for attr in &item.attrs {
|
||||
@ -852,11 +1000,11 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
}
|
||||
}
|
||||
|
||||
let arenas = self.r.arenas;
|
||||
let macro_use_directive = |span| arenas.alloc_import_directive(ImportDirective {
|
||||
let macro_use_directive =
|
||||
|this: &Self, span| this.r.arenas.alloc_import_directive(ImportDirective {
|
||||
root_id: item.id,
|
||||
id: item.id,
|
||||
parent_scope: parent_scope.clone(),
|
||||
parent_scope: this.parent_scope.clone(),
|
||||
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
|
||||
subclass: ImportDirectiveSubclass::MacroUse,
|
||||
use_span_with_attributes: item.span_with_attributes(),
|
||||
@ -869,9 +1017,9 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
used: Cell::new(false),
|
||||
});
|
||||
|
||||
let allow_shadowing = parent_scope.expansion == ExpnId::root();
|
||||
let allow_shadowing = self.parent_scope.expansion == ExpnId::root();
|
||||
if let Some(span) = import_all {
|
||||
let directive = macro_use_directive(span);
|
||||
let directive = macro_use_directive(self, span);
|
||||
self.r.potentially_unused_imports.push(directive);
|
||||
module.for_each_child(|ident, ns, binding| if ns == MacroNS {
|
||||
let imported_binding = self.r.import(binding, directive);
|
||||
@ -883,12 +1031,12 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
ModuleOrUniformRoot::Module(module),
|
||||
ident,
|
||||
MacroNS,
|
||||
parent_scope,
|
||||
&self.parent_scope,
|
||||
false,
|
||||
ident.span,
|
||||
);
|
||||
if let Ok(binding) = result {
|
||||
let directive = macro_use_directive(ident.span);
|
||||
let directive = macro_use_directive(self, ident.span);
|
||||
self.r.potentially_unused_imports.push(directive);
|
||||
let imported_binding = self.r.import(binding, directive);
|
||||
self.legacy_import_macro(ident.name, imported_binding,
|
||||
@ -924,15 +1072,8 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BuildReducedGraphVisitor<'a, 'b> {
|
||||
pub r: &'a mut Resolver<'b>,
|
||||
pub parent_scope: ParentScope<'b>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
||||
fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
|
||||
fn visit_invoc(&mut self, id: ast::NodeId) -> &'a InvocationData<'a> {
|
||||
let invoc_id = id.placeholder_to_expn_id();
|
||||
|
||||
self.parent_scope.module.unresolved_invocations.borrow_mut().insert(invoc_id);
|
||||
@ -947,11 +1088,83 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
||||
|
||||
invocation_data
|
||||
}
|
||||
|
||||
fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
|
||||
if attr::contains_name(&item.attrs, sym::proc_macro) {
|
||||
return Some((MacroKind::Bang, item.ident, item.span));
|
||||
} else if attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
|
||||
return Some((MacroKind::Attr, item.ident, item.span));
|
||||
} else if let Some(attr) = attr::find_by_name(&item.attrs, sym::proc_macro_derive) {
|
||||
if let Some(nested_meta) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
|
||||
if let Some(ident) = nested_meta.ident() {
|
||||
return Some((MacroKind::Derive, ident, ident.span));
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> {
|
||||
let parent_scope = &self.parent_scope;
|
||||
let expansion = parent_scope.expansion;
|
||||
let (ext, ident, span, is_legacy) = match &item.node {
|
||||
ItemKind::MacroDef(def) => {
|
||||
let ext = self.r.compile_macro(item, self.r.session.edition());
|
||||
(ext, item.ident, item.span, def.legacy)
|
||||
}
|
||||
ItemKind::Fn(..) => match Self::proc_macro_stub(item) {
|
||||
Some((macro_kind, ident, span)) => {
|
||||
self.r.proc_macro_stubs.insert(item.id);
|
||||
(self.r.dummy_ext(macro_kind), ident, span, false)
|
||||
}
|
||||
None => return parent_scope.legacy,
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let def_id = self.r.definitions.local_def_id(item.id);
|
||||
let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id);
|
||||
self.r.macro_map.insert(def_id, ext);
|
||||
self.r.local_macro_def_scopes.insert(item.id, parent_scope.module);
|
||||
|
||||
if is_legacy {
|
||||
let ident = ident.modern();
|
||||
self.r.macro_names.insert(ident);
|
||||
let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export);
|
||||
let vis = if is_macro_export {
|
||||
ty::Visibility::Public
|
||||
} else {
|
||||
ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
|
||||
};
|
||||
let binding = (res, vis, span, expansion).to_name_binding(self.r.arenas);
|
||||
self.r.set_binding_parent_module(binding, parent_scope.module);
|
||||
self.r.all_macros.insert(ident.name, res);
|
||||
if is_macro_export {
|
||||
let module = self.r.graph_root;
|
||||
self.r.define(module, ident, MacroNS,
|
||||
(res, vis, span, expansion, IsMacroExport));
|
||||
} else {
|
||||
self.r.check_reserved_macro_name(ident, res);
|
||||
self.r.unused_macros.insert(item.id, span);
|
||||
}
|
||||
LegacyScope::Binding(self.r.arenas.alloc_legacy_binding(LegacyBinding {
|
||||
parent_legacy_scope: parent_scope.legacy, binding, ident
|
||||
}))
|
||||
} else {
|
||||
let module = parent_scope.module;
|
||||
let vis = self.resolve_visibility(&item.vis);
|
||||
if vis != ty::Visibility::Public {
|
||||
self.r.unused_macros.insert(item.id, span);
|
||||
}
|
||||
self.r.define(module, ident, MacroNS, (res, vis, span, expansion));
|
||||
self.parent_scope.legacy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! method {
|
||||
($visit:ident: $ty:ty, $invoc:path, $walk:ident) => {
|
||||
fn $visit(&mut self, node: &'a $ty) {
|
||||
fn $visit(&mut self, node: &'b $ty) {
|
||||
if let $invoc(..) = node.node {
|
||||
self.visit_invoc(node.id);
|
||||
} else {
|
||||
@ -961,16 +1174,16 @@ macro_rules! method {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
|
||||
impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
|
||||
method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item);
|
||||
method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr);
|
||||
method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat);
|
||||
method!(visit_ty: ast::Ty, ast::TyKind::Mac, walk_ty);
|
||||
|
||||
fn visit_item(&mut self, item: &'a Item) {
|
||||
fn visit_item(&mut self, item: &'b Item) {
|
||||
let macro_use = match item.node {
|
||||
ItemKind::MacroDef(..) => {
|
||||
self.parent_scope.legacy = self.r.define_macro(item, &self.parent_scope);
|
||||
self.parent_scope.legacy = self.define_macro(item);
|
||||
return
|
||||
}
|
||||
ItemKind::Mac(..) => {
|
||||
@ -991,7 +1204,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, stmt: &'a ast::Stmt) {
|
||||
fn visit_stmt(&mut self, stmt: &'b ast::Stmt) {
|
||||
if let ast::StmtKind::Mac(..) = stmt.node {
|
||||
self.parent_scope.legacy = LegacyScope::Invocation(self.visit_invoc(stmt.id));
|
||||
} else {
|
||||
@ -999,7 +1212,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
|
||||
fn visit_foreign_item(&mut self, foreign_item: &'b ForeignItem) {
|
||||
if let ForeignItemKind::Macro(_) = foreign_item.node {
|
||||
self.visit_invoc(foreign_item.id);
|
||||
return;
|
||||
@ -1009,7 +1222,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
|
||||
visit::walk_foreign_item(self, foreign_item);
|
||||
}
|
||||
|
||||
fn visit_block(&mut self, block: &'a Block) {
|
||||
fn visit_block(&mut self, block: &'b Block) {
|
||||
let orig_current_module = self.parent_scope.module;
|
||||
let orig_current_legacy_scope = self.parent_scope.legacy;
|
||||
self.build_reduced_graph_for_block(block);
|
||||
@ -1018,7 +1231,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
|
||||
self.parent_scope.legacy = orig_current_legacy_scope;
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, item: &'a TraitItem) {
|
||||
fn visit_trait_item(&mut self, item: &'b TraitItem) {
|
||||
let parent = self.parent_scope.module;
|
||||
|
||||
if let TraitItemKind::Macro(_) = item.node {
|
||||
@ -1059,7 +1272,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
|
||||
fn visit_attribute(&mut self, attr: &'b ast::Attribute) {
|
||||
if !attr.is_sugared_doc && is_builtin_attr(attr) {
|
||||
self.parent_scope.module.builtin_attrs.borrow_mut().push((
|
||||
attr.path.segments[0].ident, self.parent_scope.clone()
|
||||
|
@ -1,9 +1,9 @@
|
||||
use GenericParameters::*;
|
||||
use RibKind::*;
|
||||
|
||||
use crate::{path_names_to_string, AliasPossibility, BindingError, CrateLint, LexicalScopeBinding};
|
||||
use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
|
||||
use crate::{Module, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult};
|
||||
use crate::{PathSource, ResolutionError, Resolver, Rib, RibKind, Segment, UseError};
|
||||
use crate::RibKind::*;
|
||||
use crate::{ResolutionError, Resolver, Segment, UseError};
|
||||
|
||||
use log::debug;
|
||||
use rustc::{bug, lint, span_bug};
|
||||
@ -66,6 +66,230 @@ impl PatternSource {
|
||||
}
|
||||
}
|
||||
|
||||
/// The rib kind restricts certain accesses,
|
||||
/// e.g. to a `Res::Local` of an outer item.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
crate enum RibKind<'a> {
|
||||
/// No restriction needs to be applied.
|
||||
NormalRibKind,
|
||||
|
||||
/// We passed through an impl or trait and are now in one of its
|
||||
/// methods or associated types. Allow references to ty params that impl or trait
|
||||
/// binds. Disallow any other upvars (including other ty params that are
|
||||
/// upvars).
|
||||
AssocItemRibKind,
|
||||
|
||||
/// We passed through a function definition. Disallow upvars.
|
||||
/// Permit only those const parameters that are specified in the function's generics.
|
||||
FnItemRibKind,
|
||||
|
||||
/// We passed through an item scope. Disallow upvars.
|
||||
ItemRibKind,
|
||||
|
||||
/// We're in a constant item. Can't refer to dynamic stuff.
|
||||
ConstantItemRibKind,
|
||||
|
||||
/// We passed through a module.
|
||||
ModuleRibKind(Module<'a>),
|
||||
|
||||
/// We passed through a `macro_rules!` statement
|
||||
MacroDefinition(DefId),
|
||||
|
||||
/// All bindings in this rib are type parameters that can't be used
|
||||
/// from the default of a type parameter because they're not declared
|
||||
/// before said type parameter. Also see the `visit_generics` override.
|
||||
ForwardTyParamBanRibKind,
|
||||
|
||||
/// We forbid the use of type parameters as the types of const parameters.
|
||||
TyParamAsConstParamTy,
|
||||
}
|
||||
|
||||
/// A single local scope.
|
||||
///
|
||||
/// A rib represents a scope names can live in. Note that these appear in many places, not just
|
||||
/// around braces. At any place where the list of accessible names (of the given namespace)
|
||||
/// changes or a new restrictions on the name accessibility are introduced, a new rib is put onto a
|
||||
/// stack. This may be, for example, a `let` statement (because it introduces variables), a macro,
|
||||
/// etc.
|
||||
///
|
||||
/// Different [rib kinds](enum.RibKind) are transparent for different names.
|
||||
///
|
||||
/// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When
|
||||
/// resolving, the name is looked up from inside out.
|
||||
#[derive(Debug)]
|
||||
crate struct Rib<'a, R = Res> {
|
||||
pub bindings: FxHashMap<Ident, R>,
|
||||
pub kind: RibKind<'a>,
|
||||
}
|
||||
|
||||
impl<'a, R> Rib<'a, R> {
|
||||
fn new(kind: RibKind<'a>) -> Rib<'a, R> {
|
||||
Rib {
|
||||
bindings: Default::default(),
|
||||
kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
crate enum AliasPossibility {
|
||||
No,
|
||||
Maybe,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
crate enum PathSource<'a> {
|
||||
// Type paths `Path`.
|
||||
Type,
|
||||
// Trait paths in bounds or impls.
|
||||
Trait(AliasPossibility),
|
||||
// Expression paths `path`, with optional parent context.
|
||||
Expr(Option<&'a Expr>),
|
||||
// Paths in path patterns `Path`.
|
||||
Pat,
|
||||
// Paths in struct expressions and patterns `Path { .. }`.
|
||||
Struct,
|
||||
// Paths in tuple struct patterns `Path(..)`.
|
||||
TupleStruct,
|
||||
// `m::A::B` in `<T as m::A>::B::C`.
|
||||
TraitItem(Namespace),
|
||||
}
|
||||
|
||||
impl<'a> PathSource<'a> {
|
||||
fn namespace(self) -> Namespace {
|
||||
match self {
|
||||
PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS,
|
||||
PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS,
|
||||
PathSource::TraitItem(ns) => ns,
|
||||
}
|
||||
}
|
||||
|
||||
fn defer_to_typeck(self) -> bool {
|
||||
match self {
|
||||
PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
|
||||
PathSource::Struct | PathSource::TupleStruct => true,
|
||||
PathSource::Trait(_) | PathSource::TraitItem(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn descr_expected(self) -> &'static str {
|
||||
match self {
|
||||
PathSource::Type => "type",
|
||||
PathSource::Trait(_) => "trait",
|
||||
PathSource::Pat => "unit struct/variant or constant",
|
||||
PathSource::Struct => "struct, variant or union type",
|
||||
PathSource::TupleStruct => "tuple struct/variant",
|
||||
PathSource::TraitItem(ns) => match ns {
|
||||
TypeNS => "associated type",
|
||||
ValueNS => "method or associated constant",
|
||||
MacroNS => bug!("associated macro"),
|
||||
},
|
||||
PathSource::Expr(parent) => match parent.map(|p| &p.node) {
|
||||
// "function" here means "anything callable" rather than `DefKind::Fn`,
|
||||
// this is not precise but usually more helpful than just "value".
|
||||
Some(&ExprKind::Call(..)) => "function",
|
||||
_ => "value",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
crate fn is_expected(self, res: Res) -> bool {
|
||||
match self {
|
||||
PathSource::Type => match res {
|
||||
Res::Def(DefKind::Struct, _)
|
||||
| Res::Def(DefKind::Union, _)
|
||||
| Res::Def(DefKind::Enum, _)
|
||||
| Res::Def(DefKind::Trait, _)
|
||||
| Res::Def(DefKind::TraitAlias, _)
|
||||
| Res::Def(DefKind::TyAlias, _)
|
||||
| Res::Def(DefKind::AssocTy, _)
|
||||
| Res::PrimTy(..)
|
||||
| Res::Def(DefKind::TyParam, _)
|
||||
| Res::SelfTy(..)
|
||||
| Res::Def(DefKind::OpaqueTy, _)
|
||||
| Res::Def(DefKind::ForeignTy, _) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::Trait(AliasPossibility::No) => match res {
|
||||
Res::Def(DefKind::Trait, _) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::Trait(AliasPossibility::Maybe) => match res {
|
||||
Res::Def(DefKind::Trait, _) => true,
|
||||
Res::Def(DefKind::TraitAlias, _) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::Expr(..) => match res {
|
||||
Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
|
||||
| Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
|
||||
| Res::Def(DefKind::Const, _)
|
||||
| Res::Def(DefKind::Static, _)
|
||||
| Res::Local(..)
|
||||
| Res::Def(DefKind::Fn, _)
|
||||
| Res::Def(DefKind::Method, _)
|
||||
| Res::Def(DefKind::AssocConst, _)
|
||||
| Res::SelfCtor(..)
|
||||
| Res::Def(DefKind::ConstParam, _) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::Pat => match res {
|
||||
Res::Def(DefKind::Ctor(_, CtorKind::Const), _) |
|
||||
Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) |
|
||||
Res::SelfCtor(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::TupleStruct => match res {
|
||||
Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::Struct => match res {
|
||||
Res::Def(DefKind::Struct, _)
|
||||
| Res::Def(DefKind::Union, _)
|
||||
| Res::Def(DefKind::Variant, _)
|
||||
| Res::Def(DefKind::TyAlias, _)
|
||||
| Res::Def(DefKind::AssocTy, _)
|
||||
| Res::SelfTy(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::TraitItem(ns) => match res {
|
||||
Res::Def(DefKind::AssocConst, _)
|
||||
| Res::Def(DefKind::Method, _) if ns == ValueNS => true,
|
||||
Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn error_code(self, has_unexpected_resolution: bool) -> &'static str {
|
||||
__diagnostic_used!(E0404);
|
||||
__diagnostic_used!(E0405);
|
||||
__diagnostic_used!(E0412);
|
||||
__diagnostic_used!(E0422);
|
||||
__diagnostic_used!(E0423);
|
||||
__diagnostic_used!(E0425);
|
||||
__diagnostic_used!(E0531);
|
||||
__diagnostic_used!(E0532);
|
||||
__diagnostic_used!(E0573);
|
||||
__diagnostic_used!(E0574);
|
||||
__diagnostic_used!(E0575);
|
||||
__diagnostic_used!(E0576);
|
||||
match (self, has_unexpected_resolution) {
|
||||
(PathSource::Trait(_), true) => "E0404",
|
||||
(PathSource::Trait(_), false) => "E0405",
|
||||
(PathSource::Type, true) => "E0573",
|
||||
(PathSource::Type, false) => "E0412",
|
||||
(PathSource::Struct, true) => "E0574",
|
||||
(PathSource::Struct, false) => "E0422",
|
||||
(PathSource::Expr(..), true) => "E0423",
|
||||
(PathSource::Expr(..), false) => "E0425",
|
||||
(PathSource::Pat, true) | (PathSource::TupleStruct, true) => "E0532",
|
||||
(PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531",
|
||||
(PathSource::TraitItem(..), true) => "E0575",
|
||||
(PathSource::TraitItem(..), false) => "E0576",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LateResolutionVisitor<'a, 'b> {
|
||||
r: &'b mut Resolver<'a>,
|
||||
|
||||
@ -786,9 +1010,6 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
||||
this.with_self_struct_ctor_rib(item_def_id, |this| {
|
||||
debug!("resolve_implementation with_self_struct_ctor_rib");
|
||||
for impl_item in impl_items {
|
||||
this.r.resolve_visibility(
|
||||
&impl_item.vis, &this.parent_scope
|
||||
);
|
||||
// We also need a new scope for the impl item type parameters.
|
||||
let generic_params = HasGenericParams(&impl_item.generics,
|
||||
AssocItemRibKind);
|
||||
|
@ -1,9 +1,9 @@
|
||||
use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
|
||||
use crate::{PathResult, PathSource, RibKind, Segment};
|
||||
use crate::{PathResult, PathSource, Segment};
|
||||
use crate::path_names_to_string;
|
||||
use crate::diagnostics::{add_typo_suggestion, add_module_candidates};
|
||||
use crate::diagnostics::{ImportSuggestion, TypoSuggestion};
|
||||
use crate::late::LateResolutionVisitor;
|
||||
use crate::late::{LateResolutionVisitor, RibKind};
|
||||
|
||||
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
|
||||
use log::debug;
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore-tidy-filelength
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
|
||||
#![feature(crate_visibility_modifier)]
|
||||
@ -13,22 +11,19 @@
|
||||
pub use rustc::hir::def::{Namespace, PerNS};
|
||||
|
||||
use Determinacy::*;
|
||||
use RibKind::*;
|
||||
|
||||
use rustc::hir::map::Definitions;
|
||||
use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str};
|
||||
use rustc::middle::cstore::CrateStore;
|
||||
use rustc::session::Session;
|
||||
use rustc::lint;
|
||||
use rustc::hir::def::{
|
||||
self, DefKind, PartialRes, CtorKind, CtorOf, NonMacroAttrKind, ExportMap
|
||||
};
|
||||
use rustc::hir::def::{self, DefKind, PartialRes, CtorOf, NonMacroAttrKind, ExportMap};
|
||||
use rustc::hir::def::Namespace::*;
|
||||
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
|
||||
use rustc::hir::{TraitMap, GlobMap};
|
||||
use rustc::ty;
|
||||
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
|
||||
use rustc::{bug, span_bug};
|
||||
use rustc::span_bug;
|
||||
|
||||
use rustc_metadata::creader::CrateLoader;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
@ -40,7 +35,7 @@ use syntax::symbol::{Symbol, kw, sym};
|
||||
|
||||
use syntax::visit::{self, Visitor};
|
||||
use syntax::attr;
|
||||
use syntax::ast::{CRATE_NODE_ID, Crate, Expr, ExprKind};
|
||||
use syntax::ast::{CRATE_NODE_ID, Crate};
|
||||
use syntax::ast::{ItemKind, Path};
|
||||
use syntax::{span_err, struct_span_err, unwrap_or};
|
||||
|
||||
@ -57,6 +52,7 @@ use rustc_data_structures::sync::Lrc;
|
||||
|
||||
use diagnostics::{Suggestion, ImportSuggestion};
|
||||
use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding};
|
||||
use late::{PathSource, Rib, RibKind::*};
|
||||
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
|
||||
use macros::{InvocationData, LegacyBinding, LegacyScope};
|
||||
|
||||
@ -199,165 +195,6 @@ enum ResolutionError<'a> {
|
||||
ConstParamDependentOnTypeParam,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
enum AliasPossibility {
|
||||
No,
|
||||
Maybe,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum PathSource<'a> {
|
||||
// Type paths `Path`.
|
||||
Type,
|
||||
// Trait paths in bounds or impls.
|
||||
Trait(AliasPossibility),
|
||||
// Expression paths `path`, with optional parent context.
|
||||
Expr(Option<&'a Expr>),
|
||||
// Paths in path patterns `Path`.
|
||||
Pat,
|
||||
// Paths in struct expressions and patterns `Path { .. }`.
|
||||
Struct,
|
||||
// Paths in tuple struct patterns `Path(..)`.
|
||||
TupleStruct,
|
||||
// `m::A::B` in `<T as m::A>::B::C`.
|
||||
TraitItem(Namespace),
|
||||
}
|
||||
|
||||
impl<'a> PathSource<'a> {
|
||||
fn namespace(self) -> Namespace {
|
||||
match self {
|
||||
PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS,
|
||||
PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS,
|
||||
PathSource::TraitItem(ns) => ns,
|
||||
}
|
||||
}
|
||||
|
||||
fn defer_to_typeck(self) -> bool {
|
||||
match self {
|
||||
PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
|
||||
PathSource::Struct | PathSource::TupleStruct => true,
|
||||
PathSource::Trait(_) | PathSource::TraitItem(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn descr_expected(self) -> &'static str {
|
||||
match self {
|
||||
PathSource::Type => "type",
|
||||
PathSource::Trait(_) => "trait",
|
||||
PathSource::Pat => "unit struct/variant or constant",
|
||||
PathSource::Struct => "struct, variant or union type",
|
||||
PathSource::TupleStruct => "tuple struct/variant",
|
||||
PathSource::TraitItem(ns) => match ns {
|
||||
TypeNS => "associated type",
|
||||
ValueNS => "method or associated constant",
|
||||
MacroNS => bug!("associated macro"),
|
||||
},
|
||||
PathSource::Expr(parent) => match parent.map(|p| &p.node) {
|
||||
// "function" here means "anything callable" rather than `DefKind::Fn`,
|
||||
// this is not precise but usually more helpful than just "value".
|
||||
Some(&ExprKind::Call(..)) => "function",
|
||||
_ => "value",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn is_expected(self, res: Res) -> bool {
|
||||
match self {
|
||||
PathSource::Type => match res {
|
||||
Res::Def(DefKind::Struct, _)
|
||||
| Res::Def(DefKind::Union, _)
|
||||
| Res::Def(DefKind::Enum, _)
|
||||
| Res::Def(DefKind::Trait, _)
|
||||
| Res::Def(DefKind::TraitAlias, _)
|
||||
| Res::Def(DefKind::TyAlias, _)
|
||||
| Res::Def(DefKind::AssocTy, _)
|
||||
| Res::PrimTy(..)
|
||||
| Res::Def(DefKind::TyParam, _)
|
||||
| Res::SelfTy(..)
|
||||
| Res::Def(DefKind::OpaqueTy, _)
|
||||
| Res::Def(DefKind::ForeignTy, _) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::Trait(AliasPossibility::No) => match res {
|
||||
Res::Def(DefKind::Trait, _) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::Trait(AliasPossibility::Maybe) => match res {
|
||||
Res::Def(DefKind::Trait, _) => true,
|
||||
Res::Def(DefKind::TraitAlias, _) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::Expr(..) => match res {
|
||||
Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
|
||||
| Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
|
||||
| Res::Def(DefKind::Const, _)
|
||||
| Res::Def(DefKind::Static, _)
|
||||
| Res::Local(..)
|
||||
| Res::Def(DefKind::Fn, _)
|
||||
| Res::Def(DefKind::Method, _)
|
||||
| Res::Def(DefKind::AssocConst, _)
|
||||
| Res::SelfCtor(..)
|
||||
| Res::Def(DefKind::ConstParam, _) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::Pat => match res {
|
||||
Res::Def(DefKind::Ctor(_, CtorKind::Const), _) |
|
||||
Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) |
|
||||
Res::SelfCtor(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::TupleStruct => match res {
|
||||
Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::Struct => match res {
|
||||
Res::Def(DefKind::Struct, _)
|
||||
| Res::Def(DefKind::Union, _)
|
||||
| Res::Def(DefKind::Variant, _)
|
||||
| Res::Def(DefKind::TyAlias, _)
|
||||
| Res::Def(DefKind::AssocTy, _)
|
||||
| Res::SelfTy(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::TraitItem(ns) => match res {
|
||||
Res::Def(DefKind::AssocConst, _)
|
||||
| Res::Def(DefKind::Method, _) if ns == ValueNS => true,
|
||||
Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn error_code(self, has_unexpected_resolution: bool) -> &'static str {
|
||||
__diagnostic_used!(E0404);
|
||||
__diagnostic_used!(E0405);
|
||||
__diagnostic_used!(E0412);
|
||||
__diagnostic_used!(E0422);
|
||||
__diagnostic_used!(E0423);
|
||||
__diagnostic_used!(E0425);
|
||||
__diagnostic_used!(E0531);
|
||||
__diagnostic_used!(E0532);
|
||||
__diagnostic_used!(E0573);
|
||||
__diagnostic_used!(E0574);
|
||||
__diagnostic_used!(E0575);
|
||||
__diagnostic_used!(E0576);
|
||||
match (self, has_unexpected_resolution) {
|
||||
(PathSource::Trait(_), true) => "E0404",
|
||||
(PathSource::Trait(_), false) => "E0405",
|
||||
(PathSource::Type, true) => "E0573",
|
||||
(PathSource::Type, false) => "E0412",
|
||||
(PathSource::Struct, true) => "E0574",
|
||||
(PathSource::Struct, false) => "E0422",
|
||||
(PathSource::Expr(..), true) => "E0423",
|
||||
(PathSource::Expr(..), false) => "E0425",
|
||||
(PathSource::Pat, true) | (PathSource::TupleStruct, true) => "E0532",
|
||||
(PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531",
|
||||
(PathSource::TraitItem(..), true) => "E0575",
|
||||
(PathSource::TraitItem(..), false) => "E0576",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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`.
|
||||
@ -463,71 +300,6 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
|
||||
}
|
||||
}
|
||||
|
||||
/// The rib kind restricts certain accesses,
|
||||
/// e.g. to a `Res::Local` of an outer item.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum RibKind<'a> {
|
||||
/// No restriction needs to be applied.
|
||||
NormalRibKind,
|
||||
|
||||
/// We passed through an impl or trait and are now in one of its
|
||||
/// methods or associated types. Allow references to ty params that impl or trait
|
||||
/// binds. Disallow any other upvars (including other ty params that are
|
||||
/// upvars).
|
||||
AssocItemRibKind,
|
||||
|
||||
/// We passed through a function definition. Disallow upvars.
|
||||
/// Permit only those const parameters that are specified in the function's generics.
|
||||
FnItemRibKind,
|
||||
|
||||
/// We passed through an item scope. Disallow upvars.
|
||||
ItemRibKind,
|
||||
|
||||
/// We're in a constant item. Can't refer to dynamic stuff.
|
||||
ConstantItemRibKind,
|
||||
|
||||
/// We passed through a module.
|
||||
ModuleRibKind(Module<'a>),
|
||||
|
||||
/// We passed through a `macro_rules!` statement
|
||||
MacroDefinition(DefId),
|
||||
|
||||
/// All bindings in this rib are type parameters that can't be used
|
||||
/// from the default of a type parameter because they're not declared
|
||||
/// before said type parameter. Also see the `visit_generics` override.
|
||||
ForwardTyParamBanRibKind,
|
||||
|
||||
/// We forbid the use of type parameters as the types of const parameters.
|
||||
TyParamAsConstParamTy,
|
||||
}
|
||||
|
||||
/// A single local scope.
|
||||
///
|
||||
/// A rib represents a scope names can live in. Note that these appear in many places, not just
|
||||
/// around braces. At any place where the list of accessible names (of the given namespace)
|
||||
/// changes or a new restrictions on the name accessibility are introduced, a new rib is put onto a
|
||||
/// stack. This may be, for example, a `let` statement (because it introduces variables), a macro,
|
||||
/// etc.
|
||||
///
|
||||
/// Different [rib kinds](enum.RibKind) are transparent for different names.
|
||||
///
|
||||
/// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When
|
||||
/// resolving, the name is looked up from inside out.
|
||||
#[derive(Debug)]
|
||||
struct Rib<'a, R = Res> {
|
||||
bindings: FxHashMap<Ident, R>,
|
||||
kind: RibKind<'a>,
|
||||
}
|
||||
|
||||
impl<'a, R> Rib<'a, R> {
|
||||
fn new(kind: RibKind<'a>) -> Rib<'a, R> {
|
||||
Rib {
|
||||
bindings: Default::default(),
|
||||
kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An intermediate resolution result.
|
||||
///
|
||||
/// This refers to the thing referred by a name. The difference between `Res` and `Item` is that
|
||||
@ -2405,105 +2177,6 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_visibility(
|
||||
&mut self, vis: &ast::Visibility, parent_scope: &ParentScope<'a>
|
||||
) -> ty::Visibility {
|
||||
match vis.node {
|
||||
ast::VisibilityKind::Public => ty::Visibility::Public,
|
||||
ast::VisibilityKind::Crate(..) => {
|
||||
ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
|
||||
}
|
||||
ast::VisibilityKind::Inherited => {
|
||||
ty::Visibility::Restricted(parent_scope.module.normal_ancestor_id)
|
||||
}
|
||||
ast::VisibilityKind::Restricted { ref path, id, .. } => {
|
||||
// For visibilities we are not ready to provide correct implementation of "uniform
|
||||
// paths" right now, so on 2018 edition we only allow module-relative paths for now.
|
||||
// On 2015 edition visibilities are resolved as crate-relative by default,
|
||||
// so we are prepending a root segment if necessary.
|
||||
let ident = path.segments.get(0).expect("empty path in visibility").ident;
|
||||
let crate_root = if ident.is_path_segment_keyword() {
|
||||
None
|
||||
} else if ident.span.rust_2018() {
|
||||
let msg = "relative paths are not supported in visibilities on 2018 edition";
|
||||
self.session.struct_span_err(ident.span, msg)
|
||||
.span_suggestion(
|
||||
path.span,
|
||||
"try",
|
||||
format!("crate::{}", path),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
return ty::Visibility::Public;
|
||||
} else {
|
||||
let ctxt = ident.span.ctxt();
|
||||
Some(Segment::from_ident(Ident::new(
|
||||
kw::PathRoot, path.span.shrink_to_lo().with_ctxt(ctxt)
|
||||
)))
|
||||
};
|
||||
|
||||
let segments = crate_root.into_iter()
|
||||
.chain(path.segments.iter().map(|seg| seg.into())).collect::<Vec<_>>();
|
||||
let expected_found_error = |this: &Self, res: Res| {
|
||||
let path_str = Segment::names_to_string(&segments);
|
||||
struct_span_err!(this.session, path.span, E0577,
|
||||
"expected module, found {} `{}`", res.descr(), path_str)
|
||||
.span_label(path.span, "not a module").emit();
|
||||
};
|
||||
match self.resolve_path(
|
||||
&segments,
|
||||
Some(TypeNS),
|
||||
parent_scope,
|
||||
true,
|
||||
path.span,
|
||||
CrateLint::SimplePath(id),
|
||||
) {
|
||||
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
|
||||
let res = module.res().expect("visibility resolved to unnamed block");
|
||||
self.record_partial_res(id, PartialRes::new(res));
|
||||
if module.is_normal() {
|
||||
if res == Res::Err {
|
||||
ty::Visibility::Public
|
||||
} else {
|
||||
let vis = ty::Visibility::Restricted(res.def_id());
|
||||
if self.is_accessible_from(vis, parent_scope.module) {
|
||||
vis
|
||||
} else {
|
||||
let msg =
|
||||
"visibilities can only be restricted to ancestor modules";
|
||||
self.session.span_err(path.span, msg);
|
||||
ty::Visibility::Public
|
||||
}
|
||||
}
|
||||
} else {
|
||||
expected_found_error(self, res);
|
||||
ty::Visibility::Public
|
||||
}
|
||||
}
|
||||
PathResult::Module(..) => {
|
||||
self.session.span_err(path.span, "visibility must resolve to a module");
|
||||
ty::Visibility::Public
|
||||
}
|
||||
PathResult::NonModule(partial_res) => {
|
||||
expected_found_error(self, partial_res.base_res());
|
||||
ty::Visibility::Public
|
||||
}
|
||||
PathResult::Failed { span, label, suggestion, .. } => {
|
||||
self.report_error(
|
||||
span, ResolutionError::FailedToResolve { label, suggestion }
|
||||
);
|
||||
ty::Visibility::Public
|
||||
}
|
||||
PathResult::Indeterminate => {
|
||||
span_err!(self.session, path.span, E0578,
|
||||
"cannot determine resolution for the visibility");
|
||||
ty::Visibility::Public
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
|
||||
vis.is_accessible_from(module.normal_ancestor_id, self)
|
||||
}
|
||||
|
@ -3,15 +3,14 @@ use crate::{CrateLint, Resolver, ResolutionError, Scope, ScopeSet, ParentScope,
|
||||
use crate::{Module, ModuleKind, NameBinding, PathResult, Segment, ToNameBinding};
|
||||
use crate::{ModuleOrUniformRoot, KNOWN_TOOLS};
|
||||
use crate::Namespace::*;
|
||||
use crate::build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
|
||||
use crate::build_reduced_graph::BuildReducedGraphVisitor;
|
||||
use crate::resolve_imports::ImportResolver;
|
||||
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||
use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
|
||||
use rustc::hir::map::DefCollector;
|
||||
use rustc::middle::stability;
|
||||
use rustc::{ty, lint, span_bug};
|
||||
use syntax::ast::{self, Ident, ItemKind};
|
||||
use syntax::attr::{self, StabilityLevel};
|
||||
use syntax::ast::{self, Ident};
|
||||
use syntax::attr::StabilityLevel;
|
||||
use syntax::edition::Edition;
|
||||
use syntax::ext::base::{self, Indeterminate, SpecialDerives};
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension};
|
||||
@ -115,21 +114,6 @@ fn fast_print_path(path: &ast::Path) -> Symbol {
|
||||
}
|
||||
}
|
||||
|
||||
fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
|
||||
if attr::contains_name(&item.attrs, sym::proc_macro) {
|
||||
return Some((MacroKind::Bang, item.ident, item.span));
|
||||
} else if attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
|
||||
return Some((MacroKind::Attr, item.ident, item.span));
|
||||
} else if let Some(attr) = attr::find_by_name(&item.attrs, sym::proc_macro_derive) {
|
||||
if let Some(nested_meta) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
|
||||
if let Some(ident) = nested_meta.ident() {
|
||||
return Some((MacroKind::Derive, ident, ident.span));
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
impl<'a> base::Resolver for Resolver<'a> {
|
||||
fn next_node_id(&mut self) -> ast::NodeId {
|
||||
self.session.next_node_id()
|
||||
@ -887,62 +871,4 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
Lrc::new(result)
|
||||
}
|
||||
|
||||
pub fn define_macro(
|
||||
&mut self, item: &ast::Item, parent_scope: &ParentScope<'a>,
|
||||
) -> LegacyScope<'a> {
|
||||
let expansion = parent_scope.expansion;
|
||||
let (ext, ident, span, is_legacy) = match &item.node {
|
||||
ItemKind::MacroDef(def) => {
|
||||
let ext = self.compile_macro(item, self.session.edition());
|
||||
(ext, item.ident, item.span, def.legacy)
|
||||
}
|
||||
ItemKind::Fn(..) => match proc_macro_stub(item) {
|
||||
Some((macro_kind, ident, span)) => {
|
||||
self.proc_macro_stubs.insert(item.id);
|
||||
(self.dummy_ext(macro_kind), ident, span, false)
|
||||
}
|
||||
None => return parent_scope.legacy,
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let def_id = self.definitions.local_def_id(item.id);
|
||||
let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id);
|
||||
self.macro_map.insert(def_id, ext);
|
||||
self.local_macro_def_scopes.insert(item.id, parent_scope.module);
|
||||
|
||||
if is_legacy {
|
||||
let ident = ident.modern();
|
||||
self.macro_names.insert(ident);
|
||||
let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export);
|
||||
let vis = if is_macro_export {
|
||||
ty::Visibility::Public
|
||||
} else {
|
||||
ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
|
||||
};
|
||||
let binding = (res, vis, span, expansion).to_name_binding(self.arenas);
|
||||
self.set_binding_parent_module(binding, parent_scope.module);
|
||||
self.all_macros.insert(ident.name, res);
|
||||
if is_macro_export {
|
||||
let module = self.graph_root;
|
||||
self.define(module, ident, MacroNS,
|
||||
(res, vis, span, expansion, IsMacroExport));
|
||||
} else {
|
||||
self.check_reserved_macro_name(ident, res);
|
||||
self.unused_macros.insert(item.id, span);
|
||||
}
|
||||
LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding {
|
||||
parent_legacy_scope: parent_scope.legacy, binding, ident
|
||||
}))
|
||||
} else {
|
||||
let module = parent_scope.module;
|
||||
let vis = self.resolve_visibility(&item.vis, parent_scope);
|
||||
if vis != ty::Visibility::Public {
|
||||
self.unused_macros.insert(item.id, span);
|
||||
}
|
||||
self.define(module, ident, MacroNS, (res, vis, span, expansion));
|
||||
parent_scope.legacy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyErro
|
||||
use crate::{Resolver, ResolutionError, Segment};
|
||||
use crate::{names_to_string, module_to_string};
|
||||
use crate::ModuleKind;
|
||||
use crate::build_reduced_graph::BuildReducedGraphVisitor;
|
||||
use crate::diagnostics::Suggestion;
|
||||
|
||||
use errors::Applicability;
|
||||
@ -27,7 +26,7 @@ use rustc::session::DiagnosticMessageId;
|
||||
use rustc::util::nodemap::FxHashSet;
|
||||
use rustc::{bug, span_bug};
|
||||
|
||||
use syntax::ast::{self, Ident, Name, NodeId, CRATE_NODE_ID};
|
||||
use syntax::ast::{Ident, Name, NodeId, CRATE_NODE_ID};
|
||||
use syntax::ext::hygiene::ExpnId;
|
||||
use syntax::symbol::kw;
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
@ -153,10 +152,14 @@ impl<'a> NameResolution<'a> {
|
||||
self.single_imports.is_empty() { Some(binding) } else { None }
|
||||
})
|
||||
}
|
||||
|
||||
crate fn add_single_import(&mut self, directive: &'a ImportDirective<'a>) {
|
||||
self.single_imports.insert(PtrKey(directive));
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Resolver<'a> {
|
||||
fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace)
|
||||
crate fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace)
|
||||
-> &'a RefCell<NameResolution<'a>> {
|
||||
*module.resolutions.borrow_mut().entry((ident.modern(), ns))
|
||||
.or_insert_with(|| self.arenas.alloc_name_resolution())
|
||||
@ -417,57 +420,7 @@ impl<'a> Resolver<'a> {
|
||||
// No resolution and no one else can define the name - determinate error.
|
||||
Err((Determined, Weak::No))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
||||
// Add an import directive to the current module.
|
||||
pub fn add_import_directive(&mut self,
|
||||
module_path: Vec<Segment>,
|
||||
subclass: ImportDirectiveSubclass<'a>,
|
||||
span: Span,
|
||||
id: NodeId,
|
||||
item: &ast::Item,
|
||||
root_span: Span,
|
||||
root_id: NodeId,
|
||||
vis: ty::Visibility,
|
||||
parent_scope: ParentScope<'a>) {
|
||||
let current_module = parent_scope.module;
|
||||
let directive = self.r.arenas.alloc_import_directive(ImportDirective {
|
||||
parent_scope,
|
||||
module_path,
|
||||
imported_module: Cell::new(None),
|
||||
subclass,
|
||||
span,
|
||||
id,
|
||||
use_span: item.span,
|
||||
use_span_with_attributes: item.span_with_attributes(),
|
||||
has_attributes: !item.attrs.is_empty(),
|
||||
root_span,
|
||||
root_id,
|
||||
vis: Cell::new(vis),
|
||||
used: Cell::new(false),
|
||||
});
|
||||
|
||||
debug!("add_import_directive({:?})", directive);
|
||||
|
||||
self.r.indeterminate_imports.push(directive);
|
||||
match directive.subclass {
|
||||
SingleImport { target, type_ns_only, .. } => {
|
||||
self.r.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
|
||||
let mut resolution = this.resolution(current_module, target, ns).borrow_mut();
|
||||
resolution.single_imports.insert(PtrKey(directive));
|
||||
});
|
||||
}
|
||||
// We don't add prelude imports to the globs since they only affect lexical scopes,
|
||||
// which are not relevant to import resolution.
|
||||
GlobImport { is_prelude: true, .. } => {}
|
||||
GlobImport { .. } => current_module.globs.borrow_mut().push(directive),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Resolver<'a> {
|
||||
// Given a binding and an import directive that resolves to it,
|
||||
// return the corresponding binding defined by the import directive.
|
||||
crate fn import(&self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
|
||||
|
Loading…
Reference in New Issue
Block a user