Skip to content

Commit 05010b6

Browse files
committed
resolve: Make bindings from extern prelude unique
instead of creating a new every time a name from extern prelude is accessed
1 parent 9ce3519 commit 05010b6

File tree

2 files changed

+38
-19
lines changed

2 files changed

+38
-19
lines changed

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -870,10 +870,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
870870
let imported_binding = self.r.import(binding, import);
871871
if parent == self.r.graph_root {
872872
if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
873-
if expansion != LocalExpnId::ROOT
874-
&& orig_name.is_some()
875-
&& entry.extern_crate_item.is_none()
876-
{
873+
if expansion != LocalExpnId::ROOT && orig_name.is_some() && !entry.is_import() {
877874
let msg = "macro-expanded `extern crate` items cannot \
878875
shadow names passed with `--extern`";
879876
self.r.tcx.sess.span_err(item.span, msg);
@@ -884,10 +881,14 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
884881
return;
885882
}
886883
}
887-
let entry = self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
888-
ExternPreludeEntry { extern_crate_item: None, introduced_by_item: true },
889-
);
890-
entry.extern_crate_item = Some(imported_binding);
884+
let entry = self
885+
.r
886+
.extern_prelude
887+
.entry(ident.normalize_to_macros_2_0())
888+
.or_insert(ExternPreludeEntry { binding: None, introduced_by_item: true });
889+
// Binding from `extern crate` item in source code can replace
890+
// a binding from `--extern` on command line here.
891+
entry.binding = Some(imported_binding);
891892
if orig_name.is_some() {
892893
entry.introduced_by_item = true;
893894
}

compiler/rustc_resolve/src/lib.rs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -885,10 +885,16 @@ impl<'a> NameBindingData<'a> {
885885

886886
#[derive(Default, Clone)]
887887
struct ExternPreludeEntry<'a> {
888-
extern_crate_item: Option<NameBinding<'a>>,
888+
binding: Option<NameBinding<'a>>,
889889
introduced_by_item: bool,
890890
}
891891

892+
impl ExternPreludeEntry<'_> {
893+
fn is_import(&self) -> bool {
894+
self.binding.is_some_and(|binding| binding.is_import())
895+
}
896+
}
897+
892898
/// Used for better errors for E0773
893899
enum BuiltinMacroState {
894900
NotYetSeen(SyntaxExtensionKind),
@@ -1742,7 +1748,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
17421748
// but not introduce it, as used if they are accessed from lexical scope.
17431749
if is_lexical_scope {
17441750
if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
1745-
if !entry.introduced_by_item && entry.extern_crate_item == Some(used_binding) {
1751+
if !entry.introduced_by_item && entry.binding == Some(used_binding) {
17461752
return;
17471753
}
17481754
}
@@ -1900,12 +1906,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
19001906
// Make sure `self`, `super` etc produce an error when passed to here.
19011907
return None;
19021908
}
1903-
self.extern_prelude.get(&ident.normalize_to_macros_2_0()).cloned().and_then(|entry| {
1904-
if let Some(binding) = entry.extern_crate_item {
1905-
if finalize && entry.introduced_by_item {
1906-
self.record_use(ident, binding, false);
1909+
1910+
let norm_ident = ident.normalize_to_macros_2_0();
1911+
let binding = self.extern_prelude.get(&norm_ident).cloned().and_then(|entry| {
1912+
Some(if let Some(binding) = entry.binding {
1913+
if finalize {
1914+
if !entry.is_import() {
1915+
self.crate_loader(|c| c.process_path_extern(ident.name, ident.span));
1916+
} else if entry.introduced_by_item {
1917+
self.record_use(ident, binding, false);
1918+
}
19071919
}
1908-
Some(binding)
1920+
binding
19091921
} else {
19101922
let crate_id = if finalize {
19111923
let Some(crate_id) =
@@ -1918,10 +1930,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
19181930
self.crate_loader(|c| c.maybe_process_path_extern(ident.name))?
19191931
};
19201932
let crate_root = self.expect_module(crate_id.as_def_id());
1921-
let vis = ty::Visibility::<LocalDefId>::Public;
1922-
Some((crate_root, vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(self.arenas))
1923-
}
1924-
})
1933+
let vis = ty::Visibility::<DefId>::Public;
1934+
(crate_root, vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(self.arenas)
1935+
})
1936+
});
1937+
1938+
if let Some(entry) = self.extern_prelude.get_mut(&norm_ident) {
1939+
entry.binding = binding;
1940+
}
1941+
1942+
binding
19251943
}
19261944

19271945
/// Rustdoc uses this to resolve doc link paths in a recoverable way. `PathResult<'a>`

0 commit comments

Comments
 (0)