Skip to content

Commit 1cfd08c

Browse files
committed
resolve: More precise determinacy tracking during import/macro resolution
1 parent f0ea1c6 commit 1cfd08c

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
@@ -863,7 +863,6 @@ impl<'a, 'b, 'cl> BuildReducedGraphVisitor<'a, 'b, 'cl> {
863863
let invocation = self.resolver.invocations[&mark];
864864
invocation.module.set(self.resolver.current_module);
865865
invocation.parent_legacy_scope.set(self.current_legacy_scope);
866-
invocation.output_legacy_scope.set(self.current_legacy_scope);
867866
invocation
868867
}
869868
}

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,
@@ -2022,7 +2028,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
20222028
ModuleOrUniformRoot::Module(module),
20232029
ident,
20242030
ns,
2025-
false,
20262031
record_used,
20272032
path_span,
20282033
);
@@ -2053,7 +2058,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
20532058
ModuleOrUniformRoot::Module(module),
20542059
ident,
20552060
ns,
2056-
false,
20572061
record_used,
20582062
path_span,
20592063
);
@@ -2095,7 +2099,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
20952099
ident,
20962100
ns,
20972101
false,
2098-
false,
20992102
path_span,
21002103
) {
21012104
return Some(LexicalScopeBinding::Item(binding));
@@ -2170,7 +2173,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
21702173
}
21712174
}
21722175
let result = self.resolve_ident_in_module_unadjusted(
2173-
module, ident, ns, false, record_used, span,
2176+
module, ident, ns, record_used, span,
21742177
);
21752178
self.current_module = orig_current_module;
21762179
result
@@ -4411,7 +4414,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
44114414
ident,
44124415
ns,
44134416
false,
4414-
false,
44154417
module.span,
44164418
).is_ok() {
44174419
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>) {
@@ -624,38 +624,50 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
624624
let mut innermost_result: Option<(&NameBinding, Flags)> = None;
625625

626626
// Go through all the scopes and try to resolve the name.
627-
let mut where_to_resolve = WhereToResolve::DeriveHelpers;
627+
let mut where_to_resolve = if ns == MacroNS {
628+
WhereToResolve::DeriveHelpers
629+
} else {
630+
WhereToResolve::Module(parent_scope.module)
631+
};
628632
let mut use_prelude = !parent_scope.module.no_implicit_prelude;
633+
let mut determinacy = Determinacy::Determined;
629634
loop {
630635
let result = match where_to_resolve {
631636
WhereToResolve::DeriveHelpers => {
632637
let mut result = Err(Determinacy::Determined);
633638
for derive in &parent_scope.derives {
634639
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
635-
if let Ok((_, ext)) = self.resolve_macro_to_def(derive, MacroKind::Derive,
636-
&parent_scope, force) {
637-
if let SyntaxExtension::ProcMacroDerive(_, helper_attrs, _) = &*ext {
638-
if helper_attrs.contains(&ident.name) {
639-
let binding =
640-
(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
641-
ty::Visibility::Public, derive.span, Mark::root())
642-
.to_name_binding(self.arenas);
643-
result = Ok((binding, Flags::empty()));
644-
break;
640+
match self.resolve_macro_to_def(derive, MacroKind::Derive,
641+
&parent_scope, force) {
642+
Ok((_, ext)) => {
643+
if let SyntaxExtension::ProcMacroDerive(_, helpers, _) = &*ext {
644+
if helpers.contains(&ident.name) {
645+
let binding =
646+
(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
647+
ty::Visibility::Public, derive.span, Mark::root())
648+
.to_name_binding(self.arenas);
649+
result = Ok((binding, Flags::empty()));
650+
break;
651+
}
645652
}
646653
}
654+
Err(Determinacy::Determined) => {}
655+
Err(Determinacy::Undetermined) =>
656+
result = Err(Determinacy::Undetermined),
647657
}
648658
}
649659
result
650660
}
651661
WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
652662
LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
653663
Ok((legacy_binding.binding, Flags::MACRO_RULES)),
664+
LegacyScope::Invocation(invoc) if invoc.output_legacy_scope.get().is_none() =>
665+
Err(Determinacy::Undetermined),
654666
_ => Err(Determinacy::Determined),
655667
}
656668
WhereToResolve::Module(module) => {
657669
let orig_current_module = mem::replace(&mut self.current_module, module);
658-
let binding = self.resolve_ident_in_module_unadjusted(
670+
let binding = self.resolve_ident_in_module_unadjusted_ext(
659671
ModuleOrUniformRoot::Module(module),
660672
ident,
661673
ns,
@@ -664,21 +676,33 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
664676
path_span,
665677
);
666678
self.current_module = orig_current_module;
667-
let misc_flags = if module.is_normal() {
668-
Flags::MISC_SUGGEST_SELF
669-
} else {
670-
Flags::empty()
671-
};
672-
binding.map(|binding| (binding, Flags::MODULE | misc_flags))
679+
match binding {
680+
Ok(binding) => {
681+
let misc_flags = if module.is_normal() {
682+
Flags::MISC_SUGGEST_SELF
683+
} else {
684+
Flags::empty()
685+
};
686+
Ok((binding, Flags::MODULE | misc_flags))
687+
}
688+
Err(DeterminacyExt::Undetermined) =>
689+
return Err(Determinacy::determined(force)),
690+
Err(DeterminacyExt::WeakUndetermined) => Err(Determinacy::Undetermined),
691+
Err(DeterminacyExt::Determined) => Err(Determinacy::Determined),
692+
}
673693
}
674694
WhereToResolve::MacroUsePrelude => {
675-
let mut result = Err(Determinacy::Determined);
676695
if use_prelude || self.session.rust_2015() {
677-
if let Some(binding) = self.macro_use_prelude.get(&ident.name).cloned() {
678-
result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE));
696+
match self.macro_use_prelude.get(&ident.name).cloned() {
697+
Some(binding) =>
698+
Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)),
699+
None => Err(Determinacy::determined(
700+
self.graph_root.unresolved_invocations.borrow().is_empty()
701+
))
679702
}
703+
} else {
704+
Err(Determinacy::Determined)
680705
}
681-
result
682706
}
683707
WhereToResolve::BuiltinMacros => {
684708
match self.builtin_macros.get(&ident.name).cloned() {
@@ -709,14 +733,17 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
709733
}
710734
}
711735
WhereToResolve::ExternPrelude => {
712-
let mut result = Err(Determinacy::Determined);
713736
if use_prelude {
714-
if let Some(binding) = self.extern_prelude_get(ident, !record_used,
715-
innermost_result.is_some()) {
716-
result = Ok((binding, Flags::PRELUDE));
737+
match self.extern_prelude_get(ident, !record_used,
738+
innermost_result.is_some()) {
739+
Some(binding) => Ok((binding, Flags::PRELUDE)),
740+
None => Err(Determinacy::determined(
741+
self.graph_root.unresolved_invocations.borrow().is_empty()
742+
)),
717743
}
744+
} else {
745+
Err(Determinacy::Determined)
718746
}
719-
result
720747
}
721748
WhereToResolve::ToolPrelude => {
722749
if use_prelude && is_known_tool(ident.name) {
@@ -736,7 +763,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
736763
ident,
737764
ns,
738765
false,
739-
false,
740766
path_span,
741767
) {
742768
result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE));
@@ -757,54 +783,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
757783
}
758784
};
759785

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

878896
// The first found solution was the only one, return it.
879897
if let Some((binding, ..)) = innermost_result {
880898
return Ok(binding);
881899
}
882900

883-
let determinacy = Determinacy::determined(force);
901+
let determinacy = Determinacy::determined(determinacy == Determinacy::Determined || force);
884902
if determinacy == Determinacy::Determined && macro_kind == Some(MacroKind::Attr) {
885903
// For single-segment attributes interpret determinate "no resolution" as a custom
886904
// attribute. (Lexical resolution implies the first segment and attr kind should imply
@@ -1026,7 +1044,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
10261044
def_index: invoc.def_index,
10271045
module: Cell::new(graph_root),
10281046
parent_legacy_scope: Cell::new(LegacyScope::Uninitialized),
1029-
output_legacy_scope: Cell::new(LegacyScope::Uninitialized),
1047+
output_legacy_scope: Cell::new(None),
10301048
})
10311049
});
10321050
};

0 commit comments

Comments
 (0)