From 40de40e0941c3c7dde0cb5dd8e116d0051481543 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 26 Apr 2023 20:53:05 +0200 Subject: [PATCH] Add typed `{Local}DefId` for modules This allows for better type safety in the compiler and also improves the documentation for many things, making it clear that they expect modules. --- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../rustc_middle/src/dep_graph/dep_node.rs | 52 +++++++++- compiler/rustc_privacy/src/lib.rs | 2 +- compiler/rustc_span/src/def_id.rs | 95 +++++++++++++++++++ 4 files changed, 148 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 8a5099804ed..e453fadf4b2 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1448,7 +1448,7 @@ pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { for id in module.items() { check_item_type(tcx, id); } - if module_def_id == CRATE_DEF_ID { + if module_def_id == LocalModDefId::CRATE_DEF_ID { super::entry::check_for_entry_fn(tcx); } } diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 06251bccc98..04c09d33400 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -60,7 +60,7 @@ use crate::mir::mono::MonoItem; use crate::ty::TyCtxt; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LOCAL_CRATE}; use rustc_hir::definitions::DefPathHash; use rustc_hir::{HirId, ItemLocalId, OwnerId}; use rustc_query_system::dep_graph::FingerprintStyle; @@ -387,3 +387,53 @@ impl<'tcx> DepNodeParams> for HirId { } } } + +macro_rules! impl_for_typed_def_id { + ($Name:ident, $LocalName:ident) => { + impl<'tcx> DepNodeParams> for $Name { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + DefId::recover(tcx, dep_node).map($Name::new_unchecked) + } + } + + impl<'tcx> DepNodeParams> for $LocalName { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + LocalDefId::recover(tcx, dep_node).map($LocalName::new_unchecked) + } + } + }; +} + +impl_for_typed_def_id! { ModDefId, LocalModDefId } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 30a4235d371..bf40b43b3bc 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -519,7 +519,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { loop { let changed_reachability = self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev); - if changed_reachability || module_def_id == CRATE_DEF_ID { + if changed_reachability || module_def_id == LocalModDefId::CRATE_DEF_ID { break; } module_def_id = self.tcx.local_parent(module_def_id); diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index f65a6aa4fb2..c03487fd3ca 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -28,10 +28,16 @@ impl CrateNum { CrateNum::from_usize(x) } + // FIXME(Nilstrieb): Replace this with `as_mod_def_id`. #[inline] pub fn as_def_id(self) -> DefId { DefId { krate: self, index: CRATE_DEF_INDEX } } + + #[inline] + pub fn as_mod_def_id(self) -> ModDefId { + ModDefId::new_unchecked(DefId { krate: self, index: CRATE_DEF_INDEX }) + } } impl fmt::Display for CrateNum { @@ -485,3 +491,92 @@ impl ToStableHashKey for CrateNum { self.as_def_id().to_stable_hash_key(hcx) } } + +macro_rules! typed_def_id { + ($Name:ident, $LocalName:ident) => { + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)] + pub struct $Name(DefId); + + impl $Name { + pub const fn new_unchecked(def_id: DefId) -> Self { + Self(def_id) + } + + pub fn to_def_id(self) -> DefId { + self.into() + } + + pub fn is_local(self) -> bool { + self.0.is_local() + } + + pub fn as_local(self) -> Option<$LocalName> { + self.0.as_local().map($LocalName::new_unchecked) + } + } + + impl From<$LocalName> for $Name { + fn from(local: $LocalName) -> Self { + Self(local.0.to_def_id()) + } + } + + impl From<$Name> for DefId { + fn from(typed: $Name) -> Self { + typed.0 + } + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)] + pub struct $LocalName(LocalDefId); + + impl !Ord for $LocalName {} + impl !PartialOrd for $LocalName {} + + impl $LocalName { + pub const fn new_unchecked(def_id: LocalDefId) -> Self { + Self(def_id) + } + + pub fn to_def_id(self) -> DefId { + self.0.into() + } + + pub fn to_local_def_id(self) -> LocalDefId { + self.0 + } + } + + impl From<$LocalName> for LocalDefId { + fn from(typed: $LocalName) -> Self { + typed.0 + } + } + + impl From<$LocalName> for DefId { + fn from(typed: $LocalName) -> Self { + typed.0.into() + } + } + }; +} + +// N.B.: when adding new typed `DefId`s update the corresponding trait impls in +// `rustc_middle::dep_graph::def_node` for `DepNodeParams`. +typed_def_id! { ModDefId, LocalModDefId } + +impl LocalModDefId { + pub const CRATE_DEF_ID: Self = Self::new_unchecked(CRATE_DEF_ID); +} + +impl ModDefId { + pub fn is_top_level_module(self) -> bool { + self.0.is_top_level_module() + } +} + +impl LocalModDefId { + pub fn is_top_level_module(self) -> bool { + self.0.is_top_level_module() + } +}