From 29d3397ff83d27a1198512f6bd42a233f3e41d4d Mon Sep 17 00:00:00 2001 From: lapla Date: Thu, 23 Apr 2026 03:41:37 +0900 Subject: [PATCH 1/4] Register `ConstArgHasType` obligation when normalizing trait projection consts --- .../src/solve/normalizes_to/mod.rs | 14 +++++-- .../src/traits/project.rs | 13 ++++++- ...e-const-value-type-mismatch.current.stderr | 32 +++++++++++++++ ...type-const-value-type-mismatch.next.stderr | 39 +++++++++++++++++++ .../mgca/type-const-value-type-mismatch.rs | 29 ++++++++++++++ 5 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr create mode 100644 tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr create mode 100644 tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 1d74f1efe9136..3da6be7a7771e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -393,10 +393,16 @@ where kind => panic!("expected projection, found {kind:?}"), }; - ecx.instantiate_normalizes_to_term( - goal, - term.instantiate(cx, target_args).skip_norm_wip(), - ); + let instantiated_term: I::Term = term.instantiate(cx, target_args); + if let Some(ct) = instantiated_term.as_const() { + let expected_ty = cx.type_of(target_item_def_id).instantiate(cx, target_args); + ecx.add_goal( + GoalSource::Misc, + goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), + ); + } + + ecx.instantiate_normalizes_to_term(goal, instantiated_term.skip_norm_wip()); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 5423e394119c4..8fc8467adec28 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2046,7 +2046,18 @@ fn confirm_impl_candidate<'cx, 'tcx>( Progress { term: err, obligations: nested } } else { assoc_term_own_obligations(selcx, obligation, &mut nested); - Progress { term: term.instantiate(tcx, args).skip_norm_wip(), obligations: nested } + let instantiated_term: Term<'tcx> = term.instantiate(tcx, args); + if let Some(ct) = instantiated_term.as_const() { + let expected_ty = tcx.type_of(assoc_term.item.def_id).instantiate(tcx, args); + nested.push(Obligation::with_depth( + tcx, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + ty::ClauseKind::ConstArgHasType(ct, expected_ty), + )); + } + Progress { term: instantiated_term.skip_norm_wip(), obligations: nested } }; Ok(Projected::Progress(progress)) } diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr new file mode 100644 index 0000000000000..7ce0513c91d13 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr @@ -0,0 +1,32 @@ +error[E0053]: method `arr` has an incompatible type for trait + --> $DIR/type-const-value-type-mismatch.rs:22:5 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a size of 0, found one with a size of const { Self::LEN } + | +note: type in trait + --> $DIR/type-const-value-type-mismatch.rs:15:5 + | +LL | fn arr() -> [u8; Self::LEN]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected signature `fn() -> [u8; 0]` + found signature `fn() -> [u8; const { Self::LEN }]` + +error: the constant `0` is not of type `usize` + --> $DIR/type-const-value-type-mismatch.rs:19:5 + | +LL | type const LEN: usize = 0u8; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `u8` + +error[E0308]: mismatched types + --> $DIR/type-const-value-type-mismatch.rs:22:17 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | --- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Self::LEN }]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0053, E0308. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr new file mode 100644 index 0000000000000..e6c7857bdb3d6 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr @@ -0,0 +1,39 @@ +error[E0271]: type mismatch resolving `::LEN normalizes-to 0` + --> $DIR/type-const-value-type-mismatch.rs:22:5 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | +note: the requirement `::LEN normalizes-to 0` appears on the `impl`'s associated function `arr` but not on the corresponding trait's associated function + --> $DIR/type-const-value-type-mismatch.rs:15:8 + | +LL | pub trait Array { + | ----- in this trait +LL | type const LEN: usize; +LL | fn arr() -> [u8; Self::LEN]; + | ^^^ this trait's associated function doesn't have the requirement `::LEN normalizes-to 0` + +error: the constant `0` is not of type `usize` + --> $DIR/type-const-value-type-mismatch.rs:19:5 + | +LL | type const LEN: usize = 0u8; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `u8` + +error[E0284]: type annotations needed: cannot normalize `::arr::{constant#0}` + --> $DIR/type-const-value-type-mismatch.rs:22:17 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `::arr::{constant#0}` + +error[E0308]: mismatched types + --> $DIR/type-const-value-type-mismatch.rs:22:17 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | --- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Self::LEN }]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0271, E0284, E0308. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs new file mode 100644 index 0000000000000..273e7e340fef1 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs @@ -0,0 +1,29 @@ +// Regression test for https://github.com/rust-lang/rust/issues/152962 + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ compile-flags: -Zvalidate-mir + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +pub struct A; + +pub trait Array { + type const LEN: usize; + fn arr() -> [u8; Self::LEN]; +} + +impl Array for A { + type const LEN: usize = 0u8; + //~^ ERROR the constant `0` is not of type `usize` + + fn arr() -> [u8; const { Self::LEN }] {} + //~^ ERROR mismatched types [E0308] + //[current]~| ERROR method `arr` has an incompatible type for trait [E0053] + //[next]~| ERROR type annotations needed + //[next]~| ERROR type mismatch resolving `::LEN normalizes-to 0` [E0271] +} + +fn main() {} From 64e57c2886b87cd9db339045c5f64d3214c15435 Mon Sep 17 00:00:00 2001 From: lapla Date: Thu, 23 Apr 2026 03:41:53 +0900 Subject: [PATCH 2/4] Register `ConstArgHasType` obligation when normalizing inherent projection consts --- .../src/solve/normalizes_to/inherent.rs | 10 ++++++++ .../src/traits/project.rs | 11 +++++++++ ...nherent-value-type-mismatch.current.stderr | 17 +++++++++++++ ...t-inherent-value-type-mismatch.next.stderr | 24 +++++++++++++++++++ ...type-const-inherent-value-type-mismatch.rs | 22 +++++++++++++++++ 5 files changed, 84 insertions(+) create mode 100644 tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr create mode 100644 tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr create mode 100644 tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 4d62407fe2995..143d62d19ba30 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -5,6 +5,7 @@ //! 2. equate the self type, and //! 3. instantiate and register where clauses. +use rustc_type_ir::inherent::*; use rustc_type_ir::{self as ty, Interner, Unnormalized}; use crate::delegate::SolverDelegate; @@ -60,6 +61,15 @@ where .skip_norm_wip() .into() }; + + if let Some(ct) = normalized.as_const() { + let expected_ty = cx.type_of(inherent.def_id).instantiate(cx, inherent_args); + self.add_goal( + GoalSource::Misc, + goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), + ); + } + self.instantiate_normalizes_to_term(goal, normalized); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 8fc8467adec28..b6da72958c9e5 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -551,6 +551,17 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( tcx.const_of_item(alias_term.def_id()).instantiate(tcx, args).skip_norm_wip().into() }; + if let Some(ct) = term.as_const() { + let expected_ty = tcx.type_of(alias_term.def_id).instantiate(tcx, args); + obligations.push(Obligation::with_depth( + tcx, + cause.clone(), + depth + 1, + param_env, + ty::ClauseKind::ConstArgHasType(ct, expected_ty), + )); + } + let mut term = selcx.infcx.resolve_vars_if_possible(term); if term.has_aliases() { term = diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr new file mode 100644 index 0000000000000..bf34bcaf9fc9c --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr @@ -0,0 +1,17 @@ +error: the constant `"this isn't a usize"` is not of type `usize` + --> $DIR/type-const-inherent-value-type-mismatch.rs:14:5 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error[E0308]: mismatched types + --> $DIR/type-const-inherent-value-type-mismatch.rs:18:11 + | +LL | fn f() -> [u8; const { Struct::N }] {} + | - ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Struct::N }]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr new file mode 100644 index 0000000000000..6af3d2118ee1c --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr @@ -0,0 +1,24 @@ +error[E0284]: type annotations needed: cannot normalize `f::{constant#0}` + --> $DIR/type-const-inherent-value-type-mismatch.rs:18:11 + | +LL | fn f() -> [u8; const { Struct::N }] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `f::{constant#0}` + +error: the constant `"this isn't a usize"` is not of type `usize` + --> $DIR/type-const-inherent-value-type-mismatch.rs:14:5 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error[E0308]: mismatched types + --> $DIR/type-const-inherent-value-type-mismatch.rs:18:11 + | +LL | fn f() -> [u8; const { Struct::N }] {} + | - ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Struct::N }]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0284, E0308. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs new file mode 100644 index 0000000000000..1f00b4410c4d7 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs @@ -0,0 +1,22 @@ +// Regression test for https://github.com/rust-lang/rust/issues/152962 + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ compile-flags: -Zvalidate-mir + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +struct Struct; + +impl Struct { + type const N: usize = "this isn't a usize"; + //~^ ERROR the constant `"this isn't a usize"` is not of type `usize` +} + +fn f() -> [u8; const { Struct::N }] {} +//~^ ERROR mismatched types [E0308] +//[next]~| ERROR type annotations needed + +fn main() {} From d9983202df76121c202eb80b37b4d2684269eee3 Mon Sep 17 00:00:00 2001 From: lapla Date: Thu, 23 Apr 2026 03:42:03 +0900 Subject: [PATCH 3/4] Add test that free type const value type mismatch does not ICE --- .../mgca/type-const-free-value-type-mismatch.rs | 13 +++++++++++++ .../type-const-free-value-type-mismatch.stderr | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs create mode 100644 tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.stderr diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs new file mode 100644 index 0000000000000..5e9147b9a7b91 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs @@ -0,0 +1,13 @@ +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +//@ compile-flags: -Zvalidate-mir +//@ normalize-stderr: "\d+-byte" -> "$$BYTE-byte" + +type const N: usize = "this isn't a usize"; +//~^ ERROR the constant `"this isn't a usize"` is not of type `usize` + +fn f() -> [u8; const { N }] {} +//~^ ERROR transmuting from + +fn main() {} diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.stderr b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.stderr new file mode 100644 index 0000000000000..20ffb7b335a55 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.stderr @@ -0,0 +1,15 @@ +error: the constant `"this isn't a usize"` is not of type `usize` + --> $DIR/type-const-free-value-type-mismatch.rs:7:1 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error[E0080]: transmuting from $BYTE-byte type to $BYTE-byte type: `&str` -> `usize` + --> $DIR/type-const-free-value-type-mismatch.rs:10:24 + | +LL | fn f() -> [u8; const { N }] {} + | ^ evaluation of `f::{constant#0}` failed here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. From 4e17133ac720e91f9ac8c44f1dda6afac60cfb62 Mon Sep 17 00:00:00 2001 From: lapla Date: Thu, 23 Apr 2026 03:42:14 +0900 Subject: [PATCH 4/4] Extract shared helper for registering `ConstArgHasType` during const projection normalization --- .../src/solve/normalizes_to/inherent.rs | 11 +-- .../src/solve/normalizes_to/mod.rs | 36 +++++++--- .../src/traits/project.rs | 69 +++++++++++++------ 3 files changed, 74 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 143d62d19ba30..98da8e0091358 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -5,7 +5,6 @@ //! 2. equate the self type, and //! 3. instantiate and register where clauses. -use rustc_type_ir::inherent::*; use rustc_type_ir::{self as ty, Interner, Unnormalized}; use crate::delegate::SolverDelegate; @@ -62,15 +61,7 @@ where .into() }; - if let Some(ct) = normalized.as_const() { - let expected_ty = cx.type_of(inherent.def_id).instantiate(cx, inherent_args); - self.add_goal( - GoalSource::Misc, - goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), - ); - } - - self.instantiate_normalizes_to_term(goal, normalized); + self.instantiate_normalizes_to_term_with_type_check(goal, normalized); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 3da6be7a7771e..f9b91dc029994 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -110,6 +110,28 @@ where .expect("expected goal term to be fully unconstrained"); } + /// Like `instantiate_normalizes_to_term`, but also registers a + /// `ConstArgHasType` goal when the term is a const. This ensures that + /// the const value's type matches the type of the alias it was + /// normalized from, preventing ICEs from type mismatches. + pub fn instantiate_normalizes_to_term_with_type_check( + &mut self, + goal: Goal>, + term: I::Term, + ) { + if let Some(ct) = term.as_const() { + let cx = self.cx(); + let alias = goal.predicate.alias; + let expected_ty = + cx.type_of(alias.def_id()).instantiate(cx, alias.args).skip_norm_wip(); + self.add_goal( + GoalSource::Misc, + goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), + ); + } + self.instantiate_normalizes_to_term(goal, term); + } + /// Unlike `instantiate_normalizes_to_term` this instantiates the expected term /// with a rigid alias. Using this is pretty much always wrong. pub fn structurally_instantiate_normalizes_to_term( @@ -393,16 +415,10 @@ where kind => panic!("expected projection, found {kind:?}"), }; - let instantiated_term: I::Term = term.instantiate(cx, target_args); - if let Some(ct) = instantiated_term.as_const() { - let expected_ty = cx.type_of(target_item_def_id).instantiate(cx, target_args); - ecx.add_goal( - GoalSource::Misc, - goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), - ); - } - - ecx.instantiate_normalizes_to_term(goal, instantiated_term.skip_norm_wip()); + ecx.instantiate_normalizes_to_term_with_type_check( + goal, + term.instantiate(cx, target_args).skip_norm_wip(), + ); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index b6da72958c9e5..3fdc9998ef2c6 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -5,6 +5,7 @@ use std::ops::ControlFlow; use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorGuaranteed; +use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::resolve::OpportunisticRegionResolver; @@ -484,6 +485,30 @@ fn normalize_to_error<'a, 'tcx>( Normalized { value: new_value, obligations } } +/// When normalizing a const alias, register a `ConstArgHasType` obligation +/// to ensure the const value's type matches the declared type. +fn push_const_arg_has_type_obligation<'tcx>( + tcx: TyCtxt<'tcx>, + obligations: &mut PredicateObligations<'tcx>, + cause: &ObligationCause<'tcx>, + depth: usize, + param_env: ty::ParamEnv<'tcx>, + term: Term<'tcx>, + def_id: DefId, + args: ty::GenericArgsRef<'tcx>, +) { + if let Some(ct) = term.as_const() { + let expected_ty = tcx.type_of(def_id).instantiate(tcx, args).skip_norm_wip(); + obligations.push(Obligation::with_depth( + tcx, + cause.clone(), + depth, + param_env, + ty::ClauseKind::ConstArgHasType(ct, expected_ty), + )); + } +} + /// Confirm and normalize the given inherent projection. // FIXME(mgca): While this supports constants, it is only used for types by default right now #[instrument(level = "debug", skip(selcx, param_env, cause, obligations))] @@ -551,16 +576,16 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( tcx.const_of_item(alias_term.def_id()).instantiate(tcx, args).skip_norm_wip().into() }; - if let Some(ct) = term.as_const() { - let expected_ty = tcx.type_of(alias_term.def_id).instantiate(tcx, args); - obligations.push(Obligation::with_depth( - tcx, - cause.clone(), - depth + 1, - param_env, - ty::ClauseKind::ConstArgHasType(ct, expected_ty), - )); - } + push_const_arg_has_type_obligation( + tcx, + obligations, + &cause, + depth + 1, + param_env, + term, + alias_term.def_id(), + args, + ); let mut term = selcx.infcx.resolve_vars_if_possible(term); if term.has_aliases() { @@ -2057,18 +2082,18 @@ fn confirm_impl_candidate<'cx, 'tcx>( Progress { term: err, obligations: nested } } else { assoc_term_own_obligations(selcx, obligation, &mut nested); - let instantiated_term: Term<'tcx> = term.instantiate(tcx, args); - if let Some(ct) = instantiated_term.as_const() { - let expected_ty = tcx.type_of(assoc_term.item.def_id).instantiate(tcx, args); - nested.push(Obligation::with_depth( - tcx, - obligation.cause.clone(), - obligation.recursion_depth + 1, - obligation.param_env, - ty::ClauseKind::ConstArgHasType(ct, expected_ty), - )); - } - Progress { term: instantiated_term.skip_norm_wip(), obligations: nested } + let instantiated_term: Term<'tcx> = term.instantiate(tcx, args).skip_norm_wip(); + push_const_arg_has_type_obligation( + tcx, + &mut nested, + &obligation.cause, + obligation.recursion_depth + 1, + obligation.param_env, + instantiated_term, + assoc_term.item.def_id, + args, + ); + Progress { term: instantiated_term, obligations: nested } }; Ok(Projected::Progress(progress)) }