1
Fork 0

Optionally add type names to TypeIds.

This feature is intended to provide expensive but thorough help for
developers who have an unexpected `TypeId` value and need to determine
what type it actually is. It causes `impl Debug for TypeId` to print
the type name in addition to the opaque ID hash, and in order to do so,
adds a name field to `TypeId`. The cost of this is the increased size of
`TypeId` and the need to store type names in the binary; therefore, it
is an optional feature.

It may be enabled via `cargo -Zbuild-std -Zbuild-std-features=debug_typeid`.
(Note that `-Zbuild-std-features` disables default features which you
may wish to reenable in addition; see
<https://doc.rust-lang.org/cargo/reference/unstable.html#build-std-features>.)

Example usage and output:

```
fn main() {
    use std::any::{Any, TypeId};
    dbg!(TypeId::of::<usize>(), drop::<usize>.type_id());
}
```

```
TypeId::of::<usize>() = TypeId(0x763d199bccd319899208909ed1a860c6 = usize)
drop::<usize>.type_id() = TypeId(0xe6a34bd13f8c92dd47806da07b8cca9a = core::mem::drop<usize>)
```

Also added feature declarations for the existing `debug_refcell` feature
so it is usable from the `rust.std-features` option of `config.toml`.
This commit is contained in:
Kevin Reid 2025-01-27 09:34:56 -08:00
parent 0cffe5cb95
commit d2ed8cf661
5 changed files with 37 additions and 4 deletions

View file

@ -23,6 +23,8 @@ optimize_for_size = []
# Make `RefCell` store additional debugging information, which is printed out when # Make `RefCell` store additional debugging information, which is printed out when
# a borrow error occurs # a borrow error occurs
debug_refcell = [] debug_refcell = []
# Make `TypeId` store a reference to the name of the type, so that it can print that name.
debug_typeid = []
[lints.rust.unexpected_cfgs] [lints.rust.unexpected_cfgs]
level = "warn" level = "warn"

View file

@ -616,6 +616,8 @@ pub struct TypeId {
// We avoid using `u128` because that imposes higher alignment requirements on many platforms. // We avoid using `u128` because that imposes higher alignment requirements on many platforms.
// See issue #115620 for more information. // See issue #115620 for more information.
t: (u64, u64), t: (u64, u64),
#[cfg(feature = "debug_typeid")]
name: &'static str,
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -647,10 +649,14 @@ impl TypeId {
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")] #[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
pub const fn of<T: ?Sized + 'static>() -> TypeId { pub const fn of<T: ?Sized + 'static>() -> TypeId {
let t: u128 = intrinsics::type_id::<T>(); let t: u128 = intrinsics::type_id::<T>();
let t1 = (t >> 64) as u64; let t1 = (t >> 64) as u64;
let t2 = t as u64; let t2 = t as u64;
TypeId { t: (t1, t2) }
TypeId {
t: (t1, t2),
#[cfg(feature = "debug_typeid")]
name: type_name::<T>(),
}
} }
fn as_u128(self) -> u128 { fn as_u128(self) -> u128 {
@ -681,7 +687,15 @@ impl hash::Hash for TypeId {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for TypeId { impl fmt::Debug for TypeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "TypeId({:#034x})", self.as_u128()) #[cfg(feature = "debug_typeid")]
{
write!(f, "TypeId({:#034x} = {})", self.as_u128(), self.name)?;
}
#[cfg(not(feature = "debug_typeid"))]
{
write!(f, "TypeId({:#034x})", self.as_u128())?;
}
Ok(())
} }
} }

View file

@ -118,6 +118,14 @@ fn any_unsized() {
is_any::<[i32]>(); is_any::<[i32]>();
} }
#[cfg(feature = "debug_typeid")]
#[test]
fn debug_typeid_includes_name() {
let type_id = TypeId::of::<[usize; 2]>();
let debug_str = format!("{type_id:?}");
assert!(debug_str.ends_with("= [usize; 2])"), "{debug_str:?} did not match");
}
#[test] #[test]
fn distinct_type_names() { fn distinct_type_names() {
// https://github.com/rust-lang/rust/issues/84666 // https://github.com/rust-lang/rust/issues/84666

View file

@ -109,6 +109,13 @@ panic_immediate_abort = [
# Choose algorithms that are optimized for binary size instead of runtime performance # Choose algorithms that are optimized for binary size instead of runtime performance
optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"] optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
# Make `RefCell` store additional debugging information, which is printed out when
# a borrow error occurs
debug_refcell = ["core/debug_refcell"]
# Make `TypeId` store a reference to the name of the type, so that it can print that name.
debug_typeid = ["core/debug_typeid"]
# Enable std_detect default features for stdarch/crates/std_detect: # Enable std_detect default features for stdarch/crates/std_detect:
# https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml # https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml
std_detect_file_io = ["std_detect/std_detect_file_io"] std_detect_file_io = ["std_detect/std_detect_file_io"]

View file

@ -19,11 +19,13 @@ compiler-builtins-mem = ["std/compiler-builtins-mem"]
compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"] compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"]
compiler-builtins-no-f16-f128 = ["std/compiler-builtins-no-f16-f128"] compiler-builtins-no-f16-f128 = ["std/compiler-builtins-no-f16-f128"]
compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"] compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"]
debug_refcell = ["std/debug_refcell"]
debug_typeid = ["std/debug_typeid"]
llvm-libunwind = ["std/llvm-libunwind"] llvm-libunwind = ["std/llvm-libunwind"]
system-llvm-libunwind = ["std/system-llvm-libunwind"] system-llvm-libunwind = ["std/system-llvm-libunwind"]
optimize_for_size = ["std/optimize_for_size"]
panic-unwind = ["std/panic_unwind"] panic-unwind = ["std/panic_unwind"]
panic_immediate_abort = ["std/panic_immediate_abort"] panic_immediate_abort = ["std/panic_immediate_abort"]
optimize_for_size = ["std/optimize_for_size"]
profiler = ["dep:profiler_builtins"] profiler = ["dep:profiler_builtins"]
std_detect_file_io = ["std/std_detect_file_io"] std_detect_file_io = ["std/std_detect_file_io"]
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"] std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]