Skip to content

Commit 7203fa8

Browse files
Auto merge of #144793 - petrochenkov:extprel3, r=<try>
resolve: Split extern prelude into two scopes
2 parents 4b55fe1 + 4d377d2 commit 7203fa8

13 files changed

+266
-120
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4519,6 +4519,7 @@ name = "rustc_resolve"
45194519
version = "0.0.0"
45204520
dependencies = [
45214521
"bitflags",
4522+
"indexmap",
45224523
"itertools",
45234524
"pulldown-cmark",
45244525
"rustc_arena",

compiler/rustc_resolve/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ edition = "2024"
66
[dependencies]
77
# tidy-alphabetical-start
88
bitflags = "2.4.1"
9+
indexmap = "2.4.0"
910
itertools = "0.12"
1011
pulldown-cmark = { version = "0.11", features = ["html"], default-features = false }
1112
rustc_arena = { path = "../rustc_arena" }

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -968,39 +968,40 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
968968
}
969969
self.r.potentially_unused_imports.push(import);
970970
let imported_binding = self.r.import(binding, import);
971-
if parent == self.r.graph_root {
971+
if ident.name != kw::Underscore && parent == self.r.graph_root {
972972
let ident = ident.normalize_to_macros_2_0();
973+
// FIXME: this error is technically unnecessary now when extern prelude is split into
974+
// two scopes, remove it with lang team approval.
973975
if let Some(entry) = self.r.extern_prelude.get(&ident)
974976
&& expansion != LocalExpnId::ROOT
975977
&& orig_name.is_some()
976-
&& !entry.is_import()
978+
&& entry.item_binding.is_none()
977979
{
978980
self.r.dcx().emit_err(
979981
errors::MacroExpandedExternCrateCannotShadowExternArguments { span: item.span },
980982
);
981-
// `return` is intended to discard this binding because it's an
982-
// unregistered ambiguity error which would result in a panic
983-
// caused by inconsistency `path_res`
984-
// more details: https://github.com/rust-lang/rust/pull/111761
985-
return;
986-
}
987-
let entry = self.r.extern_prelude.entry(ident).or_insert(ExternPreludeEntry {
988-
binding: Cell::new(None),
989-
introduced_by_item: true,
990-
});
991-
if orig_name.is_some() {
992-
entry.introduced_by_item = true;
993-
}
994-
// Binding from `extern crate` item in source code can replace
995-
// a binding from `--extern` on command line here.
996-
if !entry.is_import() {
997-
entry.binding.set(Some(imported_binding));
998-
} else if ident.name != kw::Underscore {
999-
self.r.dcx().span_delayed_bug(
1000-
item.span,
1001-
format!("it had been define the external module '{ident}' multiple times"),
1002-
);
1003983
}
984+
985+
use indexmap::map::Entry;
986+
match self.r.extern_prelude.entry(ident) {
987+
Entry::Occupied(mut occupied) => {
988+
let entry = occupied.get_mut();
989+
if entry.item_binding.is_some() {
990+
let msg = format!("extern crate `{ident}` already in extern prelude");
991+
self.r.tcx.dcx().span_delayed_bug(item.span, msg);
992+
} else {
993+
entry.item_binding = Some(imported_binding);
994+
entry.introduced_by_item = orig_name.is_some();
995+
}
996+
entry
997+
}
998+
Entry::Vacant(vacant) => vacant.insert(ExternPreludeEntry {
999+
item_binding: Some(imported_binding),
1000+
flag_binding: Cell::new(None),
1001+
only_item: true,
1002+
introduced_by_item: true,
1003+
}),
1004+
};
10041005
}
10051006
self.r.define_binding_local(parent, ident, TypeNS, imported_binding);
10061007
}

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,12 +1095,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
10951095
);
10961096
}
10971097
}
1098-
Scope::ExternPrelude => {
1099-
suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
1098+
Scope::ExternPreludeItems => {
1099+
// Add idents from both item and flag scopes.
1100+
suggestions.extend(this.extern_prelude.keys().filter_map(|ident| {
11001101
let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
11011102
filter_fn(res).then_some(TypoSuggestion::typo_from_ident(*ident, res))
11021103
}));
11031104
}
1105+
Scope::ExternPreludeFlags => {}
11041106
Scope::ToolPrelude => {
11051107
let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
11061108
suggestions.extend(
@@ -1407,7 +1409,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
14071409
);
14081410

14091411
if lookup_ident.span.at_least_rust_2018() {
1410-
for ident in self.extern_prelude.clone().into_keys() {
1412+
for &ident in self.extern_prelude.keys() {
14111413
if ident.span.from_expansion() {
14121414
// Idents are adjusted to the root context before being
14131415
// resolved in the extern prelude, so reporting this to the
@@ -1884,7 +1886,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
18841886
"consider adding an explicit import of `{ident}` to disambiguate"
18851887
))
18861888
}
1887-
if b.is_extern_crate() && ident.span.at_least_rust_2018() {
1889+
if kind != AmbiguityKind::ExternPrelude
1890+
&& b.is_extern_crate()
1891+
&& ident.span.at_least_rust_2018()
1892+
{
18881893
help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously"))
18891894
}
18901895
match misc {

compiler/rustc_resolve/src/ident.rs

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
9797
ScopeSet::All(ns)
9898
| ScopeSet::ModuleAndExternPrelude(ns, _)
9999
| ScopeSet::Late(ns, ..) => (ns, None),
100+
ScopeSet::ExternPrelude => (TypeNS, None),
100101
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
101102
};
102103
let module = match scope_set {
@@ -106,8 +107,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
106107
_ => parent_scope.module.nearest_item_scope(),
107108
};
108109
let module_and_extern_prelude = matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..));
110+
let extern_prelude = matches!(scope_set, ScopeSet::ExternPrelude);
109111
let mut scope = match ns {
110112
_ if module_and_extern_prelude => Scope::Module(module, None),
113+
_ if extern_prelude => Scope::ExternPreludeItems,
111114
TypeNS | ValueNS => Scope::Module(module, None),
112115
MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
113116
};
@@ -138,7 +141,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
138141
Scope::Module(..) => true,
139142
Scope::MacroUsePrelude => use_prelude || rust_2015,
140143
Scope::BuiltinAttrs => true,
141-
Scope::ExternPrelude => use_prelude || module_and_extern_prelude,
144+
Scope::ExternPreludeItems | Scope::ExternPreludeFlags => {
145+
use_prelude || module_and_extern_prelude || extern_prelude
146+
}
142147
Scope::ToolPrelude => use_prelude,
143148
Scope::StdLibPrelude => use_prelude || ns == MacroNS,
144149
Scope::BuiltinTypes => true,
@@ -177,7 +182,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
177182
Scope::Module(..) if module_and_extern_prelude => match ns {
178183
TypeNS => {
179184
ctxt.adjust(ExpnId::root());
180-
Scope::ExternPrelude
185+
Scope::ExternPreludeItems
181186
}
182187
ValueNS | MacroNS => break,
183188
},
@@ -194,7 +199,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
194199
None => {
195200
ctxt.adjust(ExpnId::root());
196201
match ns {
197-
TypeNS => Scope::ExternPrelude,
202+
TypeNS => Scope::ExternPreludeItems,
198203
ValueNS => Scope::StdLibPrelude,
199204
MacroNS => Scope::MacroUsePrelude,
200205
}
@@ -203,8 +208,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
203208
}
204209
Scope::MacroUsePrelude => Scope::StdLibPrelude,
205210
Scope::BuiltinAttrs => break, // nowhere else to search
206-
Scope::ExternPrelude if module_and_extern_prelude => break,
207-
Scope::ExternPrelude => Scope::ToolPrelude,
211+
Scope::ExternPreludeItems => Scope::ExternPreludeFlags,
212+
Scope::ExternPreludeFlags if module_and_extern_prelude || extern_prelude => break,
213+
Scope::ExternPreludeFlags => Scope::ToolPrelude,
208214
Scope::ToolPrelude => Scope::StdLibPrelude,
209215
Scope::StdLibPrelude => match ns {
210216
TypeNS => Scope::BuiltinTypes,
@@ -390,9 +396,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
390396
struct Flags: u8 {
391397
const MACRO_RULES = 1 << 0;
392398
const MODULE = 1 << 1;
393-
const MISC_SUGGEST_CRATE = 1 << 2;
394-
const MISC_SUGGEST_SELF = 1 << 3;
395-
const MISC_FROM_PRELUDE = 1 << 4;
399+
const EXTERN_PRELUDE = 1 << 2;
400+
const MISC_SUGGEST_CRATE = 1 << 3;
401+
const MISC_SUGGEST_SELF = 1 << 4;
402+
const MISC_FROM_PRELUDE = 1 << 5;
396403
}
397404
}
398405

@@ -407,6 +414,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
407414
ScopeSet::All(ns)
408415
| ScopeSet::ModuleAndExternPrelude(ns, _)
409416
| ScopeSet::Late(ns, ..) => (ns, None),
417+
ScopeSet::ExternPrelude => (TypeNS, None),
410418
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
411419
};
412420

@@ -555,14 +563,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
555563
Some(binding) => Ok((*binding, Flags::empty())),
556564
None => Err(Determinacy::Determined),
557565
},
558-
Scope::ExternPrelude => {
559-
match this.extern_prelude_get(ident, finalize.is_some()) {
560-
Some(binding) => Ok((binding, Flags::empty())),
566+
Scope::ExternPreludeItems => {
567+
match this.extern_prelude_get_item(ident, finalize.is_some()) {
568+
Some(binding) => Ok((binding, Flags::EXTERN_PRELUDE)),
561569
None => Err(Determinacy::determined(
562570
this.graph_root.unexpanded_invocations.borrow().is_empty(),
563571
)),
564572
}
565573
}
574+
Scope::ExternPreludeFlags => {
575+
match this.extern_prelude_get_flag(ident, finalize.is_some()) {
576+
Some(binding) => Ok((binding, Flags::EXTERN_PRELUDE)),
577+
None => Err(Determinacy::Determined),
578+
}
579+
}
566580
Scope::ToolPrelude => match this.registered_tool_bindings.get(&ident) {
567581
Some(binding) => Ok((*binding, Flags::empty())),
568582
None => Err(Determinacy::Determined),
@@ -671,7 +685,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
671685
} else if innermost_binding
672686
.may_appear_after(parent_scope.expansion, binding)
673687
{
674-
Some(AmbiguityKind::MoreExpandedVsOuter)
688+
if flags.contains(Flags::EXTERN_PRELUDE)
689+
&& innermost_flags.contains(Flags::EXTERN_PRELUDE)
690+
{
691+
Some(AmbiguityKind::ExternPrelude)
692+
} else {
693+
Some(AmbiguityKind::MoreExpandedVsOuter)
694+
}
675695
} else {
676696
None
677697
};
@@ -812,13 +832,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
812832
assert_eq!(shadowing, Shadowing::Unrestricted);
813833
return if ns != TypeNS {
814834
Err((Determined, Weak::No))
815-
} else if let Some(binding) = self.extern_prelude_get(ident, finalize.is_some()) {
816-
Ok(binding)
817-
} else if !self.graph_root.unexpanded_invocations.borrow().is_empty() {
818-
// Macro-expanded `extern crate` items can add names to extern prelude.
819-
Err((Undetermined, Weak::No))
820835
} else {
821-
Err((Determined, Weak::No))
836+
let binding = self.early_resolve_ident_in_lexical_scope(
837+
ident,
838+
ScopeSet::ExternPrelude,
839+
parent_scope,
840+
finalize,
841+
finalize.is_some(),
842+
ignore_binding,
843+
ignore_import,
844+
);
845+
return binding.map_err(|determinacy| (determinacy, Weak::No));
822846
};
823847
}
824848
ModuleOrUniformRoot::CurrentScope => {

compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2477,19 +2477,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
24772477
} else {
24782478
// Items from the prelude
24792479
if !module.no_implicit_prelude {
2480-
let extern_prelude = self.r.extern_prelude.clone();
2481-
names.extend(extern_prelude.iter().flat_map(|(ident, _)| {
2482-
self.r
2483-
.cstore_mut()
2484-
.maybe_process_path_extern(self.r.tcx, ident.name)
2485-
.and_then(|crate_id| {
2486-
let crate_mod =
2487-
Res::Def(DefKind::Mod, crate_id.as_def_id());
2488-
2489-
filter_fn(crate_mod).then(|| {
2490-
TypoSuggestion::typo_from_ident(*ident, crate_mod)
2491-
})
2492-
})
2480+
names.extend(self.r.extern_prelude.keys().flat_map(|ident| {
2481+
let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
2482+
filter_fn(res)
2483+
.then_some(TypoSuggestion::typo_from_ident(*ident, res))
24932484
}));
24942485

24952486
if let Some(prelude) = self.r.prelude {

0 commit comments

Comments
 (0)