# 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`.