Description
Currently TypeId
s have uninformative derived Debug
impls:
fn main() {
println!("{:?}", std::any::TypeId::of::<usize>());
}
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 0.91s
Running `target/debug/playground`
TypeId { t: 8766594652559642870 }
This results in fairly poor Debug output for dynamic types like anymap
.
I think it could be quite nice for debugging/logging/etc to allow printing the type name from a TypeId
in the Debug impl. It would provide an out of the box improvement to debugging existing dynamic typing tools, and IIUC the contents of Debug impls in the standard library are not considered stable so there's neither a breaking change here nor a de facto stabilization of the type_name representation.
I assume this would need to rely on some unstable intrinsic being exposed to get the type_name of an ID at run time, but I'm not really aware what would be needed.
Thoughts? cc @oli-obk as we had discussed this a bit on IRC.
Activity
czipperz commentedon Jun 5, 2019
I think this is a cool idea. However, to implement this we would probably have to add some sort of type table to each application binary. That seems like it could become extremely expensive as each instantiation of a generic type would be stored separately.
oli-obk commentedon Jun 5, 2019
The amount of extra memory needed is fairly limited, as most of these type names will already have ended up somewhere in the binary. So we could just have the other places refer to the table entries instad of having their own version of the name.
For release builds we could even just skip this table entirely and fall back to id printing.
Alternatively we can make the
TypeId
struct have a&'static str
field in debug mode and just fill it in 😆Centril commentedon Jun 5, 2019
Ostensibly we need something like this to deal with the soundness hole in #10389?
oli-obk commentedon Jun 5, 2019
oh, you mean the solution where each
TypeId
is in fact backed by a (non-deduplicateable and non-duplicatable) static item and theTypeId
is just a pointer to that? And the value of that static could be the type's name (or a zero length string in the release-mode version).anp commentedon Jun 5, 2019
Interesting ideas! If I had my druthers it would be feasible to use this in release mode as well, as I am interested in using the output for logging.
Centril commentedon Jun 6, 2019
@oli-obk Something in that spirit yeah.
gnzlbg commentedon Jun 13, 2019
I imagine this as follows.
We would have a:
that is implemented for all types:
Then we would have a global compiler switch, e.g.,
-C rtti=on/off
, that controls what the trait impls do. When-C rtti=on
,TypeName::type_name
implementations are magically generated to return the&'static str
containing the name of the type are added for each type in the whole program. When-C rtti=on
, only a blanket impl, e.g., returning"rtti-disabled"
, is provided.type_name()
method on Any. #68379eddyb commentedon Apr 9, 2022
(cross-linking)
TypeId
containing a mangled name would allow this more efficiently (in terms of binary size) than viastd::any::type_name
, and is arguably necessary for soundTypeId
(at least one some platforms?): #77125 (comment)eddyb commentedon Apr 9, 2022
Update: finally opened #95845 with a (v0) mangling-based
TypeId
representation (which could eventually be used to allow runtime demangling of type names fromTypeId
).8 remaining items