resolve: Make sure macros and imports are resolved in full parent scope

Slightly simplify `fn build_reduced_graph_for_use_tree`
This commit is contained in:
Vadim Petrochenkov 2018-10-27 20:23:54 +03:00
parent acdbd0643c
commit 1f257bd022
5 changed files with 83 additions and 86 deletions

View File

@ -111,23 +111,23 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
fn build_reduced_graph_for_use_tree(
&mut self,
root_use_tree: &ast::UseTree,
root_id: NodeId,
// This particular use tree
use_tree: &ast::UseTree,
id: NodeId,
vis: ty::Visibility,
parent_prefix: &[Segment],
mut uniform_paths_canary_emitted: bool,
nested: bool,
item: &Item,
mut uniform_paths_canary_emitted: bool,
// The whole `use` item
parent_scope: ParentScope<'a>,
item: &Item,
vis: ty::Visibility,
root_span: Span,
) {
debug!("build_reduced_graph_for_use_tree(parent_prefix={:?}, \
uniform_paths_canary_emitted={}, \
use_tree={:?}, nested={})",
parent_prefix, uniform_paths_canary_emitted, use_tree, nested);
let is_prelude = attr::contains_name(&item.attrs, "prelude_import");
let uniform_paths =
self.session.rust_2018() &&
self.session.features_untracked().uniform_paths;
@ -215,8 +215,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
subclass,
source.ident.span,
id,
root_use_tree.span,
root_id,
root_span,
item.id,
ty::Visibility::Invisible,
parent_scope.clone(),
true, // is_uniform_paths_canary
@ -345,8 +345,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
subclass,
use_tree.span,
id,
root_use_tree.span,
root_id,
root_span,
item.id,
vis,
parent_scope,
false, // is_uniform_paths_canary
@ -354,7 +354,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
}
ast::UseTreeKind::Glob => {
let subclass = GlobImport {
is_prelude,
is_prelude: attr::contains_name(&item.attrs, "prelude_import"),
max_vis: Cell::new(ty::Visibility::Invisible),
};
self.add_import_directive(
@ -362,8 +362,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
subclass,
use_tree.span,
id,
root_use_tree.span,
root_id,
root_span,
item.id,
vis,
parent_scope,
false, // is_uniform_paths_canary
@ -394,16 +394,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
for &(ref tree, id) in items {
self.build_reduced_graph_for_use_tree(
root_use_tree,
root_id,
tree,
id,
vis,
&prefix,
uniform_paths_canary_emitted,
true,
item,
parent_scope.clone(),
// This particular use tree
tree, id, &prefix, true, uniform_paths_canary_emitted,
// The whole `use` item
parent_scope.clone(), item, vis, root_span,
);
}
}
@ -421,16 +415,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
match item.node {
ItemKind::Use(ref use_tree) => {
self.build_reduced_graph_for_use_tree(
use_tree,
item.id,
use_tree,
item.id,
vis,
&[],
false, // uniform_paths_canary_emitted
false,
item,
parent_scope,
// This particular use tree
use_tree, item.id, &[], false, false,
// The whole `use` item
parent_scope, item, vis, use_tree.span,
);
}

View File

@ -9,6 +9,7 @@
// except according to those terms.
use {CrateLint, PathResult, Segment};
use macros::ParentScope;
use std::collections::BTreeSet;
@ -23,7 +24,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
pub(crate) fn make_path_suggestion(
&mut self,
span: Span,
path: Vec<Segment>
path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<Vec<Segment>> {
debug!("make_path_suggestion: span={:?} path={:?}", span, path);
// If we don't have a path to suggest changes to, then return.
@ -40,10 +42,12 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
(Some(fst), Some(snd)) if !is_special(fst.ident) && !is_special(snd.ident) => {
debug!("make_path_suggestion: fst={:?} snd={:?}", fst, snd);
self.make_missing_self_suggestion(span, path.clone())
.or_else(|| self.make_missing_crate_suggestion(span, path.clone()))
.or_else(|| self.make_missing_super_suggestion(span, path.clone()))
.or_else(|| self.make_external_crate_suggestion(span, path))
self.make_missing_self_suggestion(span, path.clone(), parent_scope)
.or_else(|| self.make_missing_crate_suggestion(span, path.clone(),
parent_scope))
.or_else(|| self.make_missing_super_suggestion(span, path.clone(),
parent_scope))
.or_else(|| self.make_external_crate_suggestion(span, path, parent_scope))
},
_ => None,
}
@ -59,11 +63,12 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
fn make_missing_self_suggestion(
&mut self,
span: Span,
mut path: Vec<Segment>
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<Vec<Segment>> {
// Replace first ident with `self` and check if that is valid.
path[0].ident.name = keywords::SelfValue.name();
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result {
Some(path)
@ -82,11 +87,12 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
fn make_missing_crate_suggestion(
&mut self,
span: Span,
mut path: Vec<Segment>
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<Vec<Segment>> {
// Replace first ident with `crate` and check if that is valid.
path[0].ident.name = keywords::Crate.name();
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result {
Some(path)
@ -105,11 +111,12 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
fn make_missing_super_suggestion(
&mut self,
span: Span,
mut path: Vec<Segment>
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<Vec<Segment>> {
// Replace first ident with `crate` and check if that is valid.
path[0].ident.name = keywords::Super.name();
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result {
Some(path)
@ -131,7 +138,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
fn make_external_crate_suggestion(
&mut self,
span: Span,
mut path: Vec<Segment>
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<Vec<Segment>> {
// Need to clone else we can't call `resolve_path` without a borrow error. We also store
// into a `BTreeMap` so we can get consistent ordering (and therefore the same diagnostic)
@ -149,7 +157,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
// Replace the first after root (a placeholder we inserted) with a crate name
// and check if that is valid.
path[1].ident.name = *name;
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
let result =
self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}",
name, path, result);
if let PathResult::Module(..) = result {

View File

@ -1054,7 +1054,7 @@ pub struct ModuleData<'a> {
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
legacy_macro_resolutions: RefCell<Vec<(Ident, MacroKind, ParentScope<'a>,
Option<&'a NameBinding<'a>>)>>,
macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>,
macro_resolutions: RefCell<Vec<(Vec<Segment>, ParentScope<'a>, Span)>>,
builtin_attrs: RefCell<Vec<(Ident, ParentScope<'a>)>>,
// Macro invocations that can expand into items in this module.
@ -1668,22 +1668,15 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
let segments = &path.segments;
let path = Segment::from_path(&path);
// FIXME (Manishearth): Intra doc links won't get warned of epoch changes
let def = match self.resolve_path(None, &path, Some(namespace), true, span, CrateLint::No) {
let def = match self.resolve_path_without_parent_scope(None, &path, Some(namespace),
true, span, CrateLint::No) {
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
module.def().unwrap(),
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
path_res.base_def(),
PathResult::NonModule(..) => {
if let PathResult::Failed(span, msg, _) = self.resolve_path(
None,
&path,
None,
true,
span,
CrateLint::No,
) {
error_callback(self, span, ResolutionError::FailedToResolve(&msg));
}
let msg = "type-relative paths are not supported in this context";
error_callback(self, span, ResolutionError::FailedToResolve(msg));
Def::Err
}
PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
@ -2530,10 +2523,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
new_id = Some(def.def_id());
let span = trait_ref.path.span;
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
self.resolve_path(
self.resolve_path_without_parent_scope(
None,
&path,
None,
Some(TypeNS),
false,
span,
CrateLint::SimplePath(trait_ref.ref_id),
@ -3055,8 +3048,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
(String::new(), "the crate root".to_string())
} else {
let mod_path = &path[..path.len() - 1];
let mod_prefix = match this.resolve_path(None, mod_path, Some(TypeNS),
false, span, CrateLint::No) {
let mod_prefix = match this.resolve_path_without_parent_scope(
None, mod_path, Some(TypeNS), false, span, CrateLint::No
) {
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
module.def(),
_ => None,
@ -3540,7 +3534,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
));
}
let result = match self.resolve_path(
let result = match self.resolve_path_without_parent_scope(
None,
&path,
Some(ns),
@ -3587,7 +3581,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
path[0].ident.name != keywords::CrateRoot.name() &&
path[0].ident.name != keywords::DollarCrate.name() {
let unqualified_result = {
match self.resolve_path(
match self.resolve_path_without_parent_scope(
None,
&[*path.last().unwrap()],
Some(ns),
@ -3610,7 +3604,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
Some(result)
}
fn resolve_path(
fn resolve_path_without_parent_scope(
&mut self,
base_module: Option<ModuleOrUniformRoot<'a>>,
path: &[Segment],
@ -3619,12 +3613,15 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
path_span: Span,
crate_lint: CrateLint,
) -> PathResult<'a> {
// Macro and import paths must have full parent scope available during resolution,
// other paths will do okay with parent module alone.
assert!(opt_ns != None && opt_ns != Some(MacroNS));
let parent_scope = ParentScope { module: self.current_module, ..self.dummy_parent_scope() };
self.resolve_path_with_parent_scope(base_module, path, opt_ns, &parent_scope,
self.resolve_path(base_module, path, opt_ns, &parent_scope,
record_used, path_span, crate_lint)
}
fn resolve_path_with_parent_scope(
fn resolve_path(
&mut self,
base_module: Option<ModuleOrUniformRoot<'a>>,
path: &[Segment],
@ -3820,7 +3817,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
PathResult::Module(module.unwrap_or_else(|| {
span_bug!(path_span, "resolve_path: empty(?) path {:?} has no module", path);
}))
}
fn lint_if_path_starts_with_module(
@ -4104,8 +4100,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
} else {
// Search in module.
let mod_path = &path[..path.len() - 1];
if let PathResult::Module(module) = self.resolve_path(None, mod_path, Some(TypeNS),
false, span, CrateLint::No) {
if let PathResult::Module(module) = self.resolve_path_without_parent_scope(
None, mod_path, Some(TypeNS), false, span, CrateLint::No
) {
if let ModuleOrUniformRoot::Module(module) = module {
add_module_candidates(module, &mut names);
}

View File

@ -462,7 +462,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
parent_scope: &ParentScope<'a>,
force: bool,
) -> Result<Def, Determinacy> {
let span = path.span;
let path_span = path.span;
let mut path = Segment::from_path(path);
// Possibly apply the macro helper hack
@ -474,15 +474,15 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
}
if path.len() > 1 {
let def = match self.resolve_path_with_parent_scope(None, &path, Some(MacroNS),
parent_scope, false, span,
CrateLint::No) {
let def = match self.resolve_path(None, &path, Some(MacroNS), parent_scope,
false, path_span, CrateLint::No) {
PathResult::NonModule(path_res) => match path_res.base_def() {
Def::Err => Err(Determinacy::Determined),
def @ _ => {
if path_res.unresolved_segments() > 0 {
self.found_unresolved_macro = true;
self.session.span_err(span, "fail to resolve non-ident macro path");
self.session.span_err(path_span,
"fail to resolve non-ident macro path");
Err(Determinacy::Determined)
} else {
Ok(def)
@ -498,16 +498,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
};
parent_scope.module.macro_resolutions.borrow_mut()
.push((path
.iter()
.map(|seg| seg.ident)
.collect::<Vec<Ident>>()
.into_boxed_slice(), span));
.push((path, parent_scope.clone(), path_span));
def
} else {
let binding = self.early_resolve_ident_in_lexical_scope(
path[0].ident, MacroNS, Some(kind), parent_scope, false, force, span
path[0].ident, MacroNS, Some(kind), parent_scope, false, force, path_span
);
match binding {
Ok(..) => {}
@ -851,9 +847,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
pub fn finalize_current_module_macro_resolutions(&mut self) {
let module = self.current_module;
for &(ref path, span) in module.macro_resolutions.borrow().iter() {
let path: Vec<_> = path.iter().map(|&ident| Segment::from_ident(ident)).collect();
match self.resolve_path(None, &path, Some(MacroNS), true, span, CrateLint::No) {
let macro_resolutions =
mem::replace(&mut *module.macro_resolutions.borrow_mut(), Vec::new());
for (mut path, parent_scope, path_span) in macro_resolutions {
// FIXME: Path resolution will ICE if segment IDs present.
for seg in &mut path { seg.id = None; }
match self.resolve_path(None, &path, Some(MacroNS), &parent_scope,
true, path_span, CrateLint::No) {
PathResult::NonModule(_) => {},
PathResult::Failed(span, msg, _) => {
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));

View File

@ -877,6 +877,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
}),
&directive.module_path[..],
None,
&directive.parent_scope,
false,
directive.span,
directive.crate_lint(),
@ -956,6 +957,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
}),
&module_path,
None,
&directive.parent_scope,
true,
span,
directive.crate_lint(),
@ -968,7 +970,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
}
PathResult::Failed(span, msg, true) => {
return if let Some(suggested_path) = self.make_path_suggestion(
span, module_path.clone()
span, module_path.clone(), &directive.parent_scope
) {
Some((
span,