resolve: Decouple scope visiting process from visitor actions
This commit is contained in:
parent
b302f62cbc
commit
1e1b081e0e
@ -109,6 +109,7 @@ impl Determinacy {
|
||||
/// A specific scope in which a name can be looked up.
|
||||
/// This enum is currently used only for early resolution (imports and macros),
|
||||
/// but not for late resolution yet.
|
||||
#[derive(Clone, Copy)]
|
||||
enum Scope<'a> {
|
||||
DeriveHelpers,
|
||||
MacroRules(LegacyScope<'a>),
|
||||
@ -2143,6 +2144,128 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A generic scope visitor.
|
||||
/// Visits scopes in order to resolve some identifier in them or perform other actions.
|
||||
/// If the callback returns `Some` result, we stop visiting scopes and return it.
|
||||
fn visit_scopes<T>(
|
||||
&mut self,
|
||||
scope_set: ScopeSet,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
mut ident: Ident,
|
||||
mut visitor: impl FnMut(&mut Self, Scope<'a>, Ident) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
// General principles:
|
||||
// 1. Not controlled (user-defined) names should have higher priority than controlled names
|
||||
// built into the language or standard library. This way we can add new names into the
|
||||
// language or standard library without breaking user code.
|
||||
// 2. "Closed set" below means new names cannot appear after the current resolution attempt.
|
||||
// Places to search (in order of decreasing priority):
|
||||
// (Type NS)
|
||||
// 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet
|
||||
// (open set, not controlled).
|
||||
// 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
|
||||
// (open, not controlled).
|
||||
// 3. Extern prelude (open, the open part is from macro expansions, not controlled).
|
||||
// 4. Tool modules (closed, controlled right now, but not in the future).
|
||||
// 5. Standard library prelude (de-facto closed, controlled).
|
||||
// 6. Language prelude (closed, controlled).
|
||||
// (Value NS)
|
||||
// 1. FIXME: Ribs (local variables), there's no necessary infrastructure yet
|
||||
// (open set, not controlled).
|
||||
// 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
|
||||
// (open, not controlled).
|
||||
// 3. Standard library prelude (de-facto closed, controlled).
|
||||
// (Macro NS)
|
||||
// 1-3. Derive helpers (open, not controlled). All ambiguities with other names
|
||||
// are currently reported as errors. They should be higher in priority than preludes
|
||||
// and probably even names in modules according to the "general principles" above. They
|
||||
// also should be subject to restricted shadowing because are effectively produced by
|
||||
// derives (you need to resolve the derive first to add helpers into scope), but they
|
||||
// should be available before the derive is expanded for compatibility.
|
||||
// It's mess in general, so we are being conservative for now.
|
||||
// 1-3. `macro_rules` (open, not controlled), loop through legacy scopes. Have higher
|
||||
// priority than prelude macros, but create ambiguities with macros in modules.
|
||||
// 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
|
||||
// (open, not controlled). Have higher priority than prelude macros, but create
|
||||
// ambiguities with `macro_rules`.
|
||||
// 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled).
|
||||
// 4a. User-defined prelude from macro-use
|
||||
// (open, the open part is from macro expansions, not controlled).
|
||||
// 4b. Standard library prelude is currently implemented as `macro-use` (closed, controlled)
|
||||
// 5. Language prelude: builtin macros (closed, controlled, except for legacy plugins).
|
||||
// 6. Language prelude: builtin attributes (closed, controlled).
|
||||
// 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers,
|
||||
// but introduced by legacy plugins using `register_attribute`. Priority is somewhere
|
||||
// in prelude, not sure where exactly (creates ambiguities with any other prelude names).
|
||||
|
||||
let (ns, is_absolute_path) = match scope_set {
|
||||
ScopeSet::Import(ns) => (ns, false),
|
||||
ScopeSet::AbsolutePath(ns) => (ns, true),
|
||||
ScopeSet::Macro(_) => (MacroNS, false),
|
||||
ScopeSet::Module => (TypeNS, false),
|
||||
};
|
||||
let mut scope = match ns {
|
||||
_ if is_absolute_path => Scope::CrateRoot,
|
||||
TypeNS | ValueNS => Scope::Module(parent_scope.module),
|
||||
MacroNS => Scope::DeriveHelpers,
|
||||
};
|
||||
|
||||
loop {
|
||||
if let break_result @ Some(..) = visitor(self, scope, ident) {
|
||||
return break_result;
|
||||
}
|
||||
|
||||
scope = match scope {
|
||||
Scope::DeriveHelpers =>
|
||||
Scope::MacroRules(parent_scope.legacy),
|
||||
Scope::MacroRules(legacy_scope) => match legacy_scope {
|
||||
LegacyScope::Binding(binding) => Scope::MacroRules(
|
||||
binding.parent_legacy_scope
|
||||
),
|
||||
LegacyScope::Invocation(invoc) => Scope::MacroRules(
|
||||
invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope)
|
||||
),
|
||||
LegacyScope::Empty => Scope::Module(parent_scope.module),
|
||||
}
|
||||
Scope::CrateRoot => match ns {
|
||||
TypeNS => {
|
||||
ident.span.adjust(Mark::root());
|
||||
Scope::ExternPrelude
|
||||
}
|
||||
ValueNS | MacroNS => break,
|
||||
}
|
||||
Scope::Module(module) => {
|
||||
match self.hygienic_lexical_parent(module, &mut ident.span) {
|
||||
Some(parent_module) => Scope::Module(parent_module),
|
||||
None => {
|
||||
ident.span.adjust(Mark::root());
|
||||
match ns {
|
||||
TypeNS => Scope::ExternPrelude,
|
||||
ValueNS => Scope::StdLibPrelude,
|
||||
MacroNS => Scope::MacroUsePrelude,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Scope::MacroUsePrelude => Scope::StdLibPrelude,
|
||||
Scope::BuiltinMacros => Scope::BuiltinAttrs,
|
||||
Scope::BuiltinAttrs => Scope::LegacyPluginHelpers,
|
||||
Scope::LegacyPluginHelpers => break, // nowhere else to search
|
||||
Scope::ExternPrelude if is_absolute_path => break,
|
||||
Scope::ExternPrelude => Scope::ToolPrelude,
|
||||
Scope::ToolPrelude => Scope::StdLibPrelude,
|
||||
Scope::StdLibPrelude => match ns {
|
||||
TypeNS => Scope::BuiltinTypes,
|
||||
ValueNS => break, // nowhere else to search
|
||||
MacroNS => Scope::BuiltinMacros,
|
||||
}
|
||||
Scope::BuiltinTypes => break, // nowhere else to search
|
||||
};
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
|
||||
/// More specifically, we proceed up the hierarchy of scopes and return the binding for
|
||||
/// `ident` in the first scope that defines it (or None if no scopes define it).
|
||||
|
@ -59,7 +59,7 @@ impl<'a> InvocationData<'a> {
|
||||
pub struct LegacyBinding<'a> {
|
||||
binding: &'a NameBinding<'a>,
|
||||
/// Legacy scope into which the `macro_rules` item was planted.
|
||||
parent_legacy_scope: LegacyScope<'a>,
|
||||
crate parent_legacy_scope: LegacyScope<'a>,
|
||||
ident: Ident,
|
||||
}
|
||||
|
||||
@ -421,50 +421,6 @@ impl<'a> Resolver<'a> {
|
||||
force: bool,
|
||||
path_span: Span,
|
||||
) -> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
// General principles:
|
||||
// 1. Not controlled (user-defined) names should have higher priority than controlled names
|
||||
// built into the language or standard library. This way we can add new names into the
|
||||
// language or standard library without breaking user code.
|
||||
// 2. "Closed set" below means new names cannot appear after the current resolution attempt.
|
||||
// Places to search (in order of decreasing priority):
|
||||
// (Type NS)
|
||||
// 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet
|
||||
// (open set, not controlled).
|
||||
// 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
|
||||
// (open, not controlled).
|
||||
// 3. Extern prelude (closed, not controlled).
|
||||
// 4. Tool modules (closed, controlled right now, but not in the future).
|
||||
// 5. Standard library prelude (de-facto closed, controlled).
|
||||
// 6. Language prelude (closed, controlled).
|
||||
// (Value NS)
|
||||
// 1. FIXME: Ribs (local variables), there's no necessary infrastructure yet
|
||||
// (open set, not controlled).
|
||||
// 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
|
||||
// (open, not controlled).
|
||||
// 3. Standard library prelude (de-facto closed, controlled).
|
||||
// (Macro NS)
|
||||
// 1-3. Derive helpers (open, not controlled). All ambiguities with other names
|
||||
// are currently reported as errors. They should be higher in priority than preludes
|
||||
// and probably even names in modules according to the "general principles" above. They
|
||||
// also should be subject to restricted shadowing because are effectively produced by
|
||||
// derives (you need to resolve the derive first to add helpers into scope), but they
|
||||
// should be available before the derive is expanded for compatibility.
|
||||
// It's mess in general, so we are being conservative for now.
|
||||
// 1-3. `macro_rules` (open, not controlled), loop through legacy scopes. Have higher
|
||||
// priority than prelude macros, but create ambiguities with macros in modules.
|
||||
// 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
|
||||
// (open, not controlled). Have higher priority than prelude macros, but create
|
||||
// ambiguities with `macro_rules`.
|
||||
// 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled).
|
||||
// 4a. User-defined prelude from macro-use
|
||||
// (open, the open part is from macro expansions, not controlled).
|
||||
// 4b. Standard library prelude is currently implemented as `macro-use` (closed, controlled)
|
||||
// 5. Language prelude: builtin macros (closed, controlled, except for legacy plugins).
|
||||
// 6. Language prelude: builtin attributes (closed, controlled).
|
||||
// 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers,
|
||||
// but introduced by legacy plugins using `register_attribute`. Priority is somewhere
|
||||
// in prelude, not sure where exactly (creates ambiguities with any other prelude names).
|
||||
|
||||
bitflags::bitflags! {
|
||||
struct Flags: u8 {
|
||||
const MACRO_RULES = 1 << 0;
|
||||
@ -477,13 +433,21 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
|
||||
assert!(force || !record_used); // `record_used` implies `force`
|
||||
let mut ident = orig_ident.modern();
|
||||
let ident = orig_ident.modern();
|
||||
|
||||
// Make sure `self`, `super` etc produce an error when passed to here.
|
||||
if ident.is_path_segment_keyword() {
|
||||
return Err(Determinacy::Determined);
|
||||
}
|
||||
|
||||
let rust_2015 = orig_ident.span.rust_2015();
|
||||
let (ns, macro_kind, is_import, is_absolute_path) = match scope_set {
|
||||
ScopeSet::Import(ns) => (ns, None, true, false),
|
||||
ScopeSet::AbsolutePath(ns) => (ns, None, false, true),
|
||||
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false, false),
|
||||
ScopeSet::Module => (TypeNS, None, false, false),
|
||||
};
|
||||
|
||||
// This is *the* result, resolution from the scope closest to the resolved identifier.
|
||||
// However, sometimes this result is "weak" because it comes from a glob import or
|
||||
// a macro expansion, and in this case it cannot shadow names from outer scopes, e.g.
|
||||
@ -496,34 +460,22 @@ impl<'a> Resolver<'a> {
|
||||
// So we have to save the innermost solution and continue searching in outer scopes
|
||||
// to detect potential ambiguities.
|
||||
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, is_absolute_path) = match scope_set {
|
||||
ScopeSet::Import(ns) => (ns, None, true, false),
|
||||
ScopeSet::AbsolutePath(ns) => (ns, None, false, true),
|
||||
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false, false),
|
||||
ScopeSet::Module => (TypeNS, None, false, false),
|
||||
};
|
||||
let mut where_to_resolve = match ns {
|
||||
_ if is_absolute_path => Scope::CrateRoot,
|
||||
TypeNS | ValueNS => Scope::Module(parent_scope.module),
|
||||
MacroNS => Scope::DeriveHelpers,
|
||||
};
|
||||
let mut use_prelude = !parent_scope.module.no_implicit_prelude;
|
||||
let mut determinacy = Determinacy::Determined;
|
||||
loop {
|
||||
let result = match where_to_resolve {
|
||||
|
||||
// Go through all the scopes and try to resolve the name.
|
||||
let break_result = self.visit_scopes(scope_set, parent_scope, ident, |this, scope, ident| {
|
||||
let result = match scope {
|
||||
Scope::DeriveHelpers => {
|
||||
let mut result = Err(Determinacy::Determined);
|
||||
for derive in &parent_scope.derives {
|
||||
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
|
||||
match self.resolve_macro_path(derive, MacroKind::Derive,
|
||||
match this.resolve_macro_path(derive, MacroKind::Derive,
|
||||
&parent_scope, true, force) {
|
||||
Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) {
|
||||
let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
|
||||
ty::Visibility::Public, derive.span, Mark::root())
|
||||
.to_name_binding(self.arenas);
|
||||
.to_name_binding(this.arenas);
|
||||
result = Ok((binding, Flags::empty()));
|
||||
break;
|
||||
}
|
||||
@ -543,8 +495,8 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
Scope::CrateRoot => {
|
||||
let root_ident = Ident::new(kw::PathRoot, orig_ident.span);
|
||||
let root_module = self.resolve_crate_root(root_ident);
|
||||
let binding = self.resolve_ident_in_module_ext(
|
||||
let root_module = this.resolve_crate_root(root_ident);
|
||||
let binding = this.resolve_ident_in_module_ext(
|
||||
ModuleOrUniformRoot::Module(root_module),
|
||||
orig_ident,
|
||||
ns,
|
||||
@ -555,15 +507,16 @@ impl<'a> Resolver<'a> {
|
||||
match binding {
|
||||
Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)),
|
||||
Err((Determinacy::Undetermined, Weak::No)) =>
|
||||
return Err(Determinacy::determined(force)),
|
||||
return Some(Err(Determinacy::determined(force))),
|
||||
Err((Determinacy::Undetermined, Weak::Yes)) =>
|
||||
Err(Determinacy::Undetermined),
|
||||
Err((Determinacy::Determined, _)) => Err(Determinacy::Determined),
|
||||
}
|
||||
}
|
||||
Scope::Module(module) => {
|
||||
let orig_current_module = mem::replace(&mut self.current_module, module);
|
||||
let binding = self.resolve_ident_in_module_unadjusted_ext(
|
||||
use_prelude = !module.no_implicit_prelude;
|
||||
let orig_current_module = mem::replace(&mut this.current_module, module);
|
||||
let binding = this.resolve_ident_in_module_unadjusted_ext(
|
||||
ModuleOrUniformRoot::Module(module),
|
||||
ident,
|
||||
ns,
|
||||
@ -572,10 +525,10 @@ impl<'a> Resolver<'a> {
|
||||
record_used,
|
||||
path_span,
|
||||
);
|
||||
self.current_module = orig_current_module;
|
||||
this.current_module = orig_current_module;
|
||||
match binding {
|
||||
Ok(binding) => {
|
||||
let misc_flags = if ptr::eq(module, self.graph_root) {
|
||||
let misc_flags = if ptr::eq(module, this.graph_root) {
|
||||
Flags::MISC_SUGGEST_CRATE
|
||||
} else if module.is_normal() {
|
||||
Flags::MISC_SUGGEST_SELF
|
||||
@ -585,7 +538,7 @@ impl<'a> Resolver<'a> {
|
||||
Ok((binding, Flags::MODULE | misc_flags))
|
||||
}
|
||||
Err((Determinacy::Undetermined, Weak::No)) =>
|
||||
return Err(Determinacy::determined(force)),
|
||||
return Some(Err(Determinacy::determined(force))),
|
||||
Err((Determinacy::Undetermined, Weak::Yes)) =>
|
||||
Err(Determinacy::Undetermined),
|
||||
Err((Determinacy::Determined, _)) => Err(Determinacy::Determined),
|
||||
@ -593,11 +546,11 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
Scope::MacroUsePrelude => {
|
||||
if use_prelude || rust_2015 {
|
||||
match self.macro_use_prelude.get(&ident.name).cloned() {
|
||||
match this.macro_use_prelude.get(&ident.name).cloned() {
|
||||
Some(binding) =>
|
||||
Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)),
|
||||
None => Err(Determinacy::determined(
|
||||
self.graph_root.unresolved_invocations.borrow().is_empty()
|
||||
this.graph_root.unresolved_invocations.borrow().is_empty()
|
||||
))
|
||||
}
|
||||
} else {
|
||||
@ -605,7 +558,7 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
Scope::BuiltinMacros => {
|
||||
match self.builtin_macros.get(&ident.name).cloned() {
|
||||
match this.builtin_macros.get(&ident.name).cloned() {
|
||||
Some(binding) => Ok((binding, Flags::PRELUDE)),
|
||||
None => Err(Determinacy::Determined),
|
||||
}
|
||||
@ -614,7 +567,7 @@ impl<'a> Resolver<'a> {
|
||||
if is_builtin_attr_name(ident.name) {
|
||||
let binding = (Res::NonMacroAttr(NonMacroAttrKind::Builtin),
|
||||
ty::Visibility::Public, DUMMY_SP, Mark::root())
|
||||
.to_name_binding(self.arenas);
|
||||
.to_name_binding(this.arenas);
|
||||
Ok((binding, Flags::PRELUDE))
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
@ -622,11 +575,11 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
Scope::LegacyPluginHelpers => {
|
||||
if (use_prelude || rust_2015) &&
|
||||
self.session.plugin_attributes.borrow().iter()
|
||||
this.session.plugin_attributes.borrow().iter()
|
||||
.any(|(name, _)| ident.name == *name) {
|
||||
let binding = (Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper),
|
||||
ty::Visibility::Public, DUMMY_SP, Mark::root())
|
||||
.to_name_binding(self.arenas);
|
||||
.to_name_binding(this.arenas);
|
||||
Ok((binding, Flags::PRELUDE))
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
@ -634,10 +587,10 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
Scope::ExternPrelude => {
|
||||
if use_prelude || is_absolute_path {
|
||||
match self.extern_prelude_get(ident, !record_used) {
|
||||
match this.extern_prelude_get(ident, !record_used) {
|
||||
Some(binding) => Ok((binding, Flags::PRELUDE)),
|
||||
None => Err(Determinacy::determined(
|
||||
self.graph_root.unresolved_invocations.borrow().is_empty()
|
||||
this.graph_root.unresolved_invocations.borrow().is_empty()
|
||||
)),
|
||||
}
|
||||
} else {
|
||||
@ -647,7 +600,7 @@ impl<'a> Resolver<'a> {
|
||||
Scope::ToolPrelude => {
|
||||
if use_prelude && is_known_tool(ident.name) {
|
||||
let binding = (Res::ToolMod, ty::Visibility::Public,
|
||||
DUMMY_SP, Mark::root()).to_name_binding(self.arenas);
|
||||
DUMMY_SP, Mark::root()).to_name_binding(this.arenas);
|
||||
Ok((binding, Flags::PRELUDE))
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
@ -656,8 +609,8 @@ impl<'a> Resolver<'a> {
|
||||
Scope::StdLibPrelude => {
|
||||
let mut result = Err(Determinacy::Determined);
|
||||
if use_prelude {
|
||||
if let Some(prelude) = self.prelude {
|
||||
if let Ok(binding) = self.resolve_ident_in_module_unadjusted(
|
||||
if let Some(prelude) = this.prelude {
|
||||
if let Ok(binding) = this.resolve_ident_in_module_unadjusted(
|
||||
ModuleOrUniformRoot::Module(prelude),
|
||||
ident,
|
||||
ns,
|
||||
@ -671,10 +624,10 @@ impl<'a> Resolver<'a> {
|
||||
result
|
||||
}
|
||||
Scope::BuiltinTypes => {
|
||||
match self.primitive_type_table.primitive_types.get(&ident.name).cloned() {
|
||||
match this.primitive_type_table.primitive_types.get(&ident.name).cloned() {
|
||||
Some(prim_ty) => {
|
||||
let binding = (Res::PrimTy(prim_ty), ty::Visibility::Public,
|
||||
DUMMY_SP, Mark::root()).to_name_binding(self.arenas);
|
||||
DUMMY_SP, Mark::root()).to_name_binding(this.arenas);
|
||||
Ok((binding, Flags::PRELUDE))
|
||||
}
|
||||
None => Err(Determinacy::Determined)
|
||||
@ -685,7 +638,7 @@ impl<'a> Resolver<'a> {
|
||||
match result {
|
||||
Ok((binding, flags)) if sub_namespace_match(binding.macro_kind(), macro_kind) => {
|
||||
if !record_used {
|
||||
return Ok(binding);
|
||||
return Some(Ok(binding));
|
||||
}
|
||||
|
||||
if let Some((innermost_binding, innermost_flags)) = innermost_result {
|
||||
@ -710,11 +663,11 @@ impl<'a> Resolver<'a> {
|
||||
Some(AmbiguityKind::LegacyHelperVsPrelude)
|
||||
} else if innermost_flags.contains(Flags::MACRO_RULES) &&
|
||||
flags.contains(Flags::MODULE) &&
|
||||
!self.disambiguate_legacy_vs_modern(innermost_binding,
|
||||
!this.disambiguate_legacy_vs_modern(innermost_binding,
|
||||
binding) ||
|
||||
flags.contains(Flags::MACRO_RULES) &&
|
||||
innermost_flags.contains(Flags::MODULE) &&
|
||||
!self.disambiguate_legacy_vs_modern(binding,
|
||||
!this.disambiguate_legacy_vs_modern(binding,
|
||||
innermost_binding) {
|
||||
Some(AmbiguityKind::LegacyVsModern)
|
||||
} else if innermost_binding.is_glob_import() {
|
||||
@ -735,7 +688,7 @@ impl<'a> Resolver<'a> {
|
||||
} else {
|
||||
AmbiguityErrorMisc::None
|
||||
};
|
||||
self.ambiguity_errors.push(AmbiguityError {
|
||||
this.ambiguity_errors.push(AmbiguityError {
|
||||
kind,
|
||||
ident: orig_ident,
|
||||
b1: innermost_binding,
|
||||
@ -743,7 +696,7 @@ impl<'a> Resolver<'a> {
|
||||
misc1: misc(innermost_flags),
|
||||
misc2: misc(flags),
|
||||
});
|
||||
return Ok(innermost_binding);
|
||||
return Some(Ok(innermost_binding));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -755,55 +708,11 @@ impl<'a> Resolver<'a> {
|
||||
Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined
|
||||
}
|
||||
|
||||
where_to_resolve = match where_to_resolve {
|
||||
Scope::DeriveHelpers =>
|
||||
Scope::MacroRules(parent_scope.legacy),
|
||||
Scope::MacroRules(legacy_scope) => match legacy_scope {
|
||||
LegacyScope::Binding(binding) => Scope::MacroRules(
|
||||
binding.parent_legacy_scope
|
||||
),
|
||||
LegacyScope::Invocation(invoc) => Scope::MacroRules(
|
||||
invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope)
|
||||
),
|
||||
LegacyScope::Empty => Scope::Module(parent_scope.module),
|
||||
}
|
||||
Scope::CrateRoot => match ns {
|
||||
TypeNS => {
|
||||
ident.span.adjust(Mark::root());
|
||||
Scope::ExternPrelude
|
||||
}
|
||||
ValueNS | MacroNS => break,
|
||||
}
|
||||
Scope::Module(module) => {
|
||||
match self.hygienic_lexical_parent(module, &mut ident.span) {
|
||||
Some(parent_module) => Scope::Module(parent_module),
|
||||
None => {
|
||||
ident.span.adjust(Mark::root());
|
||||
use_prelude = !module.no_implicit_prelude;
|
||||
match ns {
|
||||
TypeNS => Scope::ExternPrelude,
|
||||
ValueNS => Scope::StdLibPrelude,
|
||||
MacroNS => Scope::MacroUsePrelude,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Scope::MacroUsePrelude => Scope::StdLibPrelude,
|
||||
Scope::BuiltinMacros => Scope::BuiltinAttrs,
|
||||
Scope::BuiltinAttrs => Scope::LegacyPluginHelpers,
|
||||
Scope::LegacyPluginHelpers => break, // nowhere else to search
|
||||
Scope::ExternPrelude if is_absolute_path => break,
|
||||
Scope::ExternPrelude => Scope::ToolPrelude,
|
||||
Scope::ToolPrelude => Scope::StdLibPrelude,
|
||||
Scope::StdLibPrelude => match ns {
|
||||
TypeNS => Scope::BuiltinTypes,
|
||||
ValueNS => break, // nowhere else to search
|
||||
MacroNS => Scope::BuiltinMacros,
|
||||
}
|
||||
Scope::BuiltinTypes => break, // nowhere else to search
|
||||
};
|
||||
None
|
||||
});
|
||||
|
||||
continue;
|
||||
if let Some(break_result) = break_result {
|
||||
return break_result;
|
||||
}
|
||||
|
||||
// The first found solution was the only one, return it.
|
||||
|
Loading…
x
Reference in New Issue
Block a user