1
Fork 0

resolve: Generalize early_resolve_ident_in_lexical_scope slightly

Flatten `ModuleOrUniformRoot` variants
This commit is contained in:
Vadim Petrochenkov 2018-11-24 19:14:05 +03:00
parent c06e69ee70
commit 5e121756ef
3 changed files with 77 additions and 81 deletions

View file

@ -102,6 +102,12 @@ enum Weak {
No,
}
enum ScopeSet {
Import(Namespace),
Macro(MacroKind),
Module,
}
/// A free importable items suggested in case of resolution failure.
struct ImportSuggestion {
path: Path,
@ -997,22 +1003,19 @@ impl<'a> LexicalScopeBinding<'a> {
}
}
#[derive(Clone, Copy, PartialEq, Debug)]
enum UniformRootKind {
CurrentScope,
ExternPrelude,
}
#[derive(Copy, Clone, Debug)]
enum ModuleOrUniformRoot<'a> {
/// Regular module.
Module(Module<'a>),
/// This "virtual module" denotes either resolution in extern prelude
/// for paths starting with `::` on 2018 edition or `extern::`,
/// or resolution in current scope for single-segment imports.
UniformRoot(UniformRootKind),
/// Virtual module that denotes resolution in extern prelude.
/// Used for paths starting with `::` on 2018 edition or `extern::`.
ExternPrelude,
/// Virtual module that denotes resolution in current scope.
/// Used only for resolving single-segment imports. The reason it exists is that import paths
/// are always split into two parts, the first of which should be some kind of module.
CurrentScope,
}
impl<'a> PartialEq for ModuleOrUniformRoot<'a> {
@ -1020,8 +1023,8 @@ impl<'a> PartialEq for ModuleOrUniformRoot<'a> {
match (*self, *other) {
(ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) =>
ptr::eq(lhs, rhs),
(ModuleOrUniformRoot::UniformRoot(lhs), ModuleOrUniformRoot::UniformRoot(rhs)) =>
lhs == rhs,
(ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) => true,
(ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true,
_ => false,
}
}
@ -1758,8 +1761,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
error_callback(self, span, ResolutionError::FailedToResolve(msg));
Def::Err
}
PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
PathResult::Indeterminate => unreachable!(),
PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
PathResult::Failed(span, msg, _) => {
error_callback(self, span, ResolutionError::FailedToResolve(&msg));
Def::Err
@ -2220,11 +2222,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
self.current_module = self.macro_def_scope(def);
}
}
ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude) => {
ModuleOrUniformRoot::ExternPrelude => {
ident.span = ident.span.modern();
ident.span.adjust(Mark::root());
}
ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope) => {
ModuleOrUniformRoot::CurrentScope => {
// No adjustments
}
}
@ -3667,8 +3669,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
err_path_resolution()
}
PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
PathResult::Failed(..) => return None,
PathResult::Module(..) | PathResult::Failed(..) => return None,
PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"),
};
@ -3787,8 +3788,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
}
if name == keywords::Extern.name() ||
name == keywords::CrateRoot.name() && ident.span.rust_2018() {
module =
Some(ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude));
module = Some(ModuleOrUniformRoot::ExternPrelude);
continue;
}
if name == keywords::CrateRoot.name() ||
@ -3821,9 +3821,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
self.resolve_ident_in_module(module, ident, ns, None, record_used, path_span)
} else if opt_ns.is_none() || opt_ns == Some(MacroNS) {
assert!(ns == TypeNS);
self.early_resolve_ident_in_lexical_scope(ident, ns, None, opt_ns.is_none(),
parent_scope, record_used, record_used,
path_span)
let scopes = if opt_ns.is_none() { ScopeSet::Import(ns) } else { ScopeSet::Module };
self.early_resolve_ident_in_lexical_scope(ident, scopes, parent_scope, record_used,
record_used, path_span)
} else {
let record_used_id =
if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
@ -3912,8 +3912,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
PathResult::Module(match module {
Some(module) => module,
None if path.is_empty() =>
ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope),
None if path.is_empty() => ModuleOrUniformRoot::CurrentScope,
_ => span_bug!(path_span, "resolve_path: non-empty path `{:?}` has no module", path),
})
}

View file

@ -9,11 +9,11 @@
// except according to those terms.
use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
use {CrateLint, Resolver, ResolutionError, Segment, Weak};
use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding};
use {CrateLint, Resolver, ResolutionError, ScopeSet, Weak};
use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
use {is_known_tool, resolve_error};
use ModuleOrUniformRoot;
use Namespace::{self, *};
use Namespace::*;
use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
use resolve_imports::ImportResolver;
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex,
@ -502,7 +502,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
def
} else {
let binding = self.early_resolve_ident_in_lexical_scope(
path[0].ident, MacroNS, Some(kind), false, parent_scope, false, force, path_span
path[0].ident, ScopeSet::Macro(kind), parent_scope, false, force, path_span
);
match binding {
Ok(..) => {}
@ -527,9 +527,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
crate fn early_resolve_ident_in_lexical_scope(
&mut self,
orig_ident: Ident,
ns: Namespace,
macro_kind: Option<MacroKind>,
is_import: bool,
scope_set: ScopeSet,
parent_scope: &ParentScope<'a>,
record_used: bool,
force: bool,
@ -605,8 +603,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
}
assert!(force || !record_used); // `record_used` implies `force`
assert!(macro_kind.is_none() || !is_import); // `is_import` implies no macro kind
let rust_2015 = orig_ident.span.rust_2015();
let mut ident = orig_ident.modern();
// Make sure `self`, `super` etc produce an error when passed to here.
@ -628,6 +624,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
let mut innermost_result: Option<(&NameBinding, Flags)> = None;
// Go through all the scopes and try to resolve the name.
let rust_2015 = orig_ident.span.rust_2015();
let (ns, macro_kind, is_import) = match scope_set {
ScopeSet::Import(ns) => (ns, None, true),
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false),
ScopeSet::Module => (TypeNS, None, false),
};
let mut where_to_resolve = match ns {
_ if is_import && rust_2015 => WhereToResolve::CrateRoot,
TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
@ -1041,7 +1043,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
let macro_resolutions =
mem::replace(&mut *module.single_segment_macro_resolutions.borrow_mut(), Vec::new());
for (ident, kind, parent_scope, initial_binding) in macro_resolutions {
match self.early_resolve_ident_in_lexical_scope(ident, MacroNS, Some(kind), false,
match self.early_resolve_ident_in_lexical_scope(ident, ScopeSet::Macro(kind),
&parent_scope, true, true, ident.span) {
Ok(binding) => {
let initial_def = initial_binding.map(|initial_binding| {
@ -1067,7 +1069,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new());
for (ident, parent_scope) in builtin_attrs {
let _ = self.early_resolve_ident_in_lexical_scope(
ident, MacroNS, Some(MacroKind::Attr), false, &parent_scope, true, true, ident.span
ident, ScopeSet::Macro(MacroKind::Attr), &parent_scope, true, true, ident.span
);
}
}

View file

@ -11,7 +11,7 @@
use self::ImportDirectiveSubclass::*;
use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
use {CrateLint, Module, ModuleOrUniformRoot, PerNS, UniformRootKind, Weak};
use {CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, Weak};
use Namespace::{self, TypeNS, MacroNS};
use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
use {Resolver, Segment};
@ -162,10 +162,8 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
let module = match module {
ModuleOrUniformRoot::Module(module) => module,
ModuleOrUniformRoot::UniformRoot(uniform_root_kind) => {
ModuleOrUniformRoot::ExternPrelude => {
assert!(!restricted_shadowing);
match uniform_root_kind {
UniformRootKind::ExternPrelude => {
return if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
Ok(binding)
} else if !self.graph_root.unresolved_invocations.borrow().is_empty() {
@ -175,7 +173,8 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
Err((Determined, Weak::No))
}
}
UniformRootKind::CurrentScope => {
ModuleOrUniformRoot::CurrentScope => {
assert!(!restricted_shadowing);
let parent_scope =
parent_scope.expect("no parent scope for a single-segment import");
@ -196,12 +195,10 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
}
let binding = self.early_resolve_ident_in_lexical_scope(
ident, ns, None, true, parent_scope, record_used, record_used, path_span
ident, ScopeSet::Import(ns), parent_scope, record_used, record_used, path_span
);
return binding.map_err(|determinacy| (determinacy, Weak::No));
}
}
}
};
self.populate_module_if_necessary(module);
@ -333,7 +330,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
}
let module = match glob_import.imported_module.get() {
Some(ModuleOrUniformRoot::Module(module)) => module,
Some(ModuleOrUniformRoot::UniformRoot(_)) => continue,
Some(_) => continue,
None => return Err((Undetermined, Weak::Yes)),
};
let (orig_current_module, mut ident) = (self.current_module, ident.modern());
@ -966,9 +963,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
return if all_ns_failed {
let resolutions = match module {
ModuleOrUniformRoot::Module(module) =>
Some(module.resolutions.borrow()),
ModuleOrUniformRoot::UniformRoot(_) => None,
ModuleOrUniformRoot::Module(module) => Some(module.resolutions.borrow()),
_ => None,
};
let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
let names = resolutions.filter_map(|(&(ref i, _), resolution)| {
@ -1006,7 +1002,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
format!("no `{}` in the root{}", ident, lev_suggestion)
}
}
ModuleOrUniformRoot::UniformRoot(_) => {
_ => {
if !ident.is_path_segment_keyword() {
format!("no `{}` external crate{}", ident, lev_suggestion)
} else {
@ -1107,9 +1103,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
let module = match directive.imported_module.get().unwrap() {
ModuleOrUniformRoot::Module(module) => module,
ModuleOrUniformRoot::UniformRoot(_) => {
self.session.span_err(directive.span,
"cannot glob-import all possible crates");
_ => {
self.session.span_err(directive.span, "cannot glob-import all possible crates");
return;
}
};