Rollup merge of #152381 - oli-obk:non_static_reflection, r=Mark-Simulacrum

Do not require `'static` for obtaining reflection information.

tracking issue rust-lang/rust#142577

This does not affect the stable `TypeId::of`, as that has its own `'static` bound.

But it will allow obtaining `TypeId`s for non-static types via the reflection API. To obtain such a `TypeId` for any type, just use `Type::of::<(T,)>().kind` to extract the first field of a tuple.

This effectively reintroduces rust-lang/rust#41875, which @rust-lang/lang decided against allowing back in 2018 due to lack of sound use cases. We will thus need to have a T-lang meeting specifically about `TypeId` for non-static types before *stabilizing* any part of reflection (in addition to T-lang meetings about reflection in general). I'm adding an explicit point about this to the tracking issue.

cc @scottmcm @joshtriplett @9SonSteroids @SpriteOvO @izagawd @BD103
This commit is contained in:
Jonathan Brouwer 2026-02-14 22:11:53 +01:00 committed by GitHub
commit 16da3ab2ea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 11 additions and 5 deletions

View file

@ -2886,7 +2886,7 @@ pub const fn type_name<T: ?Sized>() -> &'static str;
#[rustc_nounwind]
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_intrinsic]
pub const fn type_id<T: ?Sized + 'static>() -> crate::any::TypeId;
pub const fn type_id<T: ?Sized>() -> crate::any::TypeId;
/// Tests (at compile-time) if two [`crate::any::TypeId`] instances identify the
/// same type. This is necessary because at const-eval time the actual discriminating

View file

@ -2,7 +2,7 @@
//! runtime or const-eval processable way.
use crate::any::TypeId;
use crate::intrinsics::type_of;
use crate::intrinsics::{type_id, type_of};
/// Compile-time type information.
#[derive(Debug)]
@ -28,11 +28,17 @@ impl TypeId {
impl Type {
/// Returns the type information of the generic type parameter.
///
/// Note: Unlike `TypeId`s obtained via `TypeId::of`, the `Type`
/// struct and its fields contain `TypeId`s that are not necessarily
/// derived from types that outlive `'static`. This means that using
/// the `TypeId`s (transitively) obtained from this function will
/// be able to break invariants that other `TypeId` consuming crates
/// may have assumed to hold.
#[unstable(feature = "type_info", issue = "146922")]
#[rustc_const_unstable(feature = "type_info", issue = "146922")]
// FIXME(reflection): don't require the 'static bound
pub const fn of<T: ?Sized + 'static>() -> Self {
const { TypeId::of::<T>().info() }
pub const fn of<T: ?Sized>() -> Self {
const { type_id::<T>().info() }
}
}