resolve: Generalize early_resolve_ident_in_lexical_scope
slightly
Flatten `ModuleOrUniformRoot` variants
This commit is contained in:
parent
c06e69ee70
commit
5e121756ef
3 changed files with 77 additions and 81 deletions
|
@ -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),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,45 +162,42 @@ 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() {
|
||||
// Macro-expanded `extern crate` items can add names to extern prelude.
|
||||
Err((Undetermined, Weak::No))
|
||||
} else {
|
||||
Err((Determined, Weak::No))
|
||||
}
|
||||
}
|
||||
UniformRootKind::CurrentScope => {
|
||||
let parent_scope =
|
||||
parent_scope.expect("no parent scope for a single-segment import");
|
||||
return if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
|
||||
Ok(binding)
|
||||
} else if !self.graph_root.unresolved_invocations.borrow().is_empty() {
|
||||
// Macro-expanded `extern crate` items can add names to extern prelude.
|
||||
Err((Undetermined, Weak::No))
|
||||
} else {
|
||||
Err((Determined, Weak::No))
|
||||
}
|
||||
}
|
||||
ModuleOrUniformRoot::CurrentScope => {
|
||||
assert!(!restricted_shadowing);
|
||||
let parent_scope =
|
||||
parent_scope.expect("no parent scope for a single-segment import");
|
||||
|
||||
if ns == TypeNS {
|
||||
if ident.name == keywords::Crate.name() ||
|
||||
ident.name == keywords::DollarCrate.name() {
|
||||
let module = self.resolve_crate_root(ident);
|
||||
let binding = (module, ty::Visibility::Public,
|
||||
module.span, Mark::root())
|
||||
.to_name_binding(self.arenas);
|
||||
return Ok(binding);
|
||||
} else if ident.name == keywords::Super.name() ||
|
||||
ident.name == keywords::SelfValue.name() {
|
||||
// FIXME: Implement these with renaming requirements so that e.g.
|
||||
// `use super;` doesn't work, but `use super as name;` does.
|
||||
// Fall through here to get an error from `early_resolve_...`.
|
||||
}
|
||||
}
|
||||
|
||||
let binding = self.early_resolve_ident_in_lexical_scope(
|
||||
ident, ns, None, true, parent_scope, record_used, record_used, path_span
|
||||
);
|
||||
return binding.map_err(|determinacy| (determinacy, Weak::No));
|
||||
if ns == TypeNS {
|
||||
if ident.name == keywords::Crate.name() ||
|
||||
ident.name == keywords::DollarCrate.name() {
|
||||
let module = self.resolve_crate_root(ident);
|
||||
let binding = (module, ty::Visibility::Public,
|
||||
module.span, Mark::root())
|
||||
.to_name_binding(self.arenas);
|
||||
return Ok(binding);
|
||||
} else if ident.name == keywords::Super.name() ||
|
||||
ident.name == keywords::SelfValue.name() {
|
||||
// FIXME: Implement these with renaming requirements so that e.g.
|
||||
// `use super;` doesn't work, but `use super as name;` does.
|
||||
// Fall through here to get an error from `early_resolve_...`.
|
||||
}
|
||||
}
|
||||
|
||||
let binding = self.early_resolve_ident_in_lexical_scope(
|
||||
ident, ScopeSet::Import(ns), parent_scope, record_used, record_used, path_span
|
||||
);
|
||||
return binding.map_err(|determinacy| (determinacy, Weak::No));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue