resolve: Make bindings from extern prelude unique
instead of creating a new every time a name from extern prelude is accessed
This commit is contained in:
parent
9ce35198bf
commit
05010b6074
2 changed files with 38 additions and 19 deletions
|
@ -870,10 +870,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
let imported_binding = self.r.import(binding, import);
|
||||
if parent == self.r.graph_root {
|
||||
if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
|
||||
if expansion != LocalExpnId::ROOT
|
||||
&& orig_name.is_some()
|
||||
&& entry.extern_crate_item.is_none()
|
||||
{
|
||||
if expansion != LocalExpnId::ROOT && orig_name.is_some() && !entry.is_import() {
|
||||
let msg = "macro-expanded `extern crate` items cannot \
|
||||
shadow names passed with `--extern`";
|
||||
self.r.tcx.sess.span_err(item.span, msg);
|
||||
|
@ -884,10 +881,14 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
return;
|
||||
}
|
||||
}
|
||||
let entry = self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
|
||||
ExternPreludeEntry { extern_crate_item: None, introduced_by_item: true },
|
||||
);
|
||||
entry.extern_crate_item = Some(imported_binding);
|
||||
let entry = self
|
||||
.r
|
||||
.extern_prelude
|
||||
.entry(ident.normalize_to_macros_2_0())
|
||||
.or_insert(ExternPreludeEntry { binding: None, introduced_by_item: true });
|
||||
// Binding from `extern crate` item in source code can replace
|
||||
// a binding from `--extern` on command line here.
|
||||
entry.binding = Some(imported_binding);
|
||||
if orig_name.is_some() {
|
||||
entry.introduced_by_item = true;
|
||||
}
|
||||
|
|
|
@ -885,10 +885,16 @@ impl<'a> NameBindingData<'a> {
|
|||
|
||||
#[derive(Default, Clone)]
|
||||
struct ExternPreludeEntry<'a> {
|
||||
extern_crate_item: Option<NameBinding<'a>>,
|
||||
binding: Option<NameBinding<'a>>,
|
||||
introduced_by_item: bool,
|
||||
}
|
||||
|
||||
impl ExternPreludeEntry<'_> {
|
||||
fn is_import(&self) -> bool {
|
||||
self.binding.is_some_and(|binding| binding.is_import())
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for better errors for E0773
|
||||
enum BuiltinMacroState {
|
||||
NotYetSeen(SyntaxExtensionKind),
|
||||
|
@ -1742,7 +1748,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
// but not introduce it, as used if they are accessed from lexical scope.
|
||||
if is_lexical_scope {
|
||||
if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
|
||||
if !entry.introduced_by_item && entry.extern_crate_item == Some(used_binding) {
|
||||
if !entry.introduced_by_item && entry.binding == Some(used_binding) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1900,12 +1906,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
// Make sure `self`, `super` etc produce an error when passed to here.
|
||||
return None;
|
||||
}
|
||||
self.extern_prelude.get(&ident.normalize_to_macros_2_0()).cloned().and_then(|entry| {
|
||||
if let Some(binding) = entry.extern_crate_item {
|
||||
if finalize && entry.introduced_by_item {
|
||||
self.record_use(ident, binding, false);
|
||||
|
||||
let norm_ident = ident.normalize_to_macros_2_0();
|
||||
let binding = self.extern_prelude.get(&norm_ident).cloned().and_then(|entry| {
|
||||
Some(if let Some(binding) = entry.binding {
|
||||
if finalize {
|
||||
if !entry.is_import() {
|
||||
self.crate_loader(|c| c.process_path_extern(ident.name, ident.span));
|
||||
} else if entry.introduced_by_item {
|
||||
self.record_use(ident, binding, false);
|
||||
}
|
||||
}
|
||||
Some(binding)
|
||||
binding
|
||||
} else {
|
||||
let crate_id = if finalize {
|
||||
let Some(crate_id) =
|
||||
|
@ -1918,10 +1930,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
self.crate_loader(|c| c.maybe_process_path_extern(ident.name))?
|
||||
};
|
||||
let crate_root = self.expect_module(crate_id.as_def_id());
|
||||
let vis = ty::Visibility::<LocalDefId>::Public;
|
||||
Some((crate_root, vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(self.arenas))
|
||||
}
|
||||
})
|
||||
let vis = ty::Visibility::<DefId>::Public;
|
||||
(crate_root, vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(self.arenas)
|
||||
})
|
||||
});
|
||||
|
||||
if let Some(entry) = self.extern_prelude.get_mut(&norm_ident) {
|
||||
entry.binding = binding;
|
||||
}
|
||||
|
||||
binding
|
||||
}
|
||||
|
||||
/// Rustdoc uses this to resolve doc link paths in a recoverable way. `PathResult<'a>`
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue