Repository: rust-lang/rust
File: compiler/rustc_trait_selection/src/traits/project.rs (Rust)

Code before:
    let tcx = selcx.tcx();

    let impl_def_id = tcx.parent(alias_term.def_id);
    let impl_args = selcx.infcx.fresh_args_for_item(cause.span, impl_def_id);

    let mut impl_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args);
    if !selcx.infcx.next_trait_solver() {
        impl_ty = normalize_with_depth_to(
            selcx,
            param_env,
            cause.clone(),
            depth + 1,
            impl_ty,
            obligations,
        );
    }

    // Infer the generic parameters of the impl by unifying the
    // impl type with the self type of the projection.
    // For inherent associated consts, the args may not have a Self type at position 0.
    // In that case, we use the impl_ty directly instead of calling self_ty().
    let mut self_ty = if alias_term.args.is_empty() || alias_term.args[0].as_type().is_none() {
        impl_ty
    } else {
        alias_term.self_ty()
    };
    if !selcx.infcx.next_trait_solver() {
        self_ty = normalize_with_depth_to(
            selcx,
            param_env,
            cause.clone(),
            depth + 1,
            self_ty,
            obligations,
        );
    }

    match selcx.infcx.at(&cause, param_env).eq(DefineOpaqueTypes::Yes, impl_ty, self_ty) {
        Ok(mut ok) => obligations.append(&mut ok.obligations),
        Err(_) => {
            tcx.dcx().span_bug(
                cause.span,
                format!("{self_ty:?} was equal to {impl_ty:?} during selection but now it is not"),
            );
        }
    }

    alias_term.rebase_inherent_args_onto_impl(impl_args, tcx)
}

enum Projected<'tcx> {

Review comment (bug):
This is just trying to patch a symptom.

Every inherent assoc ty / const should have a self ty, that's the format, otherwise that's a bug (meaning: we should not attempt to work around it downstream). Worth mentioning, if mGCA+IAT is enabled we seem to construct the `AliasTerm` correctly, so this issue only happens if the necessary features aren't enabled (which is a relief).

So I think the proper solution would be to tweak HIR ty lowering (which I believe to be the culprit) to construct a proper `AliasTerm` "if the features aren't enabled" (even if that means setting self ty to `{type error}` or sth. of that nature). Disclaimer: I've just written down my thoughts without any deeper investigation, so some statements might not be fully correct.

Side note: Your patch likely only addresses the ICE under the current trait solver but not under the next one (`-Znext-solver`) since you're only tackling one tail end, not the root cause, as I've mentioned.

Code after:
    let tcx = selcx.tcx();

    let impl_def_id = tcx.parent(alias_term.def_id);
    let impl_args = selcx.infcx.fresh_args_for_item(cause.span, impl_def_id);

    let mut impl_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args);
    if !selcx.infcx.next_trait_solver() {
        impl_ty = normalize_with_depth_to(
            selcx,
            param_env,
            cause.clone(),
            depth + 1,
            impl_ty,
            obligations,
        );
    }

    // Infer the generic parameters of the impl by unifying the
    // impl type with the self type of the projection.
    let mut self_ty = alias_term.self_ty();
    if !selcx.infcx.next_trait_solver() {
        self_ty = normalize_with_depth_to(
            selcx,
            param_env,
            cause.clone(),
            depth + 1,
            self_ty,
            obligations,
        );
    }

    match selcx.infcx.at(&cause, param_env).eq(DefineOpaqueTypes::Yes, impl_ty, self_ty) {
        Ok(mut ok) => obligations.append(&mut ok.obligations),
        Err(_) => {
            tcx.dcx().span_bug(
                cause.span,
                format!("{self_ty:?} was equal to {impl_ty:?} during selection but now it is not"),
            );
        }
    }

    alias_term.rebase_inherent_args_onto_impl(impl_args, tcx)
}

enum Projected<'tcx> {
    Progress(Progress<'tcx>),
    NoProgress(ty::Term<'tcx>),
}

struct Progress<'tcx> {
    term: ty::Term<'tcx>,