Skip to content

Commit 6990fc3

Browse files
b-naberLorrensP-2158466
authored andcommitted
extract single_import_can_define_name and finalize_glob_module_binding
1 parent cf3fb76 commit 6990fc3

File tree

1 file changed

+145
-118
lines changed

1 file changed

+145
-118
lines changed

compiler/rustc_resolve/src/ident.rs

Lines changed: 145 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::cell::RefMut;
2+
13
use Determinacy::*;
24
use Namespace::*;
35
use rustc_ast::{self as ast, NodeId};
@@ -13,7 +15,7 @@ use rustc_span::{Ident, Span, kw, sym};
1315
use tracing::{debug, instrument};
1416

1517
use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
16-
use crate::imports::Import;
18+
use crate::imports::{Import, NameResolution};
1719
use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind};
1820
use crate::macros::{MacroRulesScope, sub_namespace_match};
1921
use crate::{
@@ -37,7 +39,7 @@ impl From<UsePrelude> for bool {
3739
}
3840
}
3941

40-
#[derive(Debug, PartialEq)]
42+
#[derive(Debug, PartialEq, Clone, Copy)]
4143
enum Shadowing {
4244
Restricted,
4345
Unrestricted,
@@ -879,53 +881,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
879881
.into_iter()
880882
.find_map(|binding| if binding == ignore_binding { None } else { binding });
881883

882-
if let Some(Finalize { path_span, report_private, used, root_span, .. }) = finalize {
883-
let Some(binding) = binding else {
884-
return Err((Determined, Weak::No));
885-
};
886-
887-
if !self.is_accessible_from(binding.vis, parent_scope.module) {
888-
if report_private {
889-
self.privacy_errors.push(PrivacyError {
890-
ident,
891-
binding,
892-
dedup_span: path_span,
893-
outermost_res: None,
894-
parent_scope: *parent_scope,
895-
single_nested: path_span != root_span,
896-
});
897-
} else {
898-
return Err((Determined, Weak::No));
899-
}
900-
}
901-
902-
// Forbid expanded shadowing to avoid time travel.
903-
if let Some(shadowed_glob) = resolution.shadowed_glob
904-
&& shadowing == Shadowing::Restricted
905-
&& binding.expansion != LocalExpnId::ROOT
906-
&& binding.res() != shadowed_glob.res()
907-
{
908-
self.ambiguity_errors.push(AmbiguityError {
909-
kind: AmbiguityKind::GlobVsExpanded,
910-
ident,
911-
b1: binding,
912-
b2: shadowed_glob,
913-
warning: false,
914-
misc1: AmbiguityErrorMisc::None,
915-
misc2: AmbiguityErrorMisc::None,
916-
});
917-
}
918-
919-
if shadowing == Shadowing::Unrestricted
920-
&& binding.expansion != LocalExpnId::ROOT
921-
&& let NameBindingKind::Import { import, .. } = binding.kind
922-
&& matches!(import.kind, ImportKind::MacroExport)
923-
{
924-
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
925-
}
926-
927-
self.record_use(ident, binding, used);
928-
return Ok(binding);
884+
if let Some(finalize) = finalize {
885+
return self.finalize_module_binding(
886+
ident,
887+
binding,
888+
resolution.shadowed_glob,
889+
parent_scope,
890+
finalize,
891+
shadowing,
892+
);
929893
}
930894

931895
let check_usable = |this: &mut Self, binding: NameBinding<'ra>| {
@@ -944,75 +908,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
944908

945909
// Check if one of single imports can still define the name,
946910
// if it can then our result is not determined and can be invalidated.
947-
for single_import in &resolution.single_imports {
948-
if ignore_import == Some(*single_import) {
949-
// This branch handles a cycle in single imports.
950-
//
951-
// For example:
952-
// ```
953-
// use a::b;
954-
// use b as a;
955-
// ```
956-
// 1. Record `use a::b` as the `ignore_import` and attempt to locate `a` in the
957-
// current module.
958-
// 2. Encounter the import `use b as a`, which is a `single_import` for `a`,
959-
// and try to find `b` in the current module.
960-
// 3. Re-encounter the `use a::b` import since it's a `single_import` of `b`.
961-
// This leads to entering this branch.
962-
continue;
963-
}
964-
if !self.is_accessible_from(single_import.vis, parent_scope.module) {
965-
continue;
966-
}
967-
if let Some(ignored) = ignore_binding
968-
&& let NameBindingKind::Import { import, .. } = ignored.kind
969-
&& import == *single_import
970-
{
971-
// Ignore not just the binding itself, but if it has a shadowed_glob,
972-
// ignore that, too, because this loop is supposed to only process
973-
// named imports.
974-
continue;
975-
}
976-
977-
let Some(module) = single_import.imported_module.get() else {
978-
return Err((Undetermined, Weak::No));
979-
};
980-
let ImportKind::Single { source, target, target_bindings, .. } = &single_import.kind
981-
else {
982-
unreachable!();
983-
};
984-
if source != target {
985-
// This branch allows the binding to be defined or updated later if the target name
986-
// can hide the source.
987-
if target_bindings.iter().all(|binding| binding.get().is_none()) {
988-
// None of the target bindings are available, so we can't determine
989-
// if this binding is correct or not.
990-
// See more details in #124840
991-
return Err((Undetermined, Weak::No));
992-
} else if target_bindings[ns].get().is_none() && binding.is_some() {
993-
// `binding.is_some()` avoids the condition where the binding
994-
// truly doesn't exist in this namespace and should return `Err(Determined)`.
995-
return Err((Undetermined, Weak::No));
996-
}
997-
}
998-
999-
match self.resolve_ident_in_module(
1000-
module,
1001-
*source,
1002-
ns,
1003-
&single_import.parent_scope,
1004-
None,
1005-
ignore_binding,
1006-
ignore_import,
1007-
) {
1008-
Err((Determined, _)) => continue,
1009-
Ok(binding)
1010-
if !self.is_accessible_from(binding.vis, single_import.parent_scope.module) =>
1011-
{
1012-
continue;
1013-
}
1014-
Ok(_) | Err((Undetermined, _)) => return Err((Undetermined, Weak::No)),
1015-
}
911+
if self.single_import_can_define_name(
912+
&resolution,
913+
binding,
914+
ns,
915+
ignore_import,
916+
ignore_binding,
917+
parent_scope,
918+
) {
919+
return Err((Undetermined, Weak::No));
1016920
}
1017921

1018922
// So we have a resolution that's from a glob import. This resolution is determined
@@ -1101,6 +1005,129 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
11011005
Err((Determined, Weak::No))
11021006
}
11031007

1008+
fn finalize_module_binding(
1009+
&mut self,
1010+
ident: Ident,
1011+
binding: Option<NameBinding<'ra>>,
1012+
shadowed_glob: Option<NameBinding<'ra>>,
1013+
parent_scope: &ParentScope<'ra>,
1014+
finalize: Finalize,
1015+
shadowing: Shadowing,
1016+
) -> Result<NameBinding<'ra>, (Determinacy, Weak)> {
1017+
let Finalize { path_span, report_private, used, root_span, .. } = finalize;
1018+
1019+
let Some(binding) = binding else {
1020+
return Err((Determined, Weak::No));
1021+
};
1022+
1023+
if !self.is_accessible_from(binding.vis, parent_scope.module) {
1024+
if report_private {
1025+
self.privacy_errors.push(PrivacyError {
1026+
ident,
1027+
binding,
1028+
dedup_span: path_span,
1029+
outermost_res: None,
1030+
parent_scope: *parent_scope,
1031+
single_nested: path_span != root_span,
1032+
});
1033+
} else {
1034+
return Err((Determined, Weak::No));
1035+
}
1036+
}
1037+
1038+
// Forbid expanded shadowing to avoid time travel.
1039+
if let Some(shadowed_glob) = shadowed_glob
1040+
&& shadowing == Shadowing::Restricted
1041+
&& binding.expansion != LocalExpnId::ROOT
1042+
&& binding.res() != shadowed_glob.res()
1043+
{
1044+
self.ambiguity_errors.push(AmbiguityError {
1045+
kind: AmbiguityKind::GlobVsExpanded,
1046+
ident,
1047+
b1: binding,
1048+
b2: shadowed_glob,
1049+
warning: false,
1050+
misc1: AmbiguityErrorMisc::None,
1051+
misc2: AmbiguityErrorMisc::None,
1052+
});
1053+
}
1054+
1055+
if shadowing == Shadowing::Unrestricted
1056+
&& binding.expansion != LocalExpnId::ROOT
1057+
&& let NameBindingKind::Import { import, .. } = binding.kind
1058+
&& matches!(import.kind, ImportKind::MacroExport)
1059+
{
1060+
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
1061+
}
1062+
1063+
self.record_use(ident, binding, used);
1064+
return Ok(binding);
1065+
}
1066+
1067+
// Checks if a single import can define the `Ident` corresponding to `binding`.
1068+
// This is used to check whether we can definitively accept a glob as a resolution.
1069+
fn single_import_can_define_name(
1070+
&mut self,
1071+
resolution: &RefMut<'_, NameResolution<'ra>>,
1072+
binding: Option<NameBinding<'ra>>,
1073+
ns: Namespace,
1074+
ignore_import: Option<Import<'ra>>,
1075+
ignore_binding: Option<NameBinding<'ra>>,
1076+
parent_scope: &ParentScope<'ra>,
1077+
) -> bool {
1078+
for single_import in &resolution.single_imports {
1079+
if ignore_import == Some(*single_import) {
1080+
continue;
1081+
}
1082+
if !self.is_accessible_from(single_import.vis, parent_scope.module) {
1083+
continue;
1084+
}
1085+
if let Some(ignored) = ignore_binding
1086+
&& let NameBindingKind::Import { import, .. } = ignored.kind
1087+
&& import == *single_import
1088+
{
1089+
continue;
1090+
}
1091+
1092+
let Some(module) = single_import.imported_module.get() else {
1093+
return true;
1094+
};
1095+
let ImportKind::Single { source, target, target_bindings, .. } = &single_import.kind
1096+
else {
1097+
unreachable!();
1098+
};
1099+
if source != target {
1100+
if target_bindings.iter().all(|binding| binding.get().is_none()) {
1101+
return true;
1102+
} else if target_bindings[ns].get().is_none() && binding.is_some() {
1103+
return true;
1104+
}
1105+
}
1106+
1107+
match self.resolve_ident_in_module(
1108+
module,
1109+
*source,
1110+
ns,
1111+
&single_import.parent_scope,
1112+
None,
1113+
ignore_binding,
1114+
ignore_import,
1115+
) {
1116+
Err((Determined, _)) => continue,
1117+
Ok(binding)
1118+
if !self.is_accessible_from(binding.vis, single_import.parent_scope.module) =>
1119+
{
1120+
continue;
1121+
}
1122+
Ok(_) | Err((Undetermined, _)) => {
1123+
return true;
1124+
}
1125+
}
1126+
}
1127+
1128+
false
1129+
}
1130+
11041131
/// Validate a local resolution (from ribs).
11051132
#[instrument(level = "debug", skip(self, all_ribs))]
11061133
fn validate_res_from_ribs(

0 commit comments

Comments
 (0)