Repository: rust-lang/rust
File: compiler/rustc_borrowck/src/type_check/mod.rs (Rust)

Code before:
                    }
                    _ => None,
                },
                Const::Unevaluated(uv, _) => Some(uv),
                _ => None,
            };

            if let Some(uv) = maybe_uneval {
                if let Some(promoted) = uv.promoted {
                    let promoted_body = &self.promoted[promoted];
                    self.check_promoted(promoted_body, location);
                    let promoted_ty = promoted_body.return_ty();
                    if let Err(terr) =
                        self.eq_types(ty, promoted_ty, locations, ConstraintCategory::Boring)
                    {
                        span_mirbug!(
                            self,
                            promoted,
                            "bad promoted type ({:?}: {:?}): {:?}",
                            ty,
                            promoted_ty,
                            terr
                        );
                    };
                } else {
                    // FIXME: For inherent associated type constants (IACs), we skip
                    // user type ascription because the args in MIR use [impl_args...]
                    // format while IAC generics expect [Self, own_args...] format.
                    // Properly fixing this requires changes to MIR generation or a
                    // more sophisticated args transformation.
                    let is_inherent_type_const = tcx.is_type_const(uv.def)
                        && tcx.opt_associated_item(uv.def).is_some_and(|assoc| {
                            matches!(assoc.container, ty::AssocContainer::InherentImpl)
                        });
                    if !is_inherent_type_const {
                        self.ascribe_user_type(
                            constant.const_.ty(),
                            ty::UserType::new(ty::UserTypeKind::TypeOf(
                                uv.def,
                                UserArgs { args: uv.args, user_self_ty: None },
                            )),
                            locations.span(self.body),
                        );
                    }
                }
            } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
                let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
                let normalized_ty = self.normalize(unnormalized_ty, locations);
                let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();

                if let Err(terr) =

Review comment (suggestion):
I think you'll need to update the implementation of `AscribeUserType` typeops to map back from `[SelfTy, Gats1..N]` to `[ImplParams1..N, Gats1..N]` when instantiating the result of calling `type_of` the `DefId`. We do this already in the trait solver so this is normal:tm: and expected:tm: 

You can find the logic for implementing `AscribeUserType` in `type_op_ascribe_user_type_with_span`. And some of the existing places which we do this "map from SelfTy to ImplArgs" thing in the old solver's `compute_inherent_assoc_term_args` or the new solver's `normalize_inherent_associated_term`

tl;dr:
1. create a list of infer vars for arguments to the inherent impl
2. call `type_of` on the *impl* to get its self ty then instantiate it with the infer vars 
3. equate this type with the user written self ty (from `<SelfTy>::INHERENT`). this results inference constraints turning your list of infer vars into an actual list of inferrred types/consts



Code after:
                    }
                    _ => None,
                },
                Const::Unevaluated(uv, _) => Some(uv),
                _ => None,
            };

            if let Some(uv) = maybe_uneval {
                if let Some(promoted) = uv.promoted {
                    let promoted_body = &self.promoted[promoted];
                    self.check_promoted(promoted_body, location);
                    let promoted_ty = promoted_body.return_ty();
                    if let Err(terr) =
                        self.eq_types(ty, promoted_ty, locations, ConstraintCategory::Boring)
                    {
                        span_mirbug!(
                            self,
                            promoted,
                            "bad promoted type ({:?}: {:?}): {:?}",
                            ty,
                            promoted_ty,
                            terr
                        );
                    };
                } else {
                    self.ascribe_user_type(
                        constant.const_.ty(),
                        ty::UserType::new(ty::UserTypeKind::TypeOf(
                            uv.def,
                            UserArgs { args: uv.args, user_self_ty: None },
                        )),
                        locations.span(self.body),
                    );
                }
            } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
                let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
                let normalized_ty = self.normalize(unnormalized_ty, locations);
                let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();

                if let Err(terr) =
                    self.eq_types(literal_ty, normalized_ty, locations, ConstraintCategory::Boring)
                {
                    span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
                }
            } else if let Const::Ty(_, ct) = constant.const_
                && let ty::ConstKind::Param(p) = ct.kind()
            {
                let body_def_id = self.universal_regions.defining_ty.def_id();
                let const_param = tcx.generics_of(body_def_id).const_param(p, tcx);
                self.ascribe_user_type(
                    constant.const_.ty(),