resolve: More precise determinacy tracking during import/macro resolution
This commit is contained in:
parent
f0ea1c6f1e
commit
1cfd08c0c4
5 changed files with 166 additions and 133 deletions
|
@ -863,7 +863,6 @@ impl<'a, 'b, 'cl> BuildReducedGraphVisitor<'a, 'b, 'cl> {
|
||||||
let invocation = self.resolver.invocations[&mark];
|
let invocation = self.resolver.invocations[&mark];
|
||||||
invocation.module.set(self.resolver.current_module);
|
invocation.module.set(self.resolver.current_module);
|
||||||
invocation.parent_legacy_scope.set(self.current_legacy_scope);
|
invocation.parent_legacy_scope.set(self.current_legacy_scope);
|
||||||
invocation.output_legacy_scope.set(self.current_legacy_scope);
|
|
||||||
invocation
|
invocation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,12 @@ fn is_known_tool(name: Name) -> bool {
|
||||||
["clippy", "rustfmt"].contains(&&*name.as_str())
|
["clippy", "rustfmt"].contains(&&*name.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum DeterminacyExt {
|
||||||
|
Determined,
|
||||||
|
Undetermined,
|
||||||
|
WeakUndetermined,
|
||||||
|
}
|
||||||
|
|
||||||
/// A free importable items suggested in case of resolution failure.
|
/// A free importable items suggested in case of resolution failure.
|
||||||
struct ImportSuggestion {
|
struct ImportSuggestion {
|
||||||
path: Path,
|
path: Path,
|
||||||
|
@ -2022,7 +2028,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||||
ModuleOrUniformRoot::Module(module),
|
ModuleOrUniformRoot::Module(module),
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
false,
|
|
||||||
record_used,
|
record_used,
|
||||||
path_span,
|
path_span,
|
||||||
);
|
);
|
||||||
|
@ -2053,7 +2058,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||||
ModuleOrUniformRoot::Module(module),
|
ModuleOrUniformRoot::Module(module),
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
false,
|
|
||||||
record_used,
|
record_used,
|
||||||
path_span,
|
path_span,
|
||||||
);
|
);
|
||||||
|
@ -2095,7 +2099,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
false,
|
false,
|
||||||
false,
|
|
||||||
path_span,
|
path_span,
|
||||||
) {
|
) {
|
||||||
return Some(LexicalScopeBinding::Item(binding));
|
return Some(LexicalScopeBinding::Item(binding));
|
||||||
|
@ -2170,7 +2173,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let result = self.resolve_ident_in_module_unadjusted(
|
let result = self.resolve_ident_in_module_unadjusted(
|
||||||
module, ident, ns, false, record_used, span,
|
module, ident, ns, record_used, span,
|
||||||
);
|
);
|
||||||
self.current_module = orig_current_module;
|
self.current_module = orig_current_module;
|
||||||
result
|
result
|
||||||
|
@ -4411,7 +4414,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
false,
|
false,
|
||||||
false,
|
|
||||||
module.span,
|
module.span,
|
||||||
).is_ok() {
|
).is_ok() {
|
||||||
let import_id = match binding.kind {
|
let import_id = match binding.kind {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
|
use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
|
||||||
use {CrateLint, Resolver, ResolutionError, is_known_tool, resolve_error};
|
use {CrateLint, DeterminacyExt, Resolver, ResolutionError, is_known_tool, resolve_error};
|
||||||
use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding};
|
use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding};
|
||||||
use ModuleOrUniformRoot;
|
use ModuleOrUniformRoot;
|
||||||
use Namespace::{self, *};
|
use Namespace::{self, *};
|
||||||
|
@ -54,8 +54,8 @@ pub struct InvocationData<'a> {
|
||||||
crate parent_legacy_scope: Cell<LegacyScope<'a>>,
|
crate parent_legacy_scope: Cell<LegacyScope<'a>>,
|
||||||
/// Legacy scope *produced* by expanding this macro invocation,
|
/// Legacy scope *produced* by expanding this macro invocation,
|
||||||
/// includes all the macro_rules items, other invocations, etc generated by it.
|
/// includes all the macro_rules items, other invocations, etc generated by it.
|
||||||
/// Set to the parent scope if the macro is not expanded yet (as if the macro produced nothing).
|
/// `None` if the macro is not expanded yet.
|
||||||
crate output_legacy_scope: Cell<LegacyScope<'a>>,
|
crate output_legacy_scope: Cell<Option<LegacyScope<'a>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> InvocationData<'a> {
|
impl<'a> InvocationData<'a> {
|
||||||
|
@ -64,7 +64,7 @@ impl<'a> InvocationData<'a> {
|
||||||
module: Cell::new(graph_root),
|
module: Cell::new(graph_root),
|
||||||
def_index: CRATE_DEF_INDEX,
|
def_index: CRATE_DEF_INDEX,
|
||||||
parent_legacy_scope: Cell::new(LegacyScope::Empty),
|
parent_legacy_scope: Cell::new(LegacyScope::Empty),
|
||||||
output_legacy_scope: Cell::new(LegacyScope::Empty),
|
output_legacy_scope: Cell::new(Some(LegacyScope::Empty)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ pub struct ParentScope<'a> {
|
||||||
// Macro namespace is separated into two sub-namespaces, one for bang macros and
|
// Macro namespace is separated into two sub-namespaces, one for bang macros and
|
||||||
// one for attribute-like macros (attributes, derives).
|
// one for attribute-like macros (attributes, derives).
|
||||||
// We ignore resolutions from one sub-namespace when searching names in scope for another.
|
// We ignore resolutions from one sub-namespace when searching names in scope for another.
|
||||||
fn sub_namespace_mismatch(requirement: Option<MacroKind>, candidate: Option<MacroKind>) -> bool {
|
fn sub_namespace_match(candidate: Option<MacroKind>, requirement: Option<MacroKind>) -> bool {
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
enum SubNS { Bang, AttrLike }
|
enum SubNS { Bang, AttrLike }
|
||||||
let sub_ns = |kind| match kind {
|
let sub_ns = |kind| match kind {
|
||||||
|
@ -121,7 +121,7 @@ fn sub_namespace_mismatch(requirement: Option<MacroKind>, candidate: Option<Macr
|
||||||
let requirement = requirement.and_then(|kind| sub_ns(kind));
|
let requirement = requirement.and_then(|kind| sub_ns(kind));
|
||||||
let candidate = candidate.and_then(|kind| sub_ns(kind));
|
let candidate = candidate.and_then(|kind| sub_ns(kind));
|
||||||
// "No specific sub-namespace" means "matches anything" for both requirements and candidates.
|
// "No specific sub-namespace" means "matches anything" for both requirements and candidates.
|
||||||
candidate.is_some() && requirement.is_some() && candidate != requirement
|
candidate.is_none() || requirement.is_none() || candidate == requirement
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
|
impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
|
||||||
|
@ -136,7 +136,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
|
||||||
module: Cell::new(module),
|
module: Cell::new(module),
|
||||||
def_index: module.def_id().unwrap().index,
|
def_index: module.def_id().unwrap().index,
|
||||||
parent_legacy_scope: Cell::new(LegacyScope::Empty),
|
parent_legacy_scope: Cell::new(LegacyScope::Empty),
|
||||||
output_legacy_scope: Cell::new(LegacyScope::Empty),
|
output_legacy_scope: Cell::new(Some(LegacyScope::Empty)),
|
||||||
}));
|
}));
|
||||||
mark
|
mark
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
|
||||||
expansion: mark,
|
expansion: mark,
|
||||||
};
|
};
|
||||||
fragment.visit_with(&mut visitor);
|
fragment.visit_with(&mut visitor);
|
||||||
invocation.output_legacy_scope.set(visitor.current_legacy_scope);
|
invocation.output_legacy_scope.set(Some(visitor.current_legacy_scope));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
|
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
|
||||||
|
@ -624,26 +624,36 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
let mut innermost_result: Option<(&NameBinding, Flags)> = None;
|
let mut innermost_result: Option<(&NameBinding, Flags)> = None;
|
||||||
|
|
||||||
// Go through all the scopes and try to resolve the name.
|
// Go through all the scopes and try to resolve the name.
|
||||||
let mut where_to_resolve = WhereToResolve::DeriveHelpers;
|
let mut where_to_resolve = if ns == MacroNS {
|
||||||
|
WhereToResolve::DeriveHelpers
|
||||||
|
} else {
|
||||||
|
WhereToResolve::Module(parent_scope.module)
|
||||||
|
};
|
||||||
let mut use_prelude = !parent_scope.module.no_implicit_prelude;
|
let mut use_prelude = !parent_scope.module.no_implicit_prelude;
|
||||||
|
let mut determinacy = Determinacy::Determined;
|
||||||
loop {
|
loop {
|
||||||
let result = match where_to_resolve {
|
let result = match where_to_resolve {
|
||||||
WhereToResolve::DeriveHelpers => {
|
WhereToResolve::DeriveHelpers => {
|
||||||
let mut result = Err(Determinacy::Determined);
|
let mut result = Err(Determinacy::Determined);
|
||||||
for derive in &parent_scope.derives {
|
for derive in &parent_scope.derives {
|
||||||
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
|
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
|
||||||
if let Ok((_, ext)) = self.resolve_macro_to_def(derive, MacroKind::Derive,
|
match self.resolve_macro_to_def(derive, MacroKind::Derive,
|
||||||
&parent_scope, force) {
|
&parent_scope, force) {
|
||||||
if let SyntaxExtension::ProcMacroDerive(_, helper_attrs, _) = &*ext {
|
Ok((_, ext)) => {
|
||||||
if helper_attrs.contains(&ident.name) {
|
if let SyntaxExtension::ProcMacroDerive(_, helpers, _) = &*ext {
|
||||||
let binding =
|
if helpers.contains(&ident.name) {
|
||||||
(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
|
let binding =
|
||||||
ty::Visibility::Public, derive.span, Mark::root())
|
(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
|
||||||
.to_name_binding(self.arenas);
|
ty::Visibility::Public, derive.span, Mark::root())
|
||||||
result = Ok((binding, Flags::empty()));
|
.to_name_binding(self.arenas);
|
||||||
break;
|
result = Ok((binding, Flags::empty()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(Determinacy::Determined) => {}
|
||||||
|
Err(Determinacy::Undetermined) =>
|
||||||
|
result = Err(Determinacy::Undetermined),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
|
@ -651,11 +661,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
|
WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
|
||||||
LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
|
LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
|
||||||
Ok((legacy_binding.binding, Flags::MACRO_RULES)),
|
Ok((legacy_binding.binding, Flags::MACRO_RULES)),
|
||||||
|
LegacyScope::Invocation(invoc) if invoc.output_legacy_scope.get().is_none() =>
|
||||||
|
Err(Determinacy::Undetermined),
|
||||||
_ => Err(Determinacy::Determined),
|
_ => Err(Determinacy::Determined),
|
||||||
}
|
}
|
||||||
WhereToResolve::Module(module) => {
|
WhereToResolve::Module(module) => {
|
||||||
let orig_current_module = mem::replace(&mut self.current_module, module);
|
let orig_current_module = mem::replace(&mut self.current_module, module);
|
||||||
let binding = self.resolve_ident_in_module_unadjusted(
|
let binding = self.resolve_ident_in_module_unadjusted_ext(
|
||||||
ModuleOrUniformRoot::Module(module),
|
ModuleOrUniformRoot::Module(module),
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
|
@ -664,21 +676,33 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
path_span,
|
path_span,
|
||||||
);
|
);
|
||||||
self.current_module = orig_current_module;
|
self.current_module = orig_current_module;
|
||||||
let misc_flags = if module.is_normal() {
|
match binding {
|
||||||
Flags::MISC_SUGGEST_SELF
|
Ok(binding) => {
|
||||||
} else {
|
let misc_flags = if module.is_normal() {
|
||||||
Flags::empty()
|
Flags::MISC_SUGGEST_SELF
|
||||||
};
|
} else {
|
||||||
binding.map(|binding| (binding, Flags::MODULE | misc_flags))
|
Flags::empty()
|
||||||
|
};
|
||||||
|
Ok((binding, Flags::MODULE | misc_flags))
|
||||||
|
}
|
||||||
|
Err(DeterminacyExt::Undetermined) =>
|
||||||
|
return Err(Determinacy::determined(force)),
|
||||||
|
Err(DeterminacyExt::WeakUndetermined) => Err(Determinacy::Undetermined),
|
||||||
|
Err(DeterminacyExt::Determined) => Err(Determinacy::Determined),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WhereToResolve::MacroUsePrelude => {
|
WhereToResolve::MacroUsePrelude => {
|
||||||
let mut result = Err(Determinacy::Determined);
|
|
||||||
if use_prelude || self.session.rust_2015() {
|
if use_prelude || self.session.rust_2015() {
|
||||||
if let Some(binding) = self.macro_use_prelude.get(&ident.name).cloned() {
|
match self.macro_use_prelude.get(&ident.name).cloned() {
|
||||||
result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE));
|
Some(binding) =>
|
||||||
|
Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)),
|
||||||
|
None => Err(Determinacy::determined(
|
||||||
|
self.graph_root.unresolved_invocations.borrow().is_empty()
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Err(Determinacy::Determined)
|
||||||
}
|
}
|
||||||
result
|
|
||||||
}
|
}
|
||||||
WhereToResolve::BuiltinMacros => {
|
WhereToResolve::BuiltinMacros => {
|
||||||
match self.builtin_macros.get(&ident.name).cloned() {
|
match self.builtin_macros.get(&ident.name).cloned() {
|
||||||
|
@ -709,14 +733,17 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WhereToResolve::ExternPrelude => {
|
WhereToResolve::ExternPrelude => {
|
||||||
let mut result = Err(Determinacy::Determined);
|
|
||||||
if use_prelude {
|
if use_prelude {
|
||||||
if let Some(binding) = self.extern_prelude_get(ident, !record_used,
|
match self.extern_prelude_get(ident, !record_used,
|
||||||
innermost_result.is_some()) {
|
innermost_result.is_some()) {
|
||||||
result = Ok((binding, Flags::PRELUDE));
|
Some(binding) => Ok((binding, Flags::PRELUDE)),
|
||||||
|
None => Err(Determinacy::determined(
|
||||||
|
self.graph_root.unresolved_invocations.borrow().is_empty()
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Err(Determinacy::Determined)
|
||||||
}
|
}
|
||||||
result
|
|
||||||
}
|
}
|
||||||
WhereToResolve::ToolPrelude => {
|
WhereToResolve::ToolPrelude => {
|
||||||
if use_prelude && is_known_tool(ident.name) {
|
if use_prelude && is_known_tool(ident.name) {
|
||||||
|
@ -736,7 +763,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
false,
|
false,
|
||||||
false,
|
|
||||||
path_span,
|
path_span,
|
||||||
) {
|
) {
|
||||||
result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE));
|
result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE));
|
||||||
|
@ -757,54 +783,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! continue_search { () => {
|
|
||||||
where_to_resolve = match where_to_resolve {
|
|
||||||
WhereToResolve::DeriveHelpers =>
|
|
||||||
WhereToResolve::MacroRules(parent_scope.legacy),
|
|
||||||
WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
|
|
||||||
LegacyScope::Binding(binding) =>
|
|
||||||
WhereToResolve::MacroRules(binding.parent_legacy_scope),
|
|
||||||
LegacyScope::Invocation(invocation) =>
|
|
||||||
WhereToResolve::MacroRules(invocation.output_legacy_scope.get()),
|
|
||||||
LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
|
|
||||||
LegacyScope::Uninitialized => unreachable!(),
|
|
||||||
}
|
|
||||||
WhereToResolve::Module(module) => {
|
|
||||||
match self.hygienic_lexical_parent(module, &mut ident.span) {
|
|
||||||
Some(parent_module) => WhereToResolve::Module(parent_module),
|
|
||||||
None => {
|
|
||||||
use_prelude = !module.no_implicit_prelude;
|
|
||||||
match ns {
|
|
||||||
TypeNS => WhereToResolve::ExternPrelude,
|
|
||||||
ValueNS => WhereToResolve::StdLibPrelude,
|
|
||||||
MacroNS => WhereToResolve::MacroUsePrelude,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros,
|
|
||||||
WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
|
|
||||||
WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers,
|
|
||||||
WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search
|
|
||||||
WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
|
|
||||||
WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
|
|
||||||
WhereToResolve::StdLibPrelude => match ns {
|
|
||||||
TypeNS => WhereToResolve::BuiltinTypes,
|
|
||||||
ValueNS => break, // nowhere else to search
|
|
||||||
MacroNS => unreachable!(),
|
|
||||||
}
|
|
||||||
WhereToResolve::BuiltinTypes => break, // nowhere else to search
|
|
||||||
};
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}}
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok((binding, flags)) => {
|
Ok((binding, flags)) if sub_namespace_match(binding.macro_kind(), macro_kind) => {
|
||||||
if sub_namespace_mismatch(macro_kind, binding.macro_kind()) {
|
|
||||||
continue_search!();
|
|
||||||
}
|
|
||||||
|
|
||||||
if !record_used {
|
if !record_used {
|
||||||
return Ok(binding);
|
return Ok(binding);
|
||||||
}
|
}
|
||||||
|
@ -865,14 +845,52 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
// Found the first solution.
|
// Found the first solution.
|
||||||
innermost_result = Some((binding, flags));
|
innermost_result = Some((binding, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
continue_search!();
|
|
||||||
},
|
|
||||||
Err(Determinacy::Determined) => {
|
|
||||||
continue_search!();
|
|
||||||
}
|
}
|
||||||
Err(Determinacy::Undetermined) => return Err(Determinacy::determined(force)),
|
Ok(..) | Err(Determinacy::Determined) => {}
|
||||||
|
Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
where_to_resolve = match where_to_resolve {
|
||||||
|
WhereToResolve::DeriveHelpers =>
|
||||||
|
WhereToResolve::MacroRules(parent_scope.legacy),
|
||||||
|
WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
|
||||||
|
LegacyScope::Binding(binding) => WhereToResolve::MacroRules(
|
||||||
|
binding.parent_legacy_scope
|
||||||
|
),
|
||||||
|
LegacyScope::Invocation(invoc) => WhereToResolve::MacroRules(
|
||||||
|
invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope.get())
|
||||||
|
),
|
||||||
|
LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
|
||||||
|
LegacyScope::Uninitialized => unreachable!(),
|
||||||
|
}
|
||||||
|
WhereToResolve::Module(module) => {
|
||||||
|
match self.hygienic_lexical_parent(module, &mut ident.span) {
|
||||||
|
Some(parent_module) => WhereToResolve::Module(parent_module),
|
||||||
|
None => {
|
||||||
|
use_prelude = !module.no_implicit_prelude;
|
||||||
|
match ns {
|
||||||
|
TypeNS => WhereToResolve::ExternPrelude,
|
||||||
|
ValueNS => WhereToResolve::StdLibPrelude,
|
||||||
|
MacroNS => WhereToResolve::MacroUsePrelude,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros,
|
||||||
|
WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
|
||||||
|
WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers,
|
||||||
|
WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search
|
||||||
|
WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
|
||||||
|
WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
|
||||||
|
WhereToResolve::StdLibPrelude => match ns {
|
||||||
|
TypeNS => WhereToResolve::BuiltinTypes,
|
||||||
|
ValueNS => break, // nowhere else to search
|
||||||
|
MacroNS => unreachable!(),
|
||||||
|
}
|
||||||
|
WhereToResolve::BuiltinTypes => break, // nowhere else to search
|
||||||
|
};
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first found solution was the only one, return it.
|
// The first found solution was the only one, return it.
|
||||||
|
@ -880,7 +898,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
return Ok(binding);
|
return Ok(binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
let determinacy = Determinacy::determined(force);
|
let determinacy = Determinacy::determined(determinacy == Determinacy::Determined || force);
|
||||||
if determinacy == Determinacy::Determined && macro_kind == Some(MacroKind::Attr) {
|
if determinacy == Determinacy::Determined && macro_kind == Some(MacroKind::Attr) {
|
||||||
// For single-segment attributes interpret determinate "no resolution" as a custom
|
// For single-segment attributes interpret determinate "no resolution" as a custom
|
||||||
// attribute. (Lexical resolution implies the first segment and attr kind should imply
|
// attribute. (Lexical resolution implies the first segment and attr kind should imply
|
||||||
|
@ -1026,7 +1044,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
def_index: invoc.def_index,
|
def_index: invoc.def_index,
|
||||||
module: Cell::new(graph_root),
|
module: Cell::new(graph_root),
|
||||||
parent_legacy_scope: Cell::new(LegacyScope::Uninitialized),
|
parent_legacy_scope: Cell::new(LegacyScope::Uninitialized),
|
||||||
output_legacy_scope: Cell::new(LegacyScope::Uninitialized),
|
output_legacy_scope: Cell::new(None),
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
use self::ImportDirectiveSubclass::*;
|
use self::ImportDirectiveSubclass::*;
|
||||||
|
|
||||||
use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
|
use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
|
||||||
use {CrateLint, Module, ModuleOrUniformRoot, PerNS};
|
use {CrateLint, DeterminacyExt, Module, ModuleOrUniformRoot, PerNS};
|
||||||
use Namespace::{self, TypeNS, MacroNS};
|
use Namespace::{self, TypeNS, MacroNS};
|
||||||
use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
|
use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
|
||||||
use {Resolver, Segment};
|
use {Resolver, Segment};
|
||||||
|
@ -135,16 +135,33 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||||
.or_insert_with(|| self.arenas.alloc_name_resolution())
|
.or_insert_with(|| self.arenas.alloc_name_resolution())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate fn resolve_ident_in_module_unadjusted(
|
||||||
|
&mut self,
|
||||||
|
module: ModuleOrUniformRoot<'a>,
|
||||||
|
ident: Ident,
|
||||||
|
ns: Namespace,
|
||||||
|
record_used: bool,
|
||||||
|
path_span: Span,
|
||||||
|
) -> Result<&'a NameBinding<'a>, Determinacy> {
|
||||||
|
self.resolve_ident_in_module_unadjusted_ext(
|
||||||
|
module, ident, ns, false, record_used, path_span
|
||||||
|
).map_err(|determinacy_ext| match determinacy_ext {
|
||||||
|
DeterminacyExt::Determined => Determined,
|
||||||
|
DeterminacyExt::Undetermined | DeterminacyExt::WeakUndetermined => Undetermined,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Attempts to resolve `ident` in namespaces `ns` of `module`.
|
/// Attempts to resolve `ident` in namespaces `ns` of `module`.
|
||||||
/// Invariant: if `record_used` is `Some`, expansion and import resolution must be complete.
|
/// Invariant: if `record_used` is `Some`, expansion and import resolution must be complete.
|
||||||
pub fn resolve_ident_in_module_unadjusted(&mut self,
|
crate fn resolve_ident_in_module_unadjusted_ext(
|
||||||
module: ModuleOrUniformRoot<'a>,
|
&mut self,
|
||||||
ident: Ident,
|
module: ModuleOrUniformRoot<'a>,
|
||||||
ns: Namespace,
|
ident: Ident,
|
||||||
restricted_shadowing: bool,
|
ns: Namespace,
|
||||||
record_used: bool,
|
restricted_shadowing: bool,
|
||||||
path_span: Span)
|
record_used: bool,
|
||||||
-> Result<&'a NameBinding<'a>, Determinacy> {
|
path_span: Span,
|
||||||
|
) -> Result<&'a NameBinding<'a>, DeterminacyExt> {
|
||||||
let module = match module {
|
let module = match module {
|
||||||
ModuleOrUniformRoot::Module(module) => module,
|
ModuleOrUniformRoot::Module(module) => module,
|
||||||
ModuleOrUniformRoot::UniformRoot(root) => {
|
ModuleOrUniformRoot::UniformRoot(root) => {
|
||||||
|
@ -157,7 +174,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||||
let mut ctxt = ident.span.ctxt().modern();
|
let mut ctxt = ident.span.ctxt().modern();
|
||||||
let self_module = self.resolve_self(&mut ctxt, self.current_module);
|
let self_module = self.resolve_self(&mut ctxt, self.current_module);
|
||||||
|
|
||||||
let binding = self.resolve_ident_in_module_unadjusted(
|
let binding = self.resolve_ident_in_module_unadjusted_ext(
|
||||||
ModuleOrUniformRoot::Module(self_module),
|
ModuleOrUniformRoot::Module(self_module),
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
|
@ -211,12 +228,12 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||||
return Ok(binding);
|
return Ok(binding);
|
||||||
} else if !self.graph_root.unresolved_invocations.borrow().is_empty() {
|
} else if !self.graph_root.unresolved_invocations.borrow().is_empty() {
|
||||||
// Macro-expanded `extern crate`items still can add names to extern prelude.
|
// Macro-expanded `extern crate`items still can add names to extern prelude.
|
||||||
return Err(Undetermined);
|
return Err(DeterminacyExt::Undetermined);
|
||||||
} else {
|
} else {
|
||||||
return Err(Determined);
|
return Err(DeterminacyExt::Determined);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(Determined);
|
return Err(DeterminacyExt::Determined);
|
||||||
};
|
};
|
||||||
self.populate_module_if_necessary(crate_root);
|
self.populate_module_if_necessary(crate_root);
|
||||||
let binding = (crate_root, ty::Visibility::Public,
|
let binding = (crate_root, ty::Visibility::Public,
|
||||||
|
@ -229,7 +246,8 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||||
|
|
||||||
let resolution = self.resolution(module, ident, ns)
|
let resolution = self.resolution(module, ident, ns)
|
||||||
.try_borrow_mut()
|
.try_borrow_mut()
|
||||||
.map_err(|_| Determined)?; // This happens when there is a cycle of imports
|
// This happens when there is a cycle of imports.
|
||||||
|
.map_err(|_| DeterminacyExt::Determined)?;
|
||||||
|
|
||||||
if let Some(binding) = resolution.binding {
|
if let Some(binding) = resolution.binding {
|
||||||
if !restricted_shadowing && binding.expansion != Mark::root() {
|
if !restricted_shadowing && binding.expansion != Mark::root() {
|
||||||
|
@ -264,13 +282,13 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolution.binding.ok_or(Determined);
|
return resolution.binding.ok_or(DeterminacyExt::Determined);
|
||||||
}
|
}
|
||||||
|
|
||||||
let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
|
let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
|
||||||
// `extern crate` are always usable for backwards compatibility, see issue #37020.
|
// `extern crate` are always usable for backwards compatibility, see issue #37020.
|
||||||
let usable = this.is_accessible(binding.vis) || binding.is_extern_crate();
|
let usable = this.is_accessible(binding.vis) || binding.is_extern_crate();
|
||||||
if usable { Ok(binding) } else { Err(Determined) }
|
if usable { Ok(binding) } else { Err(DeterminacyExt::Determined) }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Items and single imports are not shadowable, if we have one, then it's determined.
|
// Items and single imports are not shadowable, if we have one, then it's determined.
|
||||||
|
@ -288,7 +306,8 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||||
if !self.is_accessible(single_import.vis.get()) {
|
if !self.is_accessible(single_import.vis.get()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let module = unwrap_or!(single_import.imported_module.get(), return Err(Undetermined));
|
let module = unwrap_or!(single_import.imported_module.get(),
|
||||||
|
return Err(DeterminacyExt::Undetermined));
|
||||||
let ident = match single_import.subclass {
|
let ident = match single_import.subclass {
|
||||||
SingleImport { source, .. } => source,
|
SingleImport { source, .. } => source,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -298,7 +317,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||||
Ok(binding) if !self.is_accessible_from(
|
Ok(binding) if !self.is_accessible_from(
|
||||||
binding.vis, single_import.parent_scope.module
|
binding.vis, single_import.parent_scope.module
|
||||||
) => continue,
|
) => continue,
|
||||||
Ok(_) | Err(Undetermined) => return Err(Undetermined),
|
Ok(_) | Err(Undetermined) => return Err(DeterminacyExt::Undetermined),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +338,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||||
if !unexpanded_macros || ns == MacroNS || restricted_shadowing {
|
if !unexpanded_macros || ns == MacroNS || restricted_shadowing {
|
||||||
return check_usable(self, binding);
|
return check_usable(self, binding);
|
||||||
} else {
|
} else {
|
||||||
return Err(Undetermined);
|
return Err(DeterminacyExt::Undetermined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,17 +347,13 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||||
// Now we are in situation when new item/import can appear only from a glob or a macro
|
// Now we are in situation when new item/import can appear only from a glob or a macro
|
||||||
// expansion. With restricted shadowing names from globs and macro expansions cannot
|
// expansion. With restricted shadowing names from globs and macro expansions cannot
|
||||||
// shadow names from outer scopes, so we can freely fallback from module search to search
|
// shadow names from outer scopes, so we can freely fallback from module search to search
|
||||||
// in outer scopes. To continue search in outer scopes we have to lie a bit and return
|
// in outer scopes. For `early_resolve_ident_in_lexical_scope` to continue search in outer
|
||||||
// `Determined` to `early_resolve_ident_in_lexical_scope` even if the correct answer
|
// scopes we return `WeakUndetermined` instead of full `Undetermined`.
|
||||||
// for in-module resolution could be `Undetermined`.
|
|
||||||
if restricted_shadowing {
|
|
||||||
return Err(Determined);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if one of unexpanded macros can still define the name,
|
// Check if one of unexpanded macros can still define the name,
|
||||||
// if it can then our "no resolution" result is not determined and can be invalidated.
|
// if it can then our "no resolution" result is not determined and can be invalidated.
|
||||||
if unexpanded_macros {
|
if unexpanded_macros {
|
||||||
return Err(Undetermined);
|
return Err(DeterminacyExt::WeakUndetermined);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if one of glob imports can still define the name,
|
// Check if one of glob imports can still define the name,
|
||||||
|
@ -350,7 +365,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||||
let module = match glob_import.imported_module.get() {
|
let module = match glob_import.imported_module.get() {
|
||||||
Some(ModuleOrUniformRoot::Module(module)) => module,
|
Some(ModuleOrUniformRoot::Module(module)) => module,
|
||||||
Some(ModuleOrUniformRoot::UniformRoot(_)) => continue,
|
Some(ModuleOrUniformRoot::UniformRoot(_)) => continue,
|
||||||
None => return Err(Undetermined),
|
None => return Err(DeterminacyExt::WeakUndetermined),
|
||||||
};
|
};
|
||||||
let (orig_current_module, mut ident) = (self.current_module, ident.modern());
|
let (orig_current_module, mut ident) = (self.current_module, ident.modern());
|
||||||
match ident.span.glob_adjust(module.expansion, glob_import.span.ctxt().modern()) {
|
match ident.span.glob_adjust(module.expansion, glob_import.span.ctxt().modern()) {
|
||||||
|
@ -363,7 +378,6 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
false,
|
false,
|
||||||
false,
|
|
||||||
path_span,
|
path_span,
|
||||||
);
|
);
|
||||||
self.current_module = orig_current_module;
|
self.current_module = orig_current_module;
|
||||||
|
@ -373,12 +387,12 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||||
Ok(binding) if !self.is_accessible_from(
|
Ok(binding) if !self.is_accessible_from(
|
||||||
binding.vis, glob_import.parent_scope.module
|
binding.vis, glob_import.parent_scope.module
|
||||||
) => continue,
|
) => continue,
|
||||||
Ok(_) | Err(Undetermined) => return Err(Undetermined),
|
Ok(_) | Err(Undetermined) => return Err(DeterminacyExt::WeakUndetermined),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No resolution and no one else can define the name - determinate error.
|
// No resolution and no one else can define the name - determinate error.
|
||||||
Err(Determined)
|
Err(DeterminacyExt::Determined)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add an import directive to the current module.
|
// Add an import directive to the current module.
|
||||||
|
|
|
@ -4,6 +4,12 @@ error: unexpected generic arguments in path
|
||||||
LL | m!(MyTrait<>); //~ ERROR generic arguments in macro path
|
LL | m!(MyTrait<>); //~ ERROR generic arguments in macro path
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error: generic arguments in macro path
|
||||||
|
--> $DIR/macro-ty-params.rs:20:15
|
||||||
|
|
|
||||||
|
LL | m!(MyTrait<>); //~ ERROR generic arguments in macro path
|
||||||
|
| ^^
|
||||||
|
|
||||||
error: generic arguments in macro path
|
error: generic arguments in macro path
|
||||||
--> $DIR/macro-ty-params.rs:18:8
|
--> $DIR/macro-ty-params.rs:18:8
|
||||||
|
|
|
|
||||||
|
@ -16,11 +22,5 @@ error: generic arguments in macro path
|
||||||
LL | foo::<>!(); //~ ERROR generic arguments in macro path
|
LL | foo::<>!(); //~ ERROR generic arguments in macro path
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: generic arguments in macro path
|
|
||||||
--> $DIR/macro-ty-params.rs:20:15
|
|
||||||
|
|
|
||||||
LL | m!(MyTrait<>); //~ ERROR generic arguments in macro path
|
|
||||||
| ^^
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue