Skip to content

Commit c91b6ca

Browse files
committed
resolve: Split resolve_ident_in_module_unadjusted into two parts - for non-glob and glob bindings.
In preparation for introducing `Scope::Module(Non)Globs` and `ScopeSet::Module`.
1 parent 9761db0 commit c91b6ca

File tree

1 file changed

+104
-24
lines changed

1 file changed

+104
-24
lines changed

compiler/rustc_resolve/src/ident.rs

Lines changed: 104 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,46 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
944944
// "self-confirming" import resolutions during import validation and checking.
945945
ignore_binding: Option<NameBinding<'ra>>,
946946
ignore_import: Option<Import<'ra>>,
947+
) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
948+
let res = self.reborrow().resolve_ident_in_module_non_globs_unadjusted(
949+
module,
950+
ident,
951+
ns,
952+
parent_scope,
953+
shadowing,
954+
finalize,
955+
ignore_binding,
956+
ignore_import,
957+
);
958+
959+
match res {
960+
Ok(_) | Err(ControlFlow::Break(_)) => return res,
961+
Err(ControlFlow::Continue(_)) => {}
962+
}
963+
964+
self.resolve_ident_in_module_globs_unadjusted(
965+
module,
966+
ident,
967+
ns,
968+
parent_scope,
969+
shadowing,
970+
finalize,
971+
ignore_binding,
972+
ignore_import,
973+
)
974+
}
975+
976+
/// Attempts to resolve `ident` in namespace `ns` of non-glob bindings in `module`.
977+
fn resolve_ident_in_module_non_globs_unadjusted<'r>(
978+
mut self: CmResolver<'r, 'ra, 'tcx>,
979+
module: Module<'ra>,
980+
ident: Ident,
981+
ns: Namespace,
982+
parent_scope: &ParentScope<'ra>,
983+
shadowing: Shadowing,
984+
finalize: Option<Finalize>,
985+
ignore_binding: Option<NameBinding<'ra>>,
986+
ignore_import: Option<Import<'ra>>,
947987
) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
948988
let key = BindingKey::new(ident, ns);
949989
// `try_borrow_mut` is required to ensure exclusive access, even if the resulting binding
@@ -954,13 +994,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
954994
.try_borrow_mut_unchecked()
955995
.map_err(|_| ControlFlow::Continue(Determined))?;
956996

957-
// If the primary binding is unusable, search further and return the shadowed glob
958-
// binding if it exists. What we really want here is having two separate scopes in
959-
// a module - one for non-globs and one for globs, but until that's done use this
960-
// hack to avoid inconsistent resolution ICEs during import validation.
961-
let binding = [resolution.non_glob_binding, resolution.glob_binding]
962-
.into_iter()
963-
.find_map(|binding| if binding == ignore_binding { None } else { binding });
997+
let binding = resolution.non_glob_binding.filter(|b| Some(*b) != ignore_binding);
964998

965999
if let Some(finalize) = finalize {
9661000
return self.get_mut().finalize_module_binding(
@@ -974,19 +1008,67 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
9741008
);
9751009
}
9761010

977-
let check_usable = |this: CmResolver<'r, 'ra, 'tcx>, binding: NameBinding<'ra>| {
978-
let usable = this.is_accessible_from(binding.vis, parent_scope.module);
979-
if usable { Ok(binding) } else { Err(ControlFlow::Break(Determined)) }
980-
};
981-
9821011
// Items and single imports are not shadowable, if we have one, then it's determined.
983-
if let Some(binding) = binding
984-
&& !binding.is_glob_import()
985-
{
986-
return check_usable(self, binding);
1012+
if let Some(binding) = binding {
1013+
let accessible = self.is_accessible_from(binding.vis, parent_scope.module);
1014+
return if accessible { Ok(binding) } else { Err(ControlFlow::Break(Determined)) };
1015+
}
1016+
1017+
// Check if one of single imports can still define the name, block if it can.
1018+
if self.reborrow().single_import_can_define_name(
1019+
&resolution,
1020+
None,
1021+
ns,
1022+
ignore_import,
1023+
ignore_binding,
1024+
parent_scope,
1025+
) {
1026+
return Err(ControlFlow::Break(Undetermined));
1027+
}
1028+
1029+
// Check if one of unexpanded macros can still define the name.
1030+
if !module.unexpanded_invocations.borrow().is_empty() {
1031+
return Err(ControlFlow::Continue(Undetermined));
9871032
}
9881033

989-
// --- From now on we either have a glob resolution or no resolution. ---
1034+
// No resolution and no one else can define the name - determinate error.
1035+
Err(ControlFlow::Continue(Determined))
1036+
}
1037+
1038+
/// Attempts to resolve `ident` in namespace `ns` of glob bindings in `module`.
1039+
fn resolve_ident_in_module_globs_unadjusted<'r>(
1040+
mut self: CmResolver<'r, 'ra, 'tcx>,
1041+
module: Module<'ra>,
1042+
ident: Ident,
1043+
ns: Namespace,
1044+
parent_scope: &ParentScope<'ra>,
1045+
shadowing: Shadowing,
1046+
finalize: Option<Finalize>,
1047+
ignore_binding: Option<NameBinding<'ra>>,
1048+
ignore_import: Option<Import<'ra>>,
1049+
) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
1050+
let key = BindingKey::new(ident, ns);
1051+
// `try_borrow_mut` is required to ensure exclusive access, even if the resulting binding
1052+
// doesn't need to be mutable. It will fail when there is a cycle of imports, and without
1053+
// the exclusive access infinite recursion will crash the compiler with stack overflow.
1054+
let resolution = &*self
1055+
.resolution_or_default(module, key)
1056+
.try_borrow_mut_unchecked()
1057+
.map_err(|_| ControlFlow::Continue(Determined))?;
1058+
1059+
let binding = resolution.glob_binding.filter(|b| Some(*b) != ignore_binding);
1060+
1061+
if let Some(finalize) = finalize {
1062+
return self.get_mut().finalize_module_binding(
1063+
ident,
1064+
binding,
1065+
if resolution.non_glob_binding.is_some() { resolution.glob_binding } else { None },
1066+
parent_scope,
1067+
module,
1068+
finalize,
1069+
shadowing,
1070+
);
1071+
}
9901072

9911073
// Check if one of single imports can still define the name,
9921074
// if it can then our result is not determined and can be invalidated.
@@ -1014,21 +1096,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
10141096
// and prohibit access to macro-expanded `macro_export` macros instead (unless restricted
10151097
// shadowing is enabled, see `macro_expanded_macro_export_errors`).
10161098
if let Some(binding) = binding {
1017-
if binding.determined() || ns == MacroNS || shadowing == Shadowing::Restricted {
1018-
return check_usable(self, binding);
1099+
return if binding.determined() || ns == MacroNS || shadowing == Shadowing::Restricted {
1100+
let accessible = self.is_accessible_from(binding.vis, parent_scope.module);
1101+
if accessible { Ok(binding) } else { Err(ControlFlow::Break(Determined)) }
10191102
} else {
1020-
return Err(ControlFlow::Break(Undetermined));
1021-
}
1103+
Err(ControlFlow::Break(Undetermined))
1104+
};
10221105
}
10231106

1024-
// --- From now on we have no resolution. ---
1025-
10261107
// Now we are in situation when new item/import can appear only from a glob or a macro
10271108
// expansion. With restricted shadowing names from globs and macro expansions cannot
10281109
// shadow names from outer scopes, so we can freely fallback from module search to search
10291110
// in outer scopes. For `resolve_ident_in_scope_set` to continue search in outer
10301111
// scopes we return `Undetermined` with `ControlFlow::Continue`.
1031-
10321112
// Check if one of unexpanded macros can still define the name,
10331113
// if it can then our "no resolution" result is not determined and can be invalidated.
10341114
if !module.unexpanded_invocations.borrow().is_empty() {

0 commit comments

Comments
 (0)