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.
This commit is contained in:
Nilstrieb 2023-04-26 20:53:05 +02:00 committed by Deadbeef
parent cb0c29978b
commit 40de40e094
4 changed files with 148 additions and 3 deletions

View File

@ -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);
}
}

View File

@ -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<TyCtxt<'tcx>> for HirId {
}
}
}
macro_rules! impl_for_typed_def_id {
($Name:ident, $LocalName:ident) => {
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> 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<Self> {
DefId::recover(tcx, dep_node).map($Name::new_unchecked)
}
}
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> 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<Self> {
LocalDefId::recover(tcx, dep_node).map($LocalName::new_unchecked)
}
}
};
}
impl_for_typed_def_id! { ModDefId, LocalModDefId }

View File

@ -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);

View File

@ -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<CTX: HashStableContext> ToStableHashKey<CTX> 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()
}
}