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:
Vadim Petrochenkov 2019-08-08 23:57:35 +03:00
parent 9c86ce76e5
commit f360d795f1
6 changed files with 603 additions and 617 deletions

View File

@ -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(&macro_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(&macro_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()

View File

@ -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);

View File

@ -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;

View File

@ -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)
}

View File

@ -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
}
}
}

View File

@ -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>)