mirror of https://github.com/rust-lang/rust.git
58 lines
2.1 KiB
Rust
58 lines
2.1 KiB
Rust
//! This test demonstrates how `LayoutError::NormalizationFailure` can happen and why
|
|
//! it is necessary.
|
|
//!
|
|
//! This code does not cause an immediate normalization error in typeck, because we
|
|
//! don't reveal the hidden type returned by `opaque<T>` in the analysis typing mode.
|
|
//! Instead, `<{opaque} as Project2>::Assoc2` is a *rigid projection*, because we know
|
|
//! that `{opaque}: Project2` holds, due to the opaque type's `impl Project2` bound,
|
|
//! but cannot normalize `<{opaque} as Project2>::Assoc2` any further.
|
|
//!
|
|
//! However, in the post-analysis typing mode, which is used for the layout computation,
|
|
//! the opaque's hidden type is revealed to be `PhantomData<T>`, and now we fail to
|
|
//! normalize `<PhantomData<T> as Project2>::Assoc2` if there is a `T: Project1` bound
|
|
//! in the param env! This happens, because `PhantomData<T>: Project2` only holds if
|
|
//! `<T as Project1>::Assoc1 == ()` holds. This would usually be satisfied by the
|
|
//! blanket `impl<T> Project1 for T`, but due to the `T: Project1` bound we do not
|
|
//! normalize `<T as Project1>::Assoc1` via the impl and treat it as rigid instead.
|
|
//! Therefore, `PhantomData<T>: Project2` does NOT hold and normalizing
|
|
//! `<PhantomData<T> as Project2>::Assoc2` fails.
|
|
//!
|
|
//! Note that this layout error can only happen when computing the layout in a generic
|
|
//! context, which is not required for codegen, but may happen for lints, MIR optimizations,
|
|
//! and the transmute check.
|
|
|
|
use std::marker::PhantomData;
|
|
|
|
trait Project1 {
|
|
type Assoc1;
|
|
}
|
|
|
|
impl<T> Project1 for T {
|
|
type Assoc1 = ();
|
|
}
|
|
|
|
trait Project2 {
|
|
type Assoc2;
|
|
fn get(self) -> Self::Assoc2;
|
|
}
|
|
|
|
impl<T: Project1<Assoc1 = ()>> Project2 for PhantomData<T> {
|
|
type Assoc2 = ();
|
|
fn get(self) -> Self::Assoc2 {}
|
|
}
|
|
|
|
fn opaque<T>() -> impl Project2 {
|
|
PhantomData::<T>
|
|
}
|
|
|
|
fn check<T: Project1>() {
|
|
unsafe {
|
|
std::mem::transmute::<_, ()>(opaque::<T>().get());
|
|
//~^ ERROR: cannot transmute
|
|
//~| NOTE: (unable to determine layout for `<impl Project2 as Project2>::Assoc2` because `<impl Project2 as Project2>::Assoc2` cannot be normalized)
|
|
//~| NOTE: (0 bits)
|
|
}
|
|
}
|
|
|
|
fn main() {}
|