Skip to content

Commit 35b778f

Browse files
committed
resolve: More precise determinacy tracking during import/macro resolution
1 parent dcaeced commit 35b778f

File tree

5 files changed

+166
-133
lines changed

5 files changed

+166
-133
lines changed

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,6 @@ impl<'a, 'b, 'cl> BuildReducedGraphVisitor<'a, 'b, 'cl> {
860860
let invocation = self.resolver.invocations[&mark];
861861
invocation.module.set(self.resolver.current_module);
862862
invocation.parent_legacy_scope.set(self.current_legacy_scope);
863-
invocation.output_legacy_scope.set(self.current_legacy_scope);
864863
invocation
865864
}
866865
}

src/librustc_resolve/lib.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ fn is_known_tool(name: Name) -> bool {
9797
["clippy", "rustfmt"].contains(&&*name.as_str())
9898
}
9999

100+
enum DeterminacyExt {
101+
Determined,
102+
Undetermined,
103+
WeakUndetermined,
104+
}
105+
100106
/// A free importable items suggested in case of resolution failure.
101107
struct ImportSuggestion {
102108
path: Path,
@@ -1963,7 +1969,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
19631969
ModuleOrUniformRoot::Module(module),
19641970
ident,
19651971
ns,
1966-
false,
19671972
record_used,
19681973
path_span,
19691974
);
@@ -1994,7 +1999,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
19941999
ModuleOrUniformRoot::Module(module),
19952000
ident,
19962001
ns,
1997-
false,
19982002
record_used,
19992003
path_span,
20002004
);
@@ -2036,7 +2040,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
20362040
ident,
20372041
ns,
20382042
false,
2039-
false,
20402043
path_span,
20412044
) {
20422045
return Some(LexicalScopeBinding::Item(binding));
@@ -2111,7 +2114,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
21112114
}
21122115
}
21132116
let result = self.resolve_ident_in_module_unadjusted(
2114-
module, ident, ns, false, record_used, span,
2117+
module, ident, ns, record_used, span,
21152118
);
21162119
self.current_module = orig_current_module;
21172120
result
@@ -4334,7 +4337,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
43344337
ident,
43354338
ns,
43364339
false,
4337-
false,
43384340
module.span,
43394341
).is_ok() {
43404342
let import_id = match binding.kind {

src/librustc_resolve/macros.rs

Lines changed: 109 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
12-
use {CrateLint, Resolver, ResolutionError, is_known_tool, resolve_error};
12+
use {CrateLint, DeterminacyExt, Resolver, ResolutionError, is_known_tool, resolve_error};
1313
use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding};
1414
use ModuleOrUniformRoot;
1515
use Namespace::{self, *};
@@ -54,8 +54,8 @@ pub struct InvocationData<'a> {
5454
crate parent_legacy_scope: Cell<LegacyScope<'a>>,
5555
/// Legacy scope *produced* by expanding this macro invocation,
5656
/// includes all the macro_rules items, other invocations, etc generated by it.
57-
/// Set to the parent scope if the macro is not expanded yet (as if the macro produced nothing).
58-
crate output_legacy_scope: Cell<LegacyScope<'a>>,
57+
/// `None` if the macro is not expanded yet.
58+
crate output_legacy_scope: Cell<Option<LegacyScope<'a>>>,
5959
}
6060

6161
impl<'a> InvocationData<'a> {
@@ -64,7 +64,7 @@ impl<'a> InvocationData<'a> {
6464
module: Cell::new(graph_root),
6565
def_index: CRATE_DEF_INDEX,
6666
parent_legacy_scope: Cell::new(LegacyScope::Empty),
67-
output_legacy_scope: Cell::new(LegacyScope::Empty),
67+
output_legacy_scope: Cell::new(Some(LegacyScope::Empty)),
6868
}
6969
}
7070
}
@@ -110,7 +110,7 @@ pub struct ParentScope<'a> {
110110
// Macro namespace is separated into two sub-namespaces, one for bang macros and
111111
// one for attribute-like macros (attributes, derives).
112112
// We ignore resolutions from one sub-namespace when searching names in scope for another.
113-
fn sub_namespace_mismatch(requirement: Option<MacroKind>, candidate: Option<MacroKind>) -> bool {
113+
fn sub_namespace_match(candidate: Option<MacroKind>, requirement: Option<MacroKind>) -> bool {
114114
#[derive(PartialEq)]
115115
enum SubNS { Bang, AttrLike }
116116
let sub_ns = |kind| match kind {
@@ -121,7 +121,7 @@ fn sub_namespace_mismatch(requirement: Option<MacroKind>, candidate: Option<Macr
121121
let requirement = requirement.and_then(|kind| sub_ns(kind));
122122
let candidate = candidate.and_then(|kind| sub_ns(kind));
123123
// "No specific sub-namespace" means "matches anything" for both requirements and candidates.
124-
candidate.is_some() && requirement.is_some() && candidate != requirement
124+
candidate.is_none() || requirement.is_none() || candidate == requirement
125125
}
126126

127127
impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
@@ -136,7 +136,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
136136
module: Cell::new(module),
137137
def_index: module.def_id().unwrap().index,
138138
parent_legacy_scope: Cell::new(LegacyScope::Empty),
139-
output_legacy_scope: Cell::new(LegacyScope::Empty),
139+
output_legacy_scope: Cell::new(Some(LegacyScope::Empty)),
140140
}));
141141
mark
142142
}
@@ -212,7 +212,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
212212
expansion: mark,
213213
};
214214
fragment.visit_with(&mut visitor);
215-
invocation.output_legacy_scope.set(visitor.current_legacy_scope);
215+
invocation.output_legacy_scope.set(Some(visitor.current_legacy_scope));
216216
}
217217

218218
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
@@ -620,38 +620,50 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
620620
let mut innermost_result: Option<(&NameBinding, Flags)> = None;
621621

622622
// Go through all the scopes and try to resolve the name.
623-
let mut where_to_resolve = WhereToResolve::DeriveHelpers;
623+
let mut where_to_resolve = if ns == MacroNS {
624+
WhereToResolve::DeriveHelpers
625+
} else {
626+
WhereToResolve::Module(parent_scope.module)
627+
};
624628
let mut use_prelude = !parent_scope.module.no_implicit_prelude;
629+
let mut determinacy = Determinacy::Determined;
625630
loop {
626631
let result = match where_to_resolve {
627632
WhereToResolve::DeriveHelpers => {
628633
let mut result = Err(Determinacy::Determined);
629634
for derive in &parent_scope.derives {
630635
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
631-
if let Ok((_, ext)) = self.resolve_macro_to_def(derive, MacroKind::Derive,
632-
&parent_scope, force) {
633-
if let SyntaxExtension::ProcMacroDerive(_, helper_attrs, _) = &*ext {
634-
if helper_attrs.contains(&ident.name) {
635-
let binding =
636-
(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
637-
ty::Visibility::Public, derive.span, Mark::root())
638-
.to_name_binding(self.arenas);
639-
result = Ok((binding, Flags::empty()));
640-
break;
636+
match self.resolve_macro_to_def(derive, MacroKind::Derive,
637+
&parent_scope, force) {
638+
Ok((_, ext)) => {
639+
if let SyntaxExtension::ProcMacroDerive(_, helpers, _) = &*ext {
640+
if helpers.contains(&ident.name) {
641+
let binding =
642+
(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
643+
ty::Visibility::Public, derive.span, Mark::root())
644+
.to_name_binding(self.arenas);
645+
result = Ok((binding, Flags::empty()));
646+
break;
647+
}
641648
}
642649
}
650+
Err(Determinacy::Determined) => {}
651+
Err(Determinacy::Undetermined) =>
652+
result = Err(Determinacy::Undetermined),
643653
}
644654
}
645655
result
646656
}
647657
WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
648658
LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
649659
Ok((legacy_binding.binding, Flags::MACRO_RULES)),
660+
LegacyScope::Invocation(invoc) if invoc.output_legacy_scope.get().is_none() =>
661+
Err(Determinacy::Undetermined),
650662
_ => Err(Determinacy::Determined),
651663
}
652664
WhereToResolve::Module(module) => {
653665
let orig_current_module = mem::replace(&mut self.current_module, module);
654-
let binding = self.resolve_ident_in_module_unadjusted(
666+
let binding = self.resolve_ident_in_module_unadjusted_ext(
655667
ModuleOrUniformRoot::Module(module),
656668
ident,
657669
ns,
@@ -660,21 +672,33 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
660672
path_span,
661673
);
662674
self.current_module = orig_current_module;
663-
let misc_flags = if module.is_normal() {
664-
Flags::MISC_SUGGEST_SELF
665-
} else {
666-
Flags::empty()
667-
};
668-
binding.map(|binding| (binding, Flags::MODULE | misc_flags))
675+
match binding {
676+
Ok(binding) => {
677+
let misc_flags = if module.is_normal() {
678+
Flags::MISC_SUGGEST_SELF
679+
} else {
680+
Flags::empty()
681+
};
682+
Ok((binding, Flags::MODULE | misc_flags))
683+
}
684+
Err(DeterminacyExt::Undetermined) =>
685+
return Err(Determinacy::determined(force)),
686+
Err(DeterminacyExt::WeakUndetermined) => Err(Determinacy::Undetermined),
687+
Err(DeterminacyExt::Determined) => Err(Determinacy::Determined),
688+
}
669689
}
670690
WhereToResolve::MacroUsePrelude => {
671-
let mut result = Err(Determinacy::Determined);
672691
if use_prelude || self.session.rust_2015() {
673-
if let Some(binding) = self.macro_use_prelude.get(&ident.name).cloned() {
674-
result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE));
692+
match self.macro_use_prelude.get(&ident.name).cloned() {
693+
Some(binding) =>
694+
Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)),
695+
None => Err(Determinacy::determined(
696+
self.graph_root.unresolved_invocations.borrow().is_empty()
697+
))
675698
}
699+
} else {
700+
Err(Determinacy::Determined)
676701
}
677-
result
678702
}
679703
WhereToResolve::BuiltinMacros => {
680704
match self.builtin_macros.get(&ident.name).cloned() {
@@ -705,14 +729,17 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
705729
}
706730
}
707731
WhereToResolve::ExternPrelude => {
708-
let mut result = Err(Determinacy::Determined);
709732
if use_prelude {
710-
if let Some(binding) = self.extern_prelude_get(ident, !record_used,
711-
innermost_result.is_some()) {
712-
result = Ok((binding, Flags::PRELUDE));
733+
match self.extern_prelude_get(ident, !record_used,
734+
innermost_result.is_some()) {
735+
Some(binding) => Ok((binding, Flags::PRELUDE)),
736+
None => Err(Determinacy::determined(
737+
self.graph_root.unresolved_invocations.borrow().is_empty()
738+
)),
713739
}
740+
} else {
741+
Err(Determinacy::Determined)
714742
}
715-
result
716743
}
717744
WhereToResolve::ToolPrelude => {
718745
if use_prelude && is_known_tool(ident.name) {
@@ -732,7 +759,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
732759
ident,
733760
ns,
734761
false,
735-
false,
736762
path_span,
737763
) {
738764
result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE));
@@ -753,54 +779,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
753779
}
754780
};
755781

756-
macro_rules! continue_search { () => {
757-
where_to_resolve = match where_to_resolve {
758-
WhereToResolve::DeriveHelpers =>
759-
WhereToResolve::MacroRules(parent_scope.legacy),
760-
WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
761-
LegacyScope::Binding(binding) =>
762-
WhereToResolve::MacroRules(binding.parent_legacy_scope),
763-
LegacyScope::Invocation(invocation) =>
764-
WhereToResolve::MacroRules(invocation.output_legacy_scope.get()),
765-
LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
766-
LegacyScope::Uninitialized => unreachable!(),
767-
}
768-
WhereToResolve::Module(module) => {
769-
match self.hygienic_lexical_parent(module, &mut ident.span) {
770-
Some(parent_module) => WhereToResolve::Module(parent_module),
771-
None => {
772-
use_prelude = !module.no_implicit_prelude;
773-
match ns {
774-
TypeNS => WhereToResolve::ExternPrelude,
775-
ValueNS => WhereToResolve::StdLibPrelude,
776-
MacroNS => WhereToResolve::MacroUsePrelude,
777-
}
778-
}
779-
}
780-
}
781-
WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros,
782-
WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
783-
WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers,
784-
WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search
785-
WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
786-
WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
787-
WhereToResolve::StdLibPrelude => match ns {
788-
TypeNS => WhereToResolve::BuiltinTypes,
789-
ValueNS => break, // nowhere else to search
790-
MacroNS => unreachable!(),
791-
}
792-
WhereToResolve::BuiltinTypes => break, // nowhere else to search
793-
};
794-
795-
continue;
796-
}}
797-
798782
match result {
799-
Ok((binding, flags)) => {
800-
if sub_namespace_mismatch(macro_kind, binding.macro_kind()) {
801-
continue_search!();
802-
}
803-
783+
Ok((binding, flags)) if sub_namespace_match(binding.macro_kind(), macro_kind) => {
804784
if !record_used {
805785
return Ok(binding);
806786
}
@@ -861,22 +841,60 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
861841
// Found the first solution.
862842
innermost_result = Some((binding, flags));
863843
}
864-
865-
continue_search!();
866-
},
867-
Err(Determinacy::Determined) => {
868-
continue_search!();
869844
}
870-
Err(Determinacy::Undetermined) => return Err(Determinacy::determined(force)),
845+
Ok(..) | Err(Determinacy::Determined) => {}
846+
Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined
871847
}
848+
849+
where_to_resolve = match where_to_resolve {
850+
WhereToResolve::DeriveHelpers =>
851+
WhereToResolve::MacroRules(parent_scope.legacy),
852+
WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
853+
LegacyScope::Binding(binding) => WhereToResolve::MacroRules(
854+
binding.parent_legacy_scope
855+
),
856+
LegacyScope::Invocation(invoc) => WhereToResolve::MacroRules(
857+
invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope.get())
858+
),
859+
LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
860+
LegacyScope::Uninitialized => unreachable!(),
861+
}
862+
WhereToResolve::Module(module) => {
863+
match self.hygienic_lexical_parent(module, &mut ident.span) {
864+
Some(parent_module) => WhereToResolve::Module(parent_module),
865+
None => {
866+
use_prelude = !module.no_implicit_prelude;
867+
match ns {
868+
TypeNS => WhereToResolve::ExternPrelude,
869+
ValueNS => WhereToResolve::StdLibPrelude,
870+
MacroNS => WhereToResolve::MacroUsePrelude,
871+
}
872+
}
873+
}
874+
}
875+
WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros,
876+
WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
877+
WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers,
878+
WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search
879+
WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
880+
WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
881+
WhereToResolve::StdLibPrelude => match ns {
882+
TypeNS => WhereToResolve::BuiltinTypes,
883+
ValueNS => break, // nowhere else to search
884+
MacroNS => unreachable!(),
885+
}
886+
WhereToResolve::BuiltinTypes => break, // nowhere else to search
887+
};
888+
889+
continue;
872890
}
873891

874892
// The first found solution was the only one, return it.
875893
if let Some((binding, ..)) = innermost_result {
876894
return Ok(binding);
877895
}
878896

879-
let determinacy = Determinacy::determined(force);
897+
let determinacy = Determinacy::determined(determinacy == Determinacy::Determined || force);
880898
if determinacy == Determinacy::Determined && macro_kind == Some(MacroKind::Attr) {
881899
// For single-segment attributes interpret determinate "no resolution" as a custom
882900
// attribute. (Lexical resolution implies the first segment and attr kind should imply
@@ -1020,7 +1038,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
10201038
def_index: invoc.def_index,
10211039
module: Cell::new(graph_root),
10221040
parent_legacy_scope: Cell::new(LegacyScope::Uninitialized),
1023-
output_legacy_scope: Cell::new(LegacyScope::Uninitialized),
1041+
output_legacy_scope: Cell::new(None),
10241042
})
10251043
});
10261044
};

0 commit comments

Comments
 (0)