Policy idea: Change TypeId's implementation details every other release


TypeId should have its implementation details, e.g. its size, changed every other release.

This means changing it into an u128, an &'static u64, etc.

Additionally, its Debug impl should also change every other release.


Why? What’s the motivation? TypeId is already an opaque struct.

Also, why every other release? Why not every release, every epoch, nightly, etc?


Because some ppl believe they should be allowed to transmute the thing.

Those ppl are against my changes that would make TypeId collision-free.


The question here is why they want to transmute Typeid. It’s likely not a question of “allowed” but “I need this to Solve a Problem”.

If we can identify the problem at the root, then we can deal with the transmutation demand and not have to change Typeid every X releases/whatever.

That seems like the best road forward to me, any disagreement?


I disagree because AnyMap insists on transmuting a TypeId for seemingly no good reason.

(I’ve already worked out ways to optimize a slow TypeId/Any, but those optimizations aren’t required for fixing the collisions. So I believe it’s better to keep this separate.)

It’s better to constantly evolve TypeId’s representation so as to reduce conflicts, rather than stick with the current one just because everyone’s transmuting it.


Okay what reasons did they give then? Is it a reason you disagreed with, so you’re not repeating it?

You’re proposing a potentially error-prone policy change, and I’m trying to understand the root motivations at play for all the parties - so we(being readers, etc at this forum) can have clarity and insight into this policy proposal of yours.


They claim it provides marginal performance gains and adds unsafe code:



A desire for a change to TypeId that breaks AnyMap doesn’t automatically imply that TypeId should change continually in order to keep breaking it. This just seems transparently hostile. If you don’t want AnyMap to transmute, you can certainly implement a version that doesn’t. It’s not clear why anybody should be intentionally and repeatedly breaking other people’s crates, just because you don’t like how they work.


Hmm, looks like it doesn’t actually transmute, but just does a no-op hashing.

It should be safe to freely change TypeId’s internals, it shouldn’t break AnyMap.


Then there’s no need for this policy?


No, we still should have the policy.

Or at least some way to forbid transmutes of some types, such as TypeId.


I still don’t see what the necessity for this policy is.

If someone is transmuting an opaque struct from the library like TypeId, then the consequences when internal details change are on them. There is no guarantees made that the internal details won’t change, if I remember correctly. I can be corrected if I’m wrong on this!

Transmutes are noted many times in the documentation as being very very unsafe.


Yes, so until we state otherwise, a transmute of struct Foo(Bar); to/from Bar should be considered undefined behavior. This may change in the future but that’s the current idea. If you want to freely transmute you can say: #[repr(transparent)] struct Foo(Bar);

I believe @Soni is referring to this bit: https://github.com/chris-morgan/anymap/blob/0850f5ec36b14904ae452ffdfa0a2ae0ba05c854/src/raw.rs#L24-L30

This does not seem like it could be unsound but it’s also error prone / fishy should be ever change TypeId to something other than u64.

I don’t think instituting the policy proposed in this thread is warranted tho.


Well, I’d like to change TypeId/Any to solve the collisions, but there’s a lot of momentum against it, mainly from ppl transmuting TypeIds around. at least going by my experiences on IRC…

This policy intentionally breaks their code so they give up on it, so they won’t push back against my changes so hard.


Okay, so you want to institute a policy in order to break other people’s code (which they’re pretty aware they probably shouldn’t be doing) so it would be easier to make changes you want to make to TypeId?

Policies are not your tool to make things easier for you or punish other people for stating objections to something you want to do.

How about we address the clear hole exposed by this bad usage instead? Then people will stop relying on transmutes of the TypeId struct.

So in this case, TypeId needs to be hashable. That can be added to the std library, can it not?


Do you have links to any of these chatlogs?

In all the threads I’ve seen, the resistance to “fixing” TypeId/Any comes from the simple fact that nobody actually knows how to do it (without breaking dynamic linking).


If they’re objecting to your changes because it would break their crates, why do you think they would not object to this proposal which just declares their code broken by fiat?


It’s called “make it slow”. More specifically, a comparison of a long array/slice of strings, where each element has some information about increasingly narrower scopes.

One possible TypeId could look like this:

[rustc_id, cargo_id, crate_id, crate_version, module_id, ..., fn_id, struct_id, generic_id, ...]

rustc_id is shared across all crates/etc so uses very little space, cargo_id is also generally shared across all crates so also uses very little space, crate_id is per crate, so uses a little more space, but still very little, and so on.

If you were to concatenate the whole thing it would quickly get huge, but because we can reuse many of these across most types, it ends up getting rather small.


I do believe they’d object to this policy, but it seems easier to pass a trivial policy that doesn’t affect current (guaranteed) semantics than convince them of my changes.


TypeId is Hash :stuck_out_tongue:

This is emphatically not how we go about making such changes. If changes need to be made (which I’m not necessarily saying…), we’d prefer to give people warnings if possible, under a period, and then roll out changes gracefully such that we don’t hit people with brick walls.