# Experiment for missing normalizations
For all these experiments, we use https://github.com/rust-lang/rust/pull/103985 as a base to then check where there are missing normalization calls. Don't forget to replace:
```rust
if let Some(identity_def_id) = tcx.lang_items().identity_type() {
```
with:
```rust
if let Some(identity_def_id) = tcx.lang_items().identity_type() && std::env::var("WHATEVER").is_ok() {
```
So then you can try it out with "WHATEVER=1" in your environment to enable it.
### Associated type of projection as const generic
The following code should work:
```rust
pub trait Identity {
type Identity: ?Sized;
}
impl<T: ?Sized> Identity for T {
type Identity = Self;
}
pub fn foo<const X: <i32 as Identity>::Identity>() {
// ^ error here
assert!(X == 12);
}
fn main() {
foo::<12>();
}
```
To make it work, here are the changes to be done:
In `rustc_middle::ty::consts::from_opt_const_arg_anon_const`:
This [`ty`](https://github.com/rust-lang/rust/blob/14ca83a04b00433a8caf3b805d5ea08cb2691e1b/compiler/rustc_middle/src/ty/consts.rs#L74) should be normalized:
```rust
let param_env = tcx.param_env(def.did);
let ty = tcx.normalize_erasing_regions(param_env, ty);
```
In `rustc_hir_analysis::check::wfcheck::check_param_wf`:
This [`Ty`](https://github.com/rust-lang/rust/blob/14ca83a04b00433a8caf3b805d5ea08cb2691e1b/compiler/rustc_hir_analysis/src/check/wfcheck.rs#L863) should be normalized using:
```rust
// `owner_id` must be added as an argument to this function
enter_wf_checking_ctxt(tcx, param.span, owner_id, |wfcx| {
let ty = tcx.type_of(param.def_id);
let ty = wfcx.normalize(hir_ty.span, None, ty);
// ...
});
```
However, these changes create a lot of cycle errors (as can be seen in [#104443](https://github.com/rust-lang/rust/pull/104443)).
### Associated type of projection as union field's type
The following code should work:
```rust
trait Identity {
type Identity;
}
trait NotImplemented {}
impl<T: NotImplemented> Identity for T {
type Identity = Self;
}
type Foo = u8;
union Bar {
a: <Foo as Identity>::Identity, // Error here
b: u8,
}
```
Basically, it was missing a normalization before checking the if the field's type was compatible with a union in `compiler/rustc_hir_analysis/src/check/check.rs`.
It was fixed in https://github.com/rust-lang/rust/pull/106938.
### Impl block on a projection
The following code should work:
```rust
pub trait Identity {
type Identity: ?Sized;
}
impl<T: ?Sized> Identity for T {
type Identity = Self;
}
pub struct S;
impl <S as Identity>::Identity { // error here
pub fn foo(&self) {}
}
```
It was missing a normalization before the check for the `self` type of the impl block. It was added in https://github.com/rust-lang/rust/pull/107263.
Side-note: the privacy check was wrong for the projection so it needed a fix as well.
However, it cannot work because:
```rust
pub trait Identity {
type Identity: ?Sized;
}
impl<T: ?Sized> Identity for T {
type Identity = Self;
}
pub struct I8<const F: i8>;
impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
pub fn foo(&self) {}
}
```
Gives the following error:
```
error[E0391]: cycle detected when finding all inherent impls defined in crate
|
= note: ...which requires normalizing `<I8<{i8::MIN}> as Identity>::Identity`...
note: ...which requires evaluating type-level constant...
--> bar.rs:13:10
|
13 | impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
| ^^^^^^^^^
note: ...which requires const-evaluating + checking `<impl at bar.rs:13:1: 13:43>::{constant#0}`...
--> bar.rs:13:10
|
13 | impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
| ^^^^^^^^^
note: ...which requires const-evaluating + checking `<impl at bar.rs:13:1: 13:43>::{constant#0}`...
--> bar.rs:13:10
|
13 | impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
| ^^^^^^^^^
note: ...which requires caching MIR for CTFE of the const argument `<impl at bar.rs:13:1: 13:43>::{constant#0}`...
--> bar.rs:13:10
|
13 | impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
| ^^^^^^^^^
note: ...which requires elaborating drops for `<impl at bar.rs:13:1: 13:43>::{constant#0}`...
--> bar.rs:13:10
|
13 | impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
| ^^^^^^^^^
note: ...which requires borrow-checking the const argument`<impl at bar.rs:13:1: 13:43>::{constant#0}`...
--> bar.rs:13:10
|
13 | impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
| ^^^^^^^^^
note: ...which requires processing MIR for the const argument `<impl at bar.rs:13:1: 13:43>::{constant#0}`...
--> bar.rs:13:10
|
13 | impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
| ^^^^^^^^^
note: ...which requires const checking the const argument `<impl at bar.rs:13:1: 13:43>::{constant#0}`...
--> bar.rs:13:10
|
13 | impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
| ^^^^^^^^^
note: ...which requires preparing the const argument `<impl at bar.rs:13:1: 13:43>::{constant#0}` for borrow checking...
--> bar.rs:13:10
|
13 | impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
| ^^^^^^^^^
note: ...which requires unsafety-checking the const argument `<impl at bar.rs:13:1: 13:43>::{constant#0}`...
--> bar.rs:13:10
|
13 | impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
| ^^^^^^^^^
note: ...which requires building MIR for `<impl at bar.rs:13:1: 13:43>::{constant#0}`...
--> bar.rs:13:10
|
13 | impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
| ^^^^^^^^^
note: ...which requires building THIR for `<impl at bar.rs:13:1: 13:43>::{constant#0}`...
--> bar.rs:13:10
|
13 | impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
| ^^^^^^^^^
note: ...which requires type-checking the const argument `<impl at bar.rs:13:1: 13:43>::{constant#0}`...
--> bar.rs:13:10
|
13 | impl <I8<{i8::MIN}> as Identity>::Identity { //~ ERROR
| ^^^^^^^^^
= note: ...which requires collecting all inherent impls for `IntSimplifiedType(I8)`...
= note: ...which requires collecting all impls for a type in a crate...
= note: ...which again requires finding all inherent impls defined in crate, completing the cycle
= note: cycle used when running analysis passes on this crate
error: aborting due to previous error
For more information about this error, try `rustc --explain E0391`.
```
Because of the normalization in `compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs`.