resolve: Record full parent scope data for imports
This commit is contained in:
parent
cae6efc37d
commit
dd3738a2ba
3 changed files with 52 additions and 46 deletions
|
|
@ -126,7 +126,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
mut uniform_paths_canary_emitted: bool,
|
||||
nested: bool,
|
||||
item: &Item,
|
||||
expansion: Mark,
|
||||
parent_scope: ParentScope<'a>,
|
||||
) {
|
||||
debug!("build_reduced_graph_for_use_tree(parent_prefix={:?}, \
|
||||
uniform_paths_canary_emitted={}, \
|
||||
|
|
@ -224,7 +224,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
root_use_tree.span,
|
||||
root_id,
|
||||
ty::Visibility::Invisible,
|
||||
expansion,
|
||||
parent_scope.clone(),
|
||||
true, // is_uniform_paths_canary
|
||||
);
|
||||
};
|
||||
|
|
@ -354,7 +354,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
root_use_tree.span,
|
||||
root_id,
|
||||
vis,
|
||||
expansion,
|
||||
parent_scope,
|
||||
false, // is_uniform_paths_canary
|
||||
);
|
||||
}
|
||||
|
|
@ -371,7 +371,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
root_use_tree.span,
|
||||
root_id,
|
||||
vis,
|
||||
expansion,
|
||||
parent_scope,
|
||||
false, // is_uniform_paths_canary
|
||||
);
|
||||
}
|
||||
|
|
@ -409,7 +409,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
uniform_paths_canary_emitted,
|
||||
true,
|
||||
item,
|
||||
expansion,
|
||||
parent_scope.clone(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -417,8 +417,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
}
|
||||
|
||||
/// Constructs the reduced graph for one item.
|
||||
fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
|
||||
let parent = self.current_module;
|
||||
fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScope<'a>) {
|
||||
let parent = parent_scope.module;
|
||||
let expansion = parent_scope.expansion;
|
||||
let ident = item.ident;
|
||||
let sp = item.span;
|
||||
let vis = self.resolve_visibility(&item.vis);
|
||||
|
|
@ -435,7 +436,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
false, // uniform_paths_canary_emitted
|
||||
false,
|
||||
item,
|
||||
expansion,
|
||||
parent_scope,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -448,7 +449,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
self.injected_crate = Some(module);
|
||||
}
|
||||
|
||||
let used = self.process_legacy_macro_imports(item, module, expansion);
|
||||
let used = self.process_legacy_macro_imports(item, module, &parent_scope);
|
||||
let binding =
|
||||
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
|
||||
if ptr::eq(self.current_module, self.graph_root) {
|
||||
|
|
@ -473,7 +474,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
let directive = self.arenas.alloc_import_directive(ImportDirective {
|
||||
root_id: item.id,
|
||||
id: item.id,
|
||||
parent,
|
||||
parent_scope,
|
||||
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
|
||||
subclass: ImportDirectiveSubclass::ExternCrate {
|
||||
source: orig_name,
|
||||
|
|
@ -483,7 +484,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
span: item.span,
|
||||
module_path: Vec::new(),
|
||||
vis: Cell::new(vis),
|
||||
expansion,
|
||||
used: Cell::new(used),
|
||||
is_uniform_paths_canary: false,
|
||||
});
|
||||
|
|
@ -856,9 +856,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
}
|
||||
|
||||
// This 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>, expansion: Mark)
|
||||
-> bool {
|
||||
let allow_shadowing = expansion == Mark::root();
|
||||
fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>,
|
||||
parent_scope: &ParentScope<'a>) -> bool {
|
||||
let allow_shadowing = parent_scope.expansion == Mark::root();
|
||||
let legacy_imports = self.legacy_macro_imports(&item.attrs);
|
||||
let used = legacy_imports != LegacyMacroImports::default();
|
||||
|
||||
|
|
@ -868,18 +868,17 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
"an `extern crate` loading macros must be at the crate root");
|
||||
}
|
||||
|
||||
let (graph_root, arenas) = (self.graph_root, self.arenas);
|
||||
let arenas = self.arenas;
|
||||
let macro_use_directive = |span| arenas.alloc_import_directive(ImportDirective {
|
||||
root_id: item.id,
|
||||
id: item.id,
|
||||
parent: graph_root,
|
||||
parent_scope: parent_scope.clone(),
|
||||
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
|
||||
subclass: ImportDirectiveSubclass::MacroUse,
|
||||
root_span: span,
|
||||
span,
|
||||
module_path: Vec::new(),
|
||||
vis: Cell::new(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))),
|
||||
expansion,
|
||||
used: Cell::new(false),
|
||||
is_uniform_paths_canary: false,
|
||||
});
|
||||
|
|
@ -1010,7 +1009,13 @@ impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> {
|
|||
|
||||
let orig_current_module = self.resolver.current_module;
|
||||
let orig_current_legacy_scope = self.current_legacy_scope;
|
||||
self.resolver.build_reduced_graph_for_item(item, self.expansion);
|
||||
let parent_scope = ParentScope {
|
||||
module: self.resolver.current_module,
|
||||
expansion: self.expansion,
|
||||
legacy: self.current_legacy_scope,
|
||||
derives: Vec::new(),
|
||||
};
|
||||
self.resolver.build_reduced_graph_for_item(item, parent_scope);
|
||||
visit::walk_item(self, item);
|
||||
self.resolver.current_module = orig_current_module;
|
||||
if !macro_use {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ use std::cell::Cell;
|
|||
use std::mem;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct InvocationData<'a> {
|
||||
def_index: DefIndex,
|
||||
/// Module in which the macro was invoked.
|
||||
|
|
@ -70,6 +70,7 @@ impl<'a> InvocationData<'a> {
|
|||
|
||||
/// Binding produced by a `macro_rules` item.
|
||||
/// Not modularized, can shadow previous legacy bindings, etc.
|
||||
#[derive(Debug)]
|
||||
pub struct LegacyBinding<'a> {
|
||||
binding: &'a NameBinding<'a>,
|
||||
/// Legacy scope into which the `macro_rules` item was planted.
|
||||
|
|
@ -82,7 +83,7 @@ pub struct LegacyBinding<'a> {
|
|||
/// (named or unnamed), or even further if it escapes with `#[macro_use]`.
|
||||
/// Some macro invocations need to introduce legacy scopes too because they
|
||||
/// potentially can expand into macro definitions.
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum LegacyScope<'a> {
|
||||
/// Created when invocation data is allocated in the arena,
|
||||
/// must be replaced with a proper scope later.
|
||||
|
|
@ -96,8 +97,8 @@ pub enum LegacyScope<'a> {
|
|||
Invocation(&'a InvocationData<'a>),
|
||||
}
|
||||
|
||||
/// Everything you need to resolve a macro path.
|
||||
#[derive(Clone)]
|
||||
/// Everything you need to resolve a macro or import path.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ParentScope<'a> {
|
||||
crate module: Module<'a>,
|
||||
crate expansion: Mark,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
|
|||
use {Resolver, Segment};
|
||||
use {names_to_string, module_to_string};
|
||||
use {resolve_error, ResolutionError};
|
||||
use macros::ParentScope;
|
||||
|
||||
use rustc_data_structures::ptr_key::PtrKey;
|
||||
use rustc::ty;
|
||||
|
|
@ -88,13 +89,12 @@ pub struct ImportDirective<'a> {
|
|||
/// Span of the *root* use tree (see `root_id`).
|
||||
pub root_span: Span,
|
||||
|
||||
pub parent: Module<'a>,
|
||||
pub parent_scope: ParentScope<'a>,
|
||||
pub module_path: Vec<Segment>,
|
||||
/// The resolution of `module_path`.
|
||||
pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>,
|
||||
pub subclass: ImportDirectiveSubclass<'a>,
|
||||
pub vis: Cell<ty::Visibility>,
|
||||
pub expansion: Mark,
|
||||
pub used: Cell<bool>,
|
||||
|
||||
/// Whether this import is a "canary" for the `uniform_paths` feature,
|
||||
|
|
@ -307,8 +307,9 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||
};
|
||||
match self.resolve_ident_in_module(module, ident, ns, false, path_span) {
|
||||
Err(Determined) => continue,
|
||||
Ok(binding)
|
||||
if !self.is_accessible_from(binding.vis, single_import.parent) => continue,
|
||||
Ok(binding) if !self.is_accessible_from(
|
||||
binding.vis, single_import.parent_scope.module
|
||||
) => continue,
|
||||
Ok(_) | Err(Undetermined) => return Err(Undetermined),
|
||||
}
|
||||
}
|
||||
|
|
@ -381,8 +382,9 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||
|
||||
match result {
|
||||
Err(Determined) => continue,
|
||||
Ok(binding)
|
||||
if !self.is_accessible_from(binding.vis, glob_import.parent) => continue,
|
||||
Ok(binding) if !self.is_accessible_from(
|
||||
binding.vis, glob_import.parent_scope.module
|
||||
) => continue,
|
||||
Ok(_) | Err(Undetermined) => return Err(Undetermined),
|
||||
}
|
||||
}
|
||||
|
|
@ -400,11 +402,11 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||
root_span: Span,
|
||||
root_id: NodeId,
|
||||
vis: ty::Visibility,
|
||||
expansion: Mark,
|
||||
parent_scope: ParentScope<'a>,
|
||||
is_uniform_paths_canary: bool) {
|
||||
let current_module = self.current_module;
|
||||
let current_module = parent_scope.module;
|
||||
let directive = self.arenas.alloc_import_directive(ImportDirective {
|
||||
parent: current_module,
|
||||
parent_scope,
|
||||
module_path,
|
||||
imported_module: Cell::new(None),
|
||||
subclass,
|
||||
|
|
@ -413,7 +415,6 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||
root_span,
|
||||
root_id,
|
||||
vis: Cell::new(vis),
|
||||
expansion,
|
||||
used: Cell::new(false),
|
||||
is_uniform_paths_canary,
|
||||
});
|
||||
|
|
@ -431,7 +432,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||
// 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 { .. } => self.current_module.globs.borrow_mut().push(directive),
|
||||
GlobImport { .. } => current_module.globs.borrow_mut().push(directive),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -462,7 +463,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||
},
|
||||
span: directive.span,
|
||||
vis,
|
||||
expansion: directive.expansion,
|
||||
expansion: directive.parent_scope.expansion,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -568,12 +569,12 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||
let scope = match ident.span.reverse_glob_adjust(module.expansion,
|
||||
directive.span.ctxt().modern()) {
|
||||
Some(Some(def)) => self.macro_def_scope(def),
|
||||
Some(None) => directive.parent,
|
||||
Some(None) => directive.parent_scope.module,
|
||||
None => continue,
|
||||
};
|
||||
if self.is_accessible_from(binding.vis, scope) {
|
||||
let imported_binding = self.import(binding, directive);
|
||||
let _ = self.try_define(directive.parent, ident, ns, imported_binding);
|
||||
let _ = self.try_define(directive.parent_scope.module, ident, ns, imported_binding);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -587,7 +588,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||
let dummy_binding = self.dummy_binding;
|
||||
let dummy_binding = self.import(dummy_binding, directive);
|
||||
self.per_ns(|this, ns| {
|
||||
let _ = this.try_define(directive.parent, target, ns, dummy_binding);
|
||||
let _ = this.try_define(directive.parent_scope.module, target, ns, dummy_binding);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -856,8 +857,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||
Segment::names_to_string(&directive.module_path[..]),
|
||||
module_to_string(self.current_module).unwrap_or_else(|| "???".to_string()));
|
||||
|
||||
|
||||
self.current_module = directive.parent;
|
||||
self.current_module = directive.parent_scope.module;
|
||||
|
||||
let module = if let Some(module) = directive.imported_module.get() {
|
||||
module
|
||||
|
|
@ -868,7 +868,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||
directive.vis.set(ty::Visibility::Invisible);
|
||||
let result = self.resolve_path(
|
||||
Some(if directive.is_uniform_paths_canary {
|
||||
ModuleOrUniformRoot::Module(directive.parent)
|
||||
ModuleOrUniformRoot::Module(directive.parent_scope.module)
|
||||
} else {
|
||||
ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name())
|
||||
}),
|
||||
|
|
@ -910,7 +910,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||
return
|
||||
};
|
||||
|
||||
let parent = directive.parent;
|
||||
let parent = directive.parent_scope.module;
|
||||
match result[ns].get() {
|
||||
Err(Undetermined) => indeterminate = true,
|
||||
Err(Determined) => {
|
||||
|
|
@ -942,12 +942,12 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||
|
||||
// If appropriate, returns an error to report.
|
||||
fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> {
|
||||
self.current_module = directive.parent;
|
||||
self.current_module = directive.parent_scope.module;
|
||||
let ImportDirective { ref module_path, span, .. } = *directive;
|
||||
|
||||
let module_result = self.resolve_path(
|
||||
Some(if directive.is_uniform_paths_canary {
|
||||
ModuleOrUniformRoot::Module(directive.parent)
|
||||
ModuleOrUniformRoot::Module(directive.parent_scope.module)
|
||||
} else {
|
||||
ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name())
|
||||
}),
|
||||
|
|
@ -995,7 +995,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||
}
|
||||
|
||||
if let ModuleOrUniformRoot::Module(module) = module {
|
||||
if module.def_id() == directive.parent.def_id() {
|
||||
if module.def_id() == directive.parent_scope.module.def_id() {
|
||||
// Importing a module into itself is not allowed.
|
||||
return Some((directive.span,
|
||||
"Cannot glob-import a module into itself.".to_string()));
|
||||
|
|
@ -1189,7 +1189,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||
if let Some(Def::Trait(_)) = module.def() {
|
||||
self.session.span_err(directive.span, "items in traits are not importable.");
|
||||
return;
|
||||
} else if module.def_id() == directive.parent.def_id() {
|
||||
} else if module.def_id() == directive.parent_scope.module.def_id() {
|
||||
return;
|
||||
} else if let GlobImport { is_prelude: true, .. } = directive.subclass {
|
||||
self.prelude = Some(module);
|
||||
|
|
@ -1213,7 +1213,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||
};
|
||||
if self.is_accessible_from(binding.pseudo_vis(), scope) {
|
||||
let imported_binding = self.import(binding, directive);
|
||||
let _ = self.try_define(directive.parent, ident, ns, imported_binding);
|
||||
let _ = self.try_define(directive.parent_scope.module, ident, ns, imported_binding);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue