TypeId exposes placeholders type generics with `-Znext-solver`
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
So, this isn't necessarily a bug, it's just interesting behavior and I'm not sure if it's intended:
#![feature(const_type_id, generic_const_exprs)]
const fn type_id<T: 'static>() -> u128 {
unsafe { std::mem::transmute::<_, u128>(std::any::TypeId::of::<T>()) }
}
const fn c<X: 'static>() -> usize {
// A: the evaluated program panicked at '63102938254854923095314763309601158984'
const_panic::concat_panic!(type_id::<X>());
}
pub fn u<X: 'static>() {
let _: [(); c::<X>()];
println!("{}", type_id::<X>()); // B
}
This happens without even calling u. The values printed at A and B (by commenting out the call to c and adding a call to u with any arbitrary type) are different. I'm posting this issue because I'm not sure if there's ICE potential here, for values being different in a const vs runtime context.
I stumbled across this while looking for a way to make a "commutative type" i.e. where Com<A, B> and Com<B, A> are the same type. It only works in -Znext-solver and I believe that's due to -Znext-solver eagerly evaluating stuff using these placeholder types?
#![feature(const_type_id, core_intrinsics, generic_const_exprs)]
#![allow(warnings)]
struct Foo; struct Bar;
struct Bool<const B: bool>;
trait TrueOrFalse {
type Ite<Then, Else>;
}
impl TrueOrFalse for Bool<true> {
type Ite<Then, Else> = Then;
}
impl TrueOrFalse for Bool<false> {
type Ite<Then, Else> = Else;
}
type Ite<const B: bool, T, E> = <Bool<B> as TrueOrFalse>::Ite<T, E>;
trait Map<T: 'static, U: 'static> where {
type Output;
}
impl<T: 'static, U: 'static> Map<T, U> for (T, U) {
type Output = Ite<{
std::intrinsics::type_id::<T>() > std::intrinsics::type_id::<U>()
}, (U, T), (T, U)>;
}
pub fn u<X: 'static, Y: 'static>() {
let _x: <(X, Y) as Map<X, Y>>::Output = loop {};
let mut _y: <(Y, X) as Map<Y, X>>::Output = loop {};
_y = _x;
}
pub fn f() {
u::<Foo, Bar>();
}
If this does happen to be fixed in a way which breaks the code above it would be nice to have a (perma-unstable) way to order types.
Meta
rustc 1.79.0-nightly (aed2187d5 2024-04-27)
binary: rustc
commit-hash: aed2187d53b8789e3a37f50ae36f894a2a679077
commit-date: 2024-04-27
host: x86_64-pc-windows-msvc
release: 1.79.0-nightly
LLVM version: 18.1.4
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the two provided reproductions with the noted nightly compiler and -Znext-solver, comparing the TypeId values produced during const evaluation and at runtime. Investigate whether placeholder types are being eagerly evaluated and whether the discrepancy can cause an ICE. Done means the behavior is resolved or its intended semantics are clearly established, with the commutative-type example addressed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100