# Pre-RFC: non-footgun non-static TypeId

**URL:** <https://internals.rust-lang.org/t/pre-rfc-non-footgun-non-static-typeid/17079>\
**Category:** Uncategorized\
**Created:** [July 24, 2022, 8:17pm UTC](https://internals.rust-lang.org/t/pre-rfc-non-footgun-non-static-typeid/17079 "2022-07-24T20:17:08Z")\
**Posts on this page:** 1\
**Showing post:** 3

<div class="post-metadata">

**Author:** ![eddyb](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eddyb/32/8411_2.png) [@eddyb](https://internals.rust-lang.org/u/eddyb)\
**Post date:** [July 24, 2022, 8:52pm UTC](https://internals.rust-lang.org/t/pre-rfc-non-footgun-non-static-typeid/17079/3 "2022-07-24T20:52:50Z")

</div>

Just driving by to say that [I've been exposed to something like this in the wild](https://github.com/sagebind/castaway/pull/6#issuecomment-1151011368) (though they had done it unsoundly abusing monomorphization behavior that we'll hopefully close up to some extent).

It was frankly confusing as framed in their system, but the trick is that a type with no "lifetime positions" (in its monomorphic fully-normalized form that is a tree of type constructor applications) can be known to meet a `: 'static` _without_ having to specify that bound statically (so a bit like `needs_drop`).

In a sense, this can be seen as a version of `T: 'static` that can be used during trait impl specialization, in that it only matches when the bound holds _across all possible choices of lifetimes in `T`_ (which gets back to "`T` has no lifetime positions" almost by definition, since any of them would invalidate `'static`).

* * *

I agree about integrating with `TypeId` (and `Any`, in their case), but I'm not fond on having a separate `all_types_with_this_id_are_static` intrinsic (my suggestion was `TypeId::of_lifetimeless`, which would have its own intrinsic returning `Option`).

Also, the problem with _not_ labeling it specially ("lifetimeless" was my bikeshed) is that it can fail for types that are in fact `: 'static`.

To complete your example:

```rust
assert_eq!(TypeId::of::<&'static str>(), TypeId::of::<&'static str>());
assert!(! TypeId::of::<&'static str>().same_as::<&'static str>());

```

So by that measure, `same_as` is too misleading of a name.

Whereas if we added suffixed methods to `TypeId`/`Any`, this would make sense IMO:

```rust
let any_str = &"foo" as &dyn Any;

// Successes:
assert_eq!(any_str.type_id(), TypeId::of::<&'static str>());
assert_eq!(any_str.downcast_ref::<&'static str>(), Some("foo"));

// Failures:
assert_eq!(TypeId::of_lifetimeless::<&'static str>(), None);
assert_eq!(any_str.downcast_lifetimeless_ref::<&'static str>(), None);

```

Maybe "lifetimeless" is a poor name for the concept, but regardless we should come up with one that's distinguishing enough to not be mistaken as being a helpful shorthand, and thoroughly document it.

---

_[View the full topic](https://internals.rust-lang.org/t/pre-rfc-non-footgun-non-static-typeid/17079)._
