hir: Do not introduce dummy type names for extern blocks in def paths

Use a separate nameless `DefPathData` variant instead
This commit is contained in:
Vadim Petrochenkov 2021-12-17 16:45:15 +08:00
parent dde825db46
commit 0d61852cc5
8 changed files with 36 additions and 31 deletions

View File

@ -267,6 +267,8 @@ pub enum DefPathData {
// Different kinds of items and item-like things: // Different kinds of items and item-like things:
/// An impl. /// An impl.
Impl, Impl,
/// An `extern` block.
ForeignMod,
/// Something in the type namespace. /// Something in the type namespace.
TypeNs(Symbol), TypeNs(Symbol),
/// Something in the value namespace. /// Something in the value namespace.
@ -469,7 +471,9 @@ impl DefPathData {
match *self { match *self {
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
Impl | CrateRoot | Misc | ClosureExpr | Ctor | AnonConst | ImplTrait => None, Impl | ForeignMod | CrateRoot | Misc | ClosureExpr | Ctor | AnonConst | ImplTrait => {
None
}
} }
} }
@ -482,6 +486,7 @@ impl DefPathData {
// Note that this does not show up in user print-outs. // Note that this does not show up in user print-outs.
CrateRoot => DefPathDataName::Anon { namespace: kw::Crate }, CrateRoot => DefPathDataName::Anon { namespace: kw::Crate },
Impl => DefPathDataName::Anon { namespace: kw::Impl }, Impl => DefPathDataName::Anon { namespace: kw::Impl },
ForeignMod => DefPathDataName::Anon { namespace: kw::Extern },
Misc => DefPathDataName::Anon { namespace: sym::misc }, Misc => DefPathDataName::Anon { namespace: sym::misc },
ClosureExpr => DefPathDataName::Anon { namespace: sym::closure }, ClosureExpr => DefPathDataName::Anon { namespace: sym::closure },
Ctor => DefPathDataName::Anon { namespace: sym::constructor }, Ctor => DefPathDataName::Anon { namespace: sym::constructor },

View File

@ -1040,8 +1040,8 @@ impl<'tcx> LateContext<'tcx> {
) -> Result<Self::Path, Self::Error> { ) -> Result<Self::Path, Self::Error> {
let mut path = print_prefix(self)?; let mut path = print_prefix(self)?;
// Skip `::{{constructor}}` on tuple/unit structs. // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs.
if let DefPathData::Ctor = disambiguated_data.data { if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data {
return Ok(path); return Ok(path);
} }

View File

@ -1740,15 +1740,12 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
) -> Result<Self::Path, Self::Error> { ) -> Result<Self::Path, Self::Error> {
self = print_prefix(self)?; self = print_prefix(self)?;
// Skip `::{{constructor}}` on tuple/unit structs. // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs.
if let DefPathData::Ctor = disambiguated_data.data { if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data {
return Ok(self); return Ok(self);
} }
// FIXME(eddyb) `name` should never be empty, but it
// currently is for `extern { ... }` "foreign modules".
let name = disambiguated_data.data.name(); let name = disambiguated_data.data.name();
if name != DefPathDataName::Named(kw::Empty) {
if !self.empty_path { if !self.empty_path {
write!(self, "::")?; write!(self, "::")?;
} }
@ -1763,7 +1760,6 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
disambiguated_data.fmt_maybe_verbose(&mut self, verbose)?; disambiguated_data.fmt_maybe_verbose(&mut self, verbose)?;
self.empty_path = false; self.empty_path = false;
}
Ok(self) Ok(self)
} }

View File

@ -92,6 +92,7 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
// information we encapsulate into, the better // information we encapsulate into, the better
let def_data = match &i.kind { let def_data = match &i.kind {
ItemKind::Impl { .. } => DefPathData::Impl, ItemKind::Impl { .. } => DefPathData::Impl,
ItemKind::ForeignMod(..) => DefPathData::ForeignMod,
ItemKind::Mod(..) ItemKind::Mod(..)
| ItemKind::Trait(..) | ItemKind::Trait(..)
| ItemKind::TraitAlias(..) | ItemKind::TraitAlias(..)
@ -99,7 +100,6 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
| ItemKind::Struct(..) | ItemKind::Struct(..)
| ItemKind::Union(..) | ItemKind::Union(..)
| ItemKind::ExternCrate(..) | ItemKind::ExternCrate(..)
| ItemKind::ForeignMod(..)
| ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), | ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => { ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => {
DefPathData::ValueNs(i.ident.name) DefPathData::ValueNs(i.ident.name)

View File

@ -311,8 +311,8 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
) -> Result<Self::Path, Self::Error> { ) -> Result<Self::Path, Self::Error> {
self = print_prefix(self)?; self = print_prefix(self)?;
// Skip `::{{constructor}}` on tuple/unit structs. // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs.
if let DefPathData::Ctor = disambiguated_data.data { if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data {
return Ok(self); return Ok(self);
} }

View File

@ -771,6 +771,10 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
disambiguated_data: &DisambiguatedDefPathData, disambiguated_data: &DisambiguatedDefPathData,
) -> Result<Self::Path, Self::Error> { ) -> Result<Self::Path, Self::Error> {
let ns = match disambiguated_data.data { let ns = match disambiguated_data.data {
// FIXME: It shouldn't be necessary to add anything for extern block segments,
// but we add 't' for backward compatibility.
DefPathData::ForeignMod => 't',
// Uppercase categories are more stable than lowercase ones. // Uppercase categories are more stable than lowercase ones.
DefPathData::TypeNs(_) => 't', DefPathData::TypeNs(_) => 't',
DefPathData::ValueNs(_) => 'v', DefPathData::ValueNs(_) => 'v',

View File

@ -8,6 +8,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::definitions::DefPathData;
use rustc_hir::Mutability; use rustc_hir::Mutability;
use rustc_metadata::creader::{CStore, LoadedMacro}; use rustc_metadata::creader::{CStore, LoadedMacro};
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
@ -165,9 +166,8 @@ crate fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemType)
let crate_name = cx.tcx.crate_name(did.krate).to_string(); let crate_name = cx.tcx.crate_name(did.krate).to_string();
let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| { let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| {
// extern blocks have an empty name // Filter out extern blocks
let s = elem.data.to_string(); (elem.data != DefPathData::ForeignMod).then(|| elem.data.to_string())
if !s.is_empty() { Some(s) } else { None }
}); });
let fqn = if let ItemType::Macro = kind { let fqn = if let ItemType::Macro = kind {
// Check to see if it is a macro 2.0 or built-in macro // Check to see if it is a macro 2.0 or built-in macro

View File

@ -5,6 +5,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::definitions::DefPathData;
use rustc_hir::Node; use rustc_hir::Node;
use rustc_hir::CRATE_HIR_ID; use rustc_hir::CRATE_HIR_ID;
use rustc_middle::middle::privacy::AccessLevel; use rustc_middle::middle::privacy::AccessLevel;
@ -45,9 +46,8 @@ impl Module<'hir> {
fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<String> { fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<String> {
let crate_name = tcx.crate_name(did.krate).to_string(); let crate_name = tcx.crate_name(did.krate).to_string();
let relative = tcx.def_path(did).data.into_iter().filter_map(|elem| { let relative = tcx.def_path(did).data.into_iter().filter_map(|elem| {
// extern blocks have an empty name // Filter out extern blocks
let s = elem.data.to_string(); (elem.data != DefPathData::ForeignMod).then(|| elem.data.to_string())
if !s.is_empty() { Some(s) } else { None }
}); });
std::iter::once(crate_name).chain(relative).collect() std::iter::once(crate_name).chain(relative).collect()
} }