From 2d60e51ec79e27786ae23bf55c896ad519bcb5d2 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 13 Aug 2026 06:30:43 +0000 Subject: [PATCH 1/6] Add a normalize_ty callback to try_evaluate_const --- .../src/solve/delegate.rs | 4 ++- .../src/traits/auto_trait.rs | 8 ++++-- .../src/traits/const_evaluatable.rs | 8 ++++-- .../src/traits/fulfill.rs | 1 + .../rustc_trait_selection/src/traits/mod.rs | 28 ++++++++++++++----- .../src/traits/select/mod.rs | 8 ++++-- 6 files changed, 43 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 071c62d0b5ee0..98d0cd35ed45a 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -326,7 +326,9 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< ) -> Option> { let ct = ty::Const::new_alias(self.tcx, ty::IsRigid::No, alias_const); - match crate::traits::try_evaluate_const(&self.0, ct, param_env) { + match crate::traits::try_evaluate_const(&self.0, ct, param_env, |ty| { + Ok::<_, !>(ty.skip_norm_wip()) + }) { Ok(ct) => Some(ct), Err(EvaluateConstErr::EvaluationFailure(e)) => Some(ty::Const::new_error(self.tcx, e)), Err( diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index c885406f6dcfb..798bca8483b0a 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -853,8 +853,12 @@ impl<'tcx> AutoTraitFinder<'tcx> { ty::PredicateKind::ConstEquate(c1, c2) => { let evaluate = |c: ty::Const<'tcx>| { if let ty::ConstKind::Alias(_, alias_const) = c.kind() { - let ct = - super::try_evaluate_const(selcx.infcx, c, obligation.param_env); + let ct = super::try_evaluate_const( + selcx.infcx, + c, + obligation.param_env, + |ty| Ok::<_, !>(ty.skip_norm_wip()), + ); if let Err(EvaluateConstErr::InvalidConstParamTy(_)) = ct { let span = alias_const.kind.def_span(self.tcx); diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 74413d430b1cd..2a1cb4c7ad5d3 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -67,7 +67,9 @@ pub fn is_const_evaluatable<'tcx>( tcx.dcx().span_bug(span, "evaluating `ConstKind::Expr` is not currently supported"); } ty::ConstKind::Alias(_, _) => { - match crate::traits::try_evaluate_const(infcx, unexpanded_ct, param_env) { + match crate::traits::try_evaluate_const(infcx, unexpanded_ct, param_env, |ty| { + Ok::<_, !>(ty.skip_norm_wip()) + }) { Err(EvaluateConstErr::HasGenericsOrInfers) => { Err(NotConstEvaluatable::Error(infcx.dcx().span_delayed_bug( span, @@ -98,7 +100,9 @@ pub fn is_const_evaluatable<'tcx>( _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"), }; - match crate::traits::try_evaluate_const(infcx, unexpanded_ct, param_env) { + match crate::traits::try_evaluate_const(infcx, unexpanded_ct, param_env, |ty| { + Ok::<_, !>(ty.skip_norm_wip()) + }) { // If we're evaluating a generic foreign constant, under a nightly compiler while // the current crate does not enable `feature(generic_const_exprs)`, abort // compilation with a useful error. diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index d0452052f10f6..941d80db4bbc4 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -764,6 +764,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { self.selcx.infcx, c, obligation.param_env, + |ty| Ok::<_, !>(ty.skip_norm_wip()), ) { Ok(val) => Ok(val), e @ Err(EvaluateConstErr::HasGenericsOrInfers) => { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index eda63e09b1189..8b9b21b3d58b2 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -572,8 +572,7 @@ pub fn normalize_param_env_or_error<'tcx>( ty::ParamEnv::new(tcx.mk_clauses(&clauses)) } -#[derive(Debug)] -pub enum EvaluateConstErr { +pub enum EvaluateConstErr { /// The constant being evaluated was either a generic parameter or inference variable, *or*, /// some alias const with either generic parameters or inference variables in its /// generic arguments. @@ -585,6 +584,18 @@ pub enum EvaluateConstErr { /// CTFE failed to evaluate the constant in some unrecoverable way (e.g. encountered a `panic!`). /// This is also used when the constant was already tainted by error. EvaluationFailure(ErrorGuaranteed), + FailedNormalization(E), +} + +impl std::fmt::Debug for EvaluateConstErr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::HasGenericsOrInfers => f.write_str("HasGenericsOrInfers"), + Self::InvalidConstParamTy(e) => f.debug_tuple("InvalidConstParamTy").field(e).finish(), + Self::EvaluationFailure(e) => f.debug_tuple("EvaluationFailure").field(e).finish(), + Self::FailedNormalization(_) => f.write_str("FailedNormalization(..)"), + } + } } // FIXME(BoxyUwU): Private this once we `generic_const_exprs` isn't doing its own normalization routine @@ -601,7 +612,7 @@ pub fn evaluate_const<'tcx>( ct: ty::Const<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> ty::Const<'tcx> { - match try_evaluate_const(infcx, ct, param_env) { + match try_evaluate_const(infcx, ct, param_env, |v| Ok::<_, !>(v.skip_norm_wip())) { Ok(ct) => ct, Err(EvaluateConstErr::EvaluationFailure(e) | EvaluateConstErr::InvalidConstParamTy(e)) => { ty::Const::new_error(infcx.tcx, e) @@ -618,12 +629,13 @@ pub fn evaluate_const<'tcx>( /// /// You should not call this function unless you are implementing normalization itself. Prefer to use /// `normalize_erasing_regions` or the `normalize` functions on `ObligationCtxt`/`FnCtxt`/`InferCtxt`. -#[instrument(level = "debug", skip(infcx), ret)] -pub fn try_evaluate_const<'tcx>( +#[instrument(level = "debug", skip(infcx, normalize_ty), ret)] +pub fn try_evaluate_const<'tcx, E>( infcx: &InferCtxt<'tcx>, ct: ty::Const<'tcx>, param_env: ty::ParamEnv<'tcx>, -) -> Result, EvaluateConstErr> { + normalize_ty: impl FnOnce(Unnormalized<'tcx, Ty<'tcx>>) -> Result, E>, +) -> Result, EvaluateConstErr> { let tcx = infcx.tcx; let ct = infcx.resolve_vars_if_possible(ct); debug!(?ct); @@ -762,7 +774,9 @@ pub fn try_evaluate_const<'tcx>( let span = alias_const.kind.def_span(tcx); match tcx.const_eval_resolve_for_typeck(typing_env, erased_alias_const, span) { Ok(Ok(val)) => { - Ok(ty::Const::new_value(tcx, val, alias_const.type_of(tcx).skip_norm_wip())) + let ty = normalize_ty(alias_const.type_of(tcx)) + .map_err(EvaluateConstErr::FailedNormalization)?; + Ok(ty::Const::new_value(tcx, val, ty)) } Ok(Err(_)) => { let e = tcx.dcx().delayed_bug( diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9b4ee13bf1b63..038b0ae141751 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -921,8 +921,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let evaluate = |c: ty::Const<'tcx>| { if let ty::ConstKind::Alias(_, _) = c.kind() { - match crate::traits::try_evaluate_const(self.infcx, c, obligation.param_env) - { + match crate::traits::try_evaluate_const( + self.infcx, + c, + obligation.param_env, + |v| Ok::<_, !>(v.skip_norm_wip()), + ) { Ok(val) => Ok(val), Err(e) => Err(e), } From 50ea65bdcd7c7ca64a34659cf60150e61e19921a Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 13 Aug 2026 06:31:12 +0000 Subject: [PATCH 2/6] Normalize the type of evaluated consts in the new solver --- .../rustc_next_trait_solver/src/delegate.rs | 10 ++++++++-- .../src/solve/eval_ctxt/mod.rs | 15 +++++++++++---- .../src/solve/delegate.rs | 18 ++++++++++-------- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 1212f422f76e8..2af89789f93f5 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -36,11 +36,17 @@ pub trait SolverDelegate: Deref + Sized { // FIXME: Uplift the leak check into this crate. fn leak_check(&self, max_input_universe: ty::UniverseIndex) -> Result<(), NoSolution>; - fn evaluate_const( + /// Evaluate a const, normalizing the type of the resulting value with `normalize_ty`. + /// Returns `Ok(None)` if the const is too generic, and `Err(_)` only if `normalize_ty` + /// failed. + fn evaluate_const( &self, param_env: ::ParamEnv, alias_const: ty::AliasConst, - ) -> Option<::Const>; + normalize_ty: impl FnOnce( + ty::Unnormalized::Ty>, + ) -> Result<::Ty, E>, + ) -> Result::Const>, E>; // FIXME: This only is here because `wf::obligations` is in `rustc_trait_selection`! fn well_formed_goals( diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 559ca0a98c58e..c78887527dd1e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1403,9 +1403,9 @@ where Ok(()) } - // Try to evaluate a const, or return `None` if the const is too generic. - // This doesn't mean the const isn't evaluatable, though, and should be treated - // as an ambiguity rather than no-solution. + // Try to evaluate a const and normalize the type of the resulting value, or return `None` if + // the const is too generic. This doesn't mean the const isn't evaluatable, though, and should + // be treated as an ambiguity rather than no-solution. pub(super) fn evaluate_const( &mut self, param_env: I::ParamEnv, @@ -1415,7 +1415,14 @@ where match self.opaque_accesses.rerun_always(RerunReason::EvaluateConst)? {} } - Ok(self.delegate.evaluate_const(param_env, alias_const)) + let delegate = self.delegate; + match delegate.evaluate_const(param_env, alias_const, |ty| { + self.normalize(GoalSource::Misc, param_env, ty) + }) { + Ok(ct) => Ok(ct), + Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution)) => Ok(None), + Err(NoSolutionOrRerunNonErased::RerunNonErased(e)) => Err(e), + } } pub(super) fn evaluate_const_and_instantiate_projection_term( diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 98d0cd35ed45a..ad0af281abaa9 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -319,21 +319,23 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< self.0.leak_check(max_input_universe, None).map_err(|_| NoSolution) } - fn evaluate_const( + fn evaluate_const( &self, param_env: ty::ParamEnv<'tcx>, alias_const: ty::AliasConst<'tcx>, - ) -> Option> { + normalize_ty: impl FnOnce(ty::Unnormalized<'tcx, Ty<'tcx>>) -> Result, E>, + ) -> Result>, E> { let ct = ty::Const::new_alias(self.tcx, ty::IsRigid::No, alias_const); - match crate::traits::try_evaluate_const(&self.0, ct, param_env, |ty| { - Ok::<_, !>(ty.skip_norm_wip()) - }) { - Ok(ct) => Some(ct), - Err(EvaluateConstErr::EvaluationFailure(e)) => Some(ty::Const::new_error(self.tcx, e)), + match crate::traits::try_evaluate_const(&self.0, ct, param_env, normalize_ty) { + Ok(ct) => Ok(Some(ct)), + Err(EvaluateConstErr::EvaluationFailure(e)) => { + Ok(Some(ty::Const::new_error(self.tcx, e))) + } Err( EvaluateConstErr::InvalidConstParamTy(_) | EvaluateConstErr::HasGenericsOrInfers, - ) => None, + ) => Ok(None), + Err(EvaluateConstErr::FailedNormalization(e)) => Err(e), } } From 89472f4093e2a671fe14bda91a2ff771a62edacf Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 13 Aug 2026 06:31:12 +0000 Subject: [PATCH 3/6] Add regression test for evaluated const with alias type --- .../next-solver/adt-const-param-projection.rs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/ui/traits/next-solver/adt-const-param-projection.rs diff --git a/tests/ui/traits/next-solver/adt-const-param-projection.rs b/tests/ui/traits/next-solver/adt-const-param-projection.rs new file mode 100644 index 0000000000000..926451bae2c3d --- /dev/null +++ b/tests/ui/traits/next-solver/adt-const-param-projection.rs @@ -0,0 +1,26 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver +//@ build-pass +//@ compile-flags: --crate-type=lib +//@ edition: 2015 + +// Regression test for https://github.com/rust-lang/rust/issues/156294. +// We used to not normalize the type we get back from const evaluation, so the value of +// `EMPTY_MATRIX` had the type `::Matrix` instead of `[usize; 1]`. Nobody +// normalized it later on either, so we ended up ICEing when mangling the symbol name of +// `Walk::::new`. + +#![feature(adt_const_params)] + +pub const EMPTY_MATRIX: ::Matrix = [1]; +pub struct Walk::Matrix>; +impl Walk { + pub fn new() {} +} +pub enum Type {} +pub trait Trait { + type Matrix; +} +impl Trait for Type { + type Matrix = [usize; 1]; +} From 1c7f148de428321b2e7b1e4e07116eed83eb3e31 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 13 Aug 2026 14:47:13 +0000 Subject: [PATCH 4/6] Remove explicit debug impl and other misc --- compiler/rustc_next_trait_solver/src/delegate.rs | 3 ++- .../rustc_trait_selection/src/solve/delegate.rs | 3 ++- compiler/rustc_trait_selection/src/traits/mod.rs | 14 ++------------ .../rustc_trait_selection/src/traits/select/mod.rs | 7 ++----- 4 files changed, 8 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 2af89789f93f5..93e97b53f7720 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -1,3 +1,4 @@ +use std::fmt::Debug; use std::ops::Deref; use rustc_type_ir::solve::{ @@ -39,7 +40,7 @@ pub trait SolverDelegate: Deref + Sized { /// Evaluate a const, normalizing the type of the resulting value with `normalize_ty`. /// Returns `Ok(None)` if the const is too generic, and `Err(_)` only if `normalize_ty` /// failed. - fn evaluate_const( + fn evaluate_const( &self, param_env: ::ParamEnv, alias_const: ty::AliasConst, diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index ad0af281abaa9..d93e3fdf853fc 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -1,4 +1,5 @@ use std::collections::hash_map::Entry; +use std::fmt::Debug; use std::mem; use std::ops::Deref; @@ -319,7 +320,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< self.0.leak_check(max_input_universe, None).map_err(|_| NoSolution) } - fn evaluate_const( + fn evaluate_const( &self, param_env: ty::ParamEnv<'tcx>, alias_const: ty::AliasConst<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 8b9b21b3d58b2..e0c93a7d3af63 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -572,6 +572,7 @@ pub fn normalize_param_env_or_error<'tcx>( ty::ParamEnv::new(tcx.mk_clauses(&clauses)) } +#[derive(Debug)] pub enum EvaluateConstErr { /// The constant being evaluated was either a generic parameter or inference variable, *or*, /// some alias const with either generic parameters or inference variables in its @@ -587,17 +588,6 @@ pub enum EvaluateConstErr { FailedNormalization(E), } -impl std::fmt::Debug for EvaluateConstErr { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::HasGenericsOrInfers => f.write_str("HasGenericsOrInfers"), - Self::InvalidConstParamTy(e) => f.debug_tuple("InvalidConstParamTy").field(e).finish(), - Self::EvaluationFailure(e) => f.debug_tuple("EvaluationFailure").field(e).finish(), - Self::FailedNormalization(_) => f.write_str("FailedNormalization(..)"), - } - } -} - // FIXME(BoxyUwU): Private this once we `generic_const_exprs` isn't doing its own normalization routine // FIXME(generic_const_exprs): Consider accepting a `ty::AliasConst` when we are not rolling our own // normalization scheme @@ -630,7 +620,7 @@ pub fn evaluate_const<'tcx>( /// You should not call this function unless you are implementing normalization itself. Prefer to use /// `normalize_erasing_regions` or the `normalize` functions on `ObligationCtxt`/`FnCtxt`/`InferCtxt`. #[instrument(level = "debug", skip(infcx, normalize_ty), ret)] -pub fn try_evaluate_const<'tcx, E>( +pub fn try_evaluate_const<'tcx, E: Debug>( infcx: &InferCtxt<'tcx>, ct: ty::Const<'tcx>, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 038b0ae141751..d1c579d922287 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -921,15 +921,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let evaluate = |c: ty::Const<'tcx>| { if let ty::ConstKind::Alias(_, _) = c.kind() { - match crate::traits::try_evaluate_const( + crate::traits::try_evaluate_const( self.infcx, c, obligation.param_env, |v| Ok::<_, !>(v.skip_norm_wip()), - ) { - Ok(val) => Ok(val), - Err(e) => Err(e), - } + ) } else { Ok(c) } From 60ec532a0115871660fa0c28a9b7d01238cbf72e Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Tue, 18 Aug 2026 10:52:59 +0000 Subject: [PATCH 5/6] make sure to propagate even the NoSolution from ty normalization in current parent goal context --- .../src/solve/eval_ctxt/mod.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index c78887527dd1e..78d3ab86cc250 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1410,19 +1410,14 @@ where &mut self, param_env: I::ParamEnv, alias_const: ty::AliasConst, - ) -> Result, RerunNonErased> { + ) -> Result, NoSolutionOrRerunNonErased> { if self.typing_mode().is_erased_not_coherence() { match self.opaque_accesses.rerun_always(RerunReason::EvaluateConst)? {} } - let delegate = self.delegate; - match delegate.evaluate_const(param_env, alias_const, |ty| { + self.delegate.evaluate_const(param_env, alias_const, |ty| { self.normalize(GoalSource::Misc, param_env, ty) - }) { - Ok(ct) => Ok(ct), - Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution)) => Ok(None), - Err(NoSolutionOrRerunNonErased::RerunNonErased(e)) => Err(e), - } + }) } pub(super) fn evaluate_const_and_instantiate_projection_term( From 40616472975b7e07f3c44a14719700950f9f4ce8 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Tue, 18 Aug 2026 10:53:37 +0000 Subject: [PATCH 6/6] Add test to observer where CTFE succeeds but normalization of type fails with NoSolution in parent goal context --- .../next-solver/normalize-const-item-type.rs | 34 +++++++++++++++++++ .../normalize-const-item-type.stderr | 23 +++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 tests/ui/traits/next-solver/normalize-const-item-type.rs create mode 100644 tests/ui/traits/next-solver/normalize-const-item-type.stderr diff --git a/tests/ui/traits/next-solver/normalize-const-item-type.rs b/tests/ui/traits/next-solver/normalize-const-item-type.rs new file mode 100644 index 0000000000000..873b0bb690e4c --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-const-item-type.rs @@ -0,0 +1,34 @@ +//@ compile-flags: -Znext-solver +#![feature(generic_const_items)] +#![feature(min_generic_const_args)] +#![feature(generic_const_args)] + +use std::marker::PhantomData; + +trait Project1<'a> { + type Assoc1; +} + +impl<'a, T> Project1<'a> for T { + type Assoc1 = (); +} + +trait Project2 { + type Assoc2; +} + +impl> Project2 for PhantomData { + type Assoc2 = usize; +} + +const N: as Project2>::Assoc2 = 2_usize; + +fn func(_: [(); core::direct_const_arg!(N::)]) +//~^ ERROR: type mismatch resolving `N == _` [E0271] +//~| ERROR: the type `[(); N::]` is not well-formed +//~| ERROR: type mismatch resolving `N == _` [E0271] +where + for<'a> u32: Project1<'a>, +{} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize-const-item-type.stderr b/tests/ui/traits/next-solver/normalize-const-item-type.stderr new file mode 100644 index 0000000000000..67f4f596f40bf --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-const-item-type.stderr @@ -0,0 +1,23 @@ +error[E0271]: type mismatch resolving `N == _` + --> $DIR/normalize-const-item-type.rs:26:12 + | +LL | fn func(_: [(); core::direct_const_arg!(N::)]) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: the type `[(); N::]` is not well-formed + --> $DIR/normalize-const-item-type.rs:26:12 + | +LL | fn func(_: [(); core::direct_const_arg!(N::)]) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0271]: type mismatch resolving `N == _` + --> $DIR/normalize-const-item-type.rs:26:12 + | +LL | fn func(_: [(); core::direct_const_arg!(N::)]) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0271`.