Reflection = a program inspecting a value’s type at runtime (Java/Go/Python: determine type, explore fields, invoke methods). Rust has none of this — and can’t, by design. Its default is the opposite: types are resolved at compile time (monomorphization) or erased (trait objects), so a value carries no “what am I” tag at runtime. There’s nothing to reflect on.

The std::any helpers look reflective but aren’t — they’re compile-time generics:

  • std::any::type_name::<T>() — generic, so type_name::<u32> and type_name::<Square> are different monomorphized functions, each baking in a statically-known type. Returns a diagnostic string; best-effort, may change, may not be unique — don’t parse it.
  • TypeId::of::<T>() — compile-time, unique, code-usable type identifier.

The tell that proves it’s compile-time, not runtime: feed a trait object.

let square = Square::new(1, 2, 2);
let shape: &dyn Shape = &square;
println!("{}", type_name_of(&shape)); // "&dyn Shape", NOT "Square"

It reports the static type of the reference (&dyn Shape), not the concrete Square, because forming the trait object erased the concrete type — nothing at runtime carries it. Real reflection (Java/Go) would report the runtime Square.

See also

References

Questions

flashcards/rust

Does Rust have runtime reflection (inspect a value’s type at runtime like Java/Go)?::No. Types are resolved at compile time (monomorphization) or erased (trait objects); values carry no runtime type tag, so there’s nothing to reflect on.

How do type_name::<T>() and TypeId::of::<T>() work?::They’re compile-time generic functions monomorphized per type — they report the static type parameter T, with no runtime inspection.

For shape: &dyn Shape backing a Square, type_name reports `&dyn Shape` (the static reference type), not Square, because the concrete type was erased.