Skip to content

Commit

Permalink
Optionally add type names to TypeIds.
Browse files Browse the repository at this point in the history
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`.
  • Loading branch information
kpreid committed Jan 27, 2025
1 parent 01a26c0 commit 9a6fa11
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 4 deletions.
2 changes: 2 additions & 0 deletions library/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ optimize_for_size = []
# Make `RefCell` store additional debugging information, which is printed out when
# a borrow error occurs
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]
level = "warn"
Expand Down
17 changes: 14 additions & 3 deletions library/core/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,8 @@ pub struct TypeId {
// We avoid using `u128` because that imposes higher alignment requirements on many platforms.
// See issue #115620 for more information.
t: (u64, u64),
#[cfg(feature = "debug_typeid")]
name: &'static str,
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -647,10 +649,14 @@ impl TypeId {
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
pub const fn of<T: ?Sized + 'static>() -> TypeId {
let t: u128 = intrinsics::type_id::<T>();

let t1 = (t >> 64) 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 {
Expand Down Expand Up @@ -681,7 +687,12 @@ impl hash::Hash for TypeId {
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for TypeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "TypeId({:#034x})", self.as_u128())
write!(f, "TypeId({:#034x}", self.as_u128())?;
#[cfg(feature = "debug_typeid")]
{
write!(f, " = {}", self.name)?;
}
write!(f, ")")
}
}

Expand Down
8 changes: 8 additions & 0 deletions library/core/tests/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ fn any_unsized() {
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]
fn distinct_type_names() {
// https://github.com/rust-lang/rust/issues/84666
Expand Down
7 changes: 7 additions & 0 deletions library/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ panic_immediate_abort = [
# Choose algorithms that are optimized for binary size instead of runtime performance
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:
# https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml
std_detect_file_io = ["std_detect/std_detect_file_io"]
Expand Down
4 changes: 3 additions & 1 deletion library/sysroot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ compiler-builtins-mem = ["std/compiler-builtins-mem"]
compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"]
compiler-builtins-no-f16-f128 = ["std/compiler-builtins-no-f16-f128"]
compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"]
debug_refcell = ["std/debug_refcell"]
debug_typeid = ["std/debug_typeid"]
llvm-libunwind = ["std/llvm-libunwind"]
system-llvm-libunwind = ["std/system-llvm-libunwind"]
optimize_for_size = ["std/optimize_for_size"]
panic-unwind = ["std/panic_unwind"]
panic_immediate_abort = ["std/panic_immediate_abort"]
optimize_for_size = ["std/optimize_for_size"]
profiler = ["dep:profiler_builtins"]
std_detect_file_io = ["std/std_detect_file_io"]
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
Expand Down

0 comments on commit 9a6fa11

Please sign in to comment.