From 3587bf8b63ded0b2677e74850d09bac8b1f650f1 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 3 Feb 2026 20:45:16 +0900 Subject: [PATCH 1/2] trait_selection: fix type-const eval ICE --- .../rustc_trait_selection/src/traits/mod.rs | 19 ++++++++++ .../type-const-ice-issue-151631.rs | 38 +++++++++++++++++++ .../type-const-ice-issue-151631.stderr | 17 +++++++++ 3 files changed, 74 insertions(+) create mode 100644 tests/ui/const-generics/type-const-ice-issue-151631.rs create mode 100644 tests/ui/const-generics/type-const-ice-issue-151631.stderr diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 08f1d947dfb5c..b261e955ea9a4 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -720,6 +720,25 @@ pub fn try_evaluate_const<'tcx>( } }; + if tcx.is_type_const(uv.def) { + match ty::Instance::try_resolve(tcx, typing_env, uv.def, args) { + Ok(Some(instance)) => { + let ct = + tcx.const_of_item(instance.def_id()).instantiate(tcx, instance.args); + return try_evaluate_const(infcx, ct, param_env); + } + Ok(None) => return Err(EvaluateConstErr::HasGenericsOrInfers), + Err(err) => { + return Err(EvaluateConstErr::EvaluationFailure( + rustc_middle::mir::interpret::ReportedErrorInfo::non_const_eval_error( + err, + ) + .into(), + )); + } + } + } + let uv = ty::UnevaluatedConst::new(uv.def, args); let erased_uv = tcx.erase_and_anonymize_regions(uv); diff --git a/tests/ui/const-generics/type-const-ice-issue-151631.rs b/tests/ui/const-generics/type-const-ice-issue-151631.rs new file mode 100644 index 0000000000000..885b4d42c76ab --- /dev/null +++ b/tests/ui/const-generics/type-const-ice-issue-151631.rs @@ -0,0 +1,38 @@ +//@ compile-flags: -Znext-solver=globally +#![feature(generic_const_items, min_generic_const_args)] +#![feature(adt_const_params)] +#![allow(incomplete_features)] +#![allow(dead_code)] + +trait Owner: NewTrait { + #[type_const] + const C: u32; + #[type_const] + const K: u32; +} + +trait NewTrait {} + +impl NewTrait for () {} + +impl Owner for () { + #[type_const] + const C: u32 = N; + #[type_const] + const K: u32 = const { 99 + 1 }; +} + +fn take0(_: impl Owner = { N }>) {} +fn take1(_: impl Owner = 100>) {} + +#[derive(PartialEq, Eq, std::marker::ConstParamTy)] +enum Maybe { + Nothing, + Just(T), +} + +fn main() { + take0::<128>(()); + take1(()); + //~^ ERROR type mismatch resolving `const { 99 + 1 } == 100` +} diff --git a/tests/ui/const-generics/type-const-ice-issue-151631.stderr b/tests/ui/const-generics/type-const-ice-issue-151631.stderr new file mode 100644 index 0000000000000..36575efeec46b --- /dev/null +++ b/tests/ui/const-generics/type-const-ice-issue-151631.stderr @@ -0,0 +1,17 @@ +error[E0271]: type mismatch resolving `const { 99 + 1 } == 100` + --> $DIR/type-const-ice-issue-151631.rs:36:11 + | +LL | take1(()); + | ----- ^^ types differ + | | + | required by a bound introduced by this call + | +note: required by a bound in `take1` + --> $DIR/type-const-ice-issue-151631.rs:26:24 + | +LL | fn take1(_: impl Owner = 100>) {} + | ^^^^^^^^^^^ required by this bound in `take1` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. From 1641602f611ebb7a91b89858a9b263432cdb287c Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 3 Feb 2026 21:03:54 +0900 Subject: [PATCH 2/2] guard recursive type-const evaluation --- .../rustc_trait_selection/src/traits/mod.rs | 325 ++++++++++-------- ...rr => type_const-recursive.current.stderr} | 2 +- .../mgca/type_const-recursive.next.stderr | 8 + .../mgca/type_const-recursive.rs | 8 +- tests/ui/const-generics/type-const-cycle.rs | 16 + .../ui/const-generics/type-const-cycle.stderr | 8 + .../type-const-ice-issue-151631.rs | 42 +-- .../type-const-ice-issue-151631.stderr | 44 ++- 8 files changed, 259 insertions(+), 194 deletions(-) rename tests/ui/const-generics/mgca/{type_const-recursive.stderr => type_const-recursive.current.stderr} (89%) create mode 100644 tests/ui/const-generics/mgca/type_const-recursive.next.stderr create mode 100644 tests/ui/const-generics/type-const-cycle.rs create mode 100644 tests/ui/const-generics/type-const-cycle.stderr diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index b261e955ea9a4..c2279aebcec72 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -26,6 +26,7 @@ pub mod wf; use std::fmt::Debug; use std::ops::ControlFlow; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::DefKind; pub use rustc_infer::traits::*; @@ -592,178 +593,206 @@ pub fn try_evaluate_const<'tcx>( ct: ty::Const<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Result, EvaluateConstErr> { - let tcx = infcx.tcx; - let ct = infcx.resolve_vars_if_possible(ct); - debug!(?ct); - - match ct.kind() { - ty::ConstKind::Value(..) => Ok(ct), - ty::ConstKind::Error(e) => Err(EvaluateConstErr::EvaluationFailure(e)), - ty::ConstKind::Param(_) - | ty::ConstKind::Infer(_) - | ty::ConstKind::Bound(_, _) - | ty::ConstKind::Placeholder(_) - | ty::ConstKind::Expr(_) => Err(EvaluateConstErr::HasGenericsOrInfers), - ty::ConstKind::Unevaluated(uv) => { - let opt_anon_const_kind = - (tcx.def_kind(uv.def) == DefKind::AnonConst).then(|| tcx.anon_const_kind(uv.def)); - - // Postpone evaluation of constants that depend on generic parameters or - // inference variables. - // - // We use `TypingMode::PostAnalysis` here which is not *technically* correct - // to be revealing opaque types here as borrowcheck has not run yet. However, - // CTFE itself uses `TypingMode::PostAnalysis` unconditionally even during - // typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821). - // As a result we always use a revealed env when resolving the instance to evaluate. - // - // FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself - // instead of having this logic here - let (args, typing_env) = match opt_anon_const_kind { - // We handle `generic_const_exprs` separately as reasonable ways of handling constants in the type system - // completely fall apart under `generic_const_exprs` and makes this whole function Really hard to reason - // about if you have to consider gce whatsoever. - Some(ty::AnonConstKind::GCE) => { - if uv.has_non_region_infer() || uv.has_non_region_param() { - // `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause - // inference variables and generic parameters to show up in `ty::Const` even though the anon const - // does not actually make use of them. We handle this case specially and attempt to evaluate anyway. - match tcx.thir_abstract_const(uv.def) { - Ok(Some(ct)) => { - let ct = tcx.expand_abstract_consts(ct.instantiate(tcx, uv.args)); - if let Err(e) = ct.error_reported() { - return Err(EvaluateConstErr::EvaluationFailure(e)); - } else if ct.has_non_region_infer() || ct.has_non_region_param() { - // If the anon const *does* actually use generic parameters or inference variables from - // the generic arguments provided for it, then we should *not* attempt to evaluate it. - return Err(EvaluateConstErr::HasGenericsOrInfers); - } else { - let args = - replace_param_and_infer_args_with_placeholder(tcx, uv.args); - let typing_env = infcx - .typing_env(tcx.erase_and_anonymize_regions(param_env)) - .with_post_analysis_normalized(tcx); + fn try_evaluate_const_inner<'tcx>( + infcx: &InferCtxt<'tcx>, + ct: ty::Const<'tcx>, + param_env: ty::ParamEnv<'tcx>, + type_const_stack: &mut FxHashSet, + ) -> Result, EvaluateConstErr> { + let tcx = infcx.tcx; + let ct = infcx.resolve_vars_if_possible(ct); + debug!(?ct); + + match ct.kind() { + ty::ConstKind::Value(..) => Ok(ct), + ty::ConstKind::Error(e) => Err(EvaluateConstErr::EvaluationFailure(e)), + ty::ConstKind::Param(_) + | ty::ConstKind::Infer(_) + | ty::ConstKind::Bound(_, _) + | ty::ConstKind::Placeholder(_) + | ty::ConstKind::Expr(_) => Err(EvaluateConstErr::HasGenericsOrInfers), + ty::ConstKind::Unevaluated(uv) => { + let opt_anon_const_kind = (tcx.def_kind(uv.def) == DefKind::AnonConst) + .then(|| tcx.anon_const_kind(uv.def)); + + // Postpone evaluation of constants that depend on generic parameters or + // inference variables. + // + // We use `TypingMode::PostAnalysis` here which is not *technically* correct + // to be revealing opaque types here as borrowcheck has not run yet. However, + // CTFE itself uses `TypingMode::PostAnalysis` unconditionally even during + // typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821). + // As a result we always use a revealed env when resolving the instance to evaluate. + // + // FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself + // instead of having this logic here + let (args, typing_env) = match opt_anon_const_kind { + // We handle `generic_const_exprs` separately as reasonable ways of handling constants in the type system + // completely fall apart under `generic_const_exprs` and makes this whole function Really hard to reason + // about if you have to consider gce whatsoever. + Some(ty::AnonConstKind::GCE) => { + if uv.has_non_region_infer() || uv.has_non_region_param() { + // `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause + // inference variables and generic parameters to show up in `ty::Const` even though the anon const + // does not actually make use of them. We handle this case specially and attempt to evaluate anyway. + match tcx.thir_abstract_const(uv.def) { + Ok(Some(ct)) => { + let ct = + tcx.expand_abstract_consts(ct.instantiate(tcx, uv.args)); + if let Err(e) = ct.error_reported() { + return Err(EvaluateConstErr::EvaluationFailure(e)); + } else if ct.has_non_region_infer() || ct.has_non_region_param() + { + // If the anon const *does* actually use generic parameters or inference variables from + // the generic arguments provided for it, then we should *not* attempt to evaluate it. + return Err(EvaluateConstErr::HasGenericsOrInfers); + } else { + let args = replace_param_and_infer_args_with_placeholder( + tcx, uv.args, + ); + let typing_env = infcx + .typing_env(tcx.erase_and_anonymize_regions(param_env)) + .with_post_analysis_normalized(tcx); + (args, typing_env) + } + } + Err(_) | Ok(None) => { + let args = GenericArgs::identity_for_item(tcx, uv.def); + let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def); (args, typing_env) } } - Err(_) | Ok(None) => { - let args = GenericArgs::identity_for_item(tcx, uv.def); - let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def); - (args, typing_env) - } + } else { + let typing_env = infcx + .typing_env(tcx.erase_and_anonymize_regions(param_env)) + .with_post_analysis_normalized(tcx); + (uv.args, typing_env) } - } else { - let typing_env = infcx - .typing_env(tcx.erase_and_anonymize_regions(param_env)) - .with_post_analysis_normalized(tcx); - (uv.args, typing_env) - } - } - Some(ty::AnonConstKind::RepeatExprCount) => { - if uv.has_non_region_infer() { - // Diagnostics will sometimes replace the identity args of anon consts in - // array repeat expr counts with inference variables so we have to handle this - // even though it is not something we should ever actually encounter. - // - // Array repeat expr counts are allowed to syntactically use generic parameters - // but must not actually depend on them in order to evalaute successfully. This means - // that it is actually fine to evalaute them in their own environment rather than with - // the actually provided generic arguments. - tcx.dcx().delayed_bug("AnonConst with infer args but no error reported"); } + Some(ty::AnonConstKind::RepeatExprCount) => { + if uv.has_non_region_infer() { + // Diagnostics will sometimes replace the identity args of anon consts in + // array repeat expr counts with inference variables so we have to handle this + // even though it is not something we should ever actually encounter. + // + // Array repeat expr counts are allowed to syntactically use generic parameters + // but must not actually depend on them in order to evalaute successfully. This means + // that it is actually fine to evalaute them in their own environment rather than with + // the actually provided generic arguments. + tcx.dcx() + .delayed_bug("AnonConst with infer args but no error reported"); + } - // The generic args of repeat expr counts under `min_const_generics` are not supposed to - // affect evaluation of the constant as this would make it a "truly" generic const arg. - // To prevent this we discard all the generic arguments and evalaute with identity args - // and in its own environment instead of the current environment we are normalizing in. - let args = GenericArgs::identity_for_item(tcx, uv.def); - let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def); + // The generic args of repeat expr counts under `min_const_generics` are not supposed to + // affect evaluation of the constant as this would make it a "truly" generic const arg. + // To prevent this we discard all the generic arguments and evalaute with identity args + // and in its own environment instead of the current environment we are normalizing in. + let args = GenericArgs::identity_for_item(tcx, uv.def); + let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def); - (args, typing_env) - } - Some(ty::AnonConstKind::OGCA) => { - if infcx.typing_mode() != TypingMode::PostAnalysis { - // OGCA anon consts should be treated as always having generics - // during anything before codegen (or maybe MIR opts too). - return Err(EvaluateConstErr::HasGenericsOrInfers); + (args, typing_env) } + Some(ty::AnonConstKind::OGCA) => { + if infcx.typing_mode() != TypingMode::PostAnalysis { + // OGCA anon consts should be treated as always having generics + // during anything before codegen (or maybe MIR opts too). + return Err(EvaluateConstErr::HasGenericsOrInfers); + } - if uv.args.has_non_region_param() || uv.args.has_non_region_infer() { - return Err(EvaluateConstErr::HasGenericsOrInfers); - } + if uv.args.has_non_region_param() || uv.args.has_non_region_infer() { + return Err(EvaluateConstErr::HasGenericsOrInfers); + } - let typing_env = ty::TypingEnv::fully_monomorphized(); - (uv.args, typing_env) - } - Some(ty::AnonConstKind::MCG) | Some(ty::AnonConstKind::NonTypeSystem) | None => { - // We are only dealing with "truly" generic/uninferred constants here: - // - GCEConsts have been handled separately - // - Repeat expr count back compat consts have also been handled separately - // So we are free to simply defer evaluation here. - // - // FIXME: This assumes that `args` are normalized which is not necessarily true - // - // Const patterns are converted to type system constants before being - // evaluated. However, we don't care about them here as pattern evaluation - // logic does not go through type system normalization. If it did this would - // be a backwards compatibility problem as we do not enforce "syntactic" non- - // usage of generic parameters like we do here. - if uv.args.has_non_region_param() || uv.args.has_non_region_infer() { - return Err(EvaluateConstErr::HasGenericsOrInfers); + let typing_env = ty::TypingEnv::fully_monomorphized(); + (uv.args, typing_env) } + Some(ty::AnonConstKind::MCG) + | Some(ty::AnonConstKind::NonTypeSystem) + | None => { + // We are only dealing with "truly" generic/uninferred constants here: + // - GCEConsts have been handled separately + // - Repeat expr count back compat consts have also been handled separately + // So we are free to simply defer evaluation here. + // + // FIXME: This assumes that `args` are normalized which is not necessarily true + // + // Const patterns are converted to type system constants before being + // evaluated. However, we don't care about them here as pattern evaluation + // logic does not go through type system normalization. If it did this would + // be a backwards compatibility problem as we do not enforce "syntactic" non- + // usage of generic parameters like we do here. + if uv.args.has_non_region_param() || uv.args.has_non_region_infer() { + return Err(EvaluateConstErr::HasGenericsOrInfers); + } - // Since there is no generic parameter, we can just drop the environment - // to prevent query cycle. - let typing_env = ty::TypingEnv::fully_monomorphized(); + // Since there is no generic parameter, we can just drop the environment + // to prevent query cycle. + let typing_env = ty::TypingEnv::fully_monomorphized(); - (uv.args, typing_env) - } - }; - - if tcx.is_type_const(uv.def) { - match ty::Instance::try_resolve(tcx, typing_env, uv.def, args) { - Ok(Some(instance)) => { - let ct = - tcx.const_of_item(instance.def_id()).instantiate(tcx, instance.args); - return try_evaluate_const(infcx, ct, param_env); + (uv.args, typing_env) + } + }; + + if tcx.is_type_const(uv.def) { + // Guard against self-referential type consts which would otherwise recurse. + if !type_const_stack.insert(uv.def) { + let guar = tcx.dcx().span_err( + tcx.def_span(uv.def), + "cycle detected when evaluating type-level constant", + ); + return Err(EvaluateConstErr::EvaluationFailure(guar)); } - Ok(None) => return Err(EvaluateConstErr::HasGenericsOrInfers), - Err(err) => { - return Err(EvaluateConstErr::EvaluationFailure( + + let result = match ty::Instance::try_resolve(tcx, typing_env, uv.def, args) { + Ok(Some(instance)) => { + let ct = tcx + .const_of_item(instance.def_id()) + .instantiate(tcx, instance.args); + try_evaluate_const_inner(infcx, ct, param_env, type_const_stack) + } + Ok(None) => Err(EvaluateConstErr::HasGenericsOrInfers), + Err(err) => Err(EvaluateConstErr::EvaluationFailure( rustc_middle::mir::interpret::ReportedErrorInfo::non_const_eval_error( err, ) .into(), - )); - } - } - } + )), + }; - let uv = ty::UnevaluatedConst::new(uv.def, args); - let erased_uv = tcx.erase_and_anonymize_regions(uv); - - use rustc_middle::mir::interpret::ErrorHandled; - // FIXME: `def_span` will point at the definition of this const; ideally, we'd point at - // where it gets used as a const generic. - match tcx.const_eval_resolve_for_typeck(typing_env, erased_uv, tcx.def_span(uv.def)) { - Ok(Ok(val)) => Ok(ty::Const::new_value( - tcx, - val, - tcx.type_of(uv.def).instantiate(tcx, uv.args), - )), - Ok(Err(_)) => { - let e = tcx.dcx().delayed_bug( - "Type system constant with non valtree'able type evaluated but no error emitted", - ); - Err(EvaluateConstErr::InvalidConstParamTy(e)) + type_const_stack.remove(&uv.def); + return result; } - Err(ErrorHandled::Reported(info, _)) => { - Err(EvaluateConstErr::EvaluationFailure(info.into())) + + let uv = ty::UnevaluatedConst::new(uv.def, args); + let erased_uv = tcx.erase_and_anonymize_regions(uv); + + use rustc_middle::mir::interpret::ErrorHandled; + // FIXME: `def_span` will point at the definition of this const; ideally, we'd point at + // where it gets used as a const generic. + match tcx.const_eval_resolve_for_typeck(typing_env, erased_uv, tcx.def_span(uv.def)) + { + Ok(Ok(val)) => Ok(ty::Const::new_value( + tcx, + val, + tcx.type_of(uv.def).instantiate(tcx, uv.args), + )), + Ok(Err(_)) => { + let e = tcx.dcx().delayed_bug( + "Type system constant with non valtree'able type evaluated but no error emitted", + ); + Err(EvaluateConstErr::InvalidConstParamTy(e)) + } + Err(ErrorHandled::Reported(info, _)) => { + Err(EvaluateConstErr::EvaluationFailure(info.into())) + } + Err(ErrorHandled::TooGeneric(_)) => Err(EvaluateConstErr::HasGenericsOrInfers), } - Err(ErrorHandled::TooGeneric(_)) => Err(EvaluateConstErr::HasGenericsOrInfers), } } } + + let mut type_const_stack = FxHashSet::default(); + try_evaluate_const_inner(infcx, ct, param_env, &mut type_const_stack) } /// Replaces args that reference param or infer variables with suitable diff --git a/tests/ui/const-generics/mgca/type_const-recursive.stderr b/tests/ui/const-generics/mgca/type_const-recursive.current.stderr similarity index 89% rename from tests/ui/const-generics/mgca/type_const-recursive.stderr rename to tests/ui/const-generics/mgca/type_const-recursive.current.stderr index d21ccb22bc90b..4df39fce0bc80 100644 --- a/tests/ui/const-generics/mgca/type_const-recursive.stderr +++ b/tests/ui/const-generics/mgca/type_const-recursive.current.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow normalizing the unevaluated constant `A` - --> $DIR/type_const-recursive.rs:5:1 + --> $DIR/type_const-recursive.rs:8:1 | LL | type const A: u8 = A; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/mgca/type_const-recursive.next.stderr b/tests/ui/const-generics/mgca/type_const-recursive.next.stderr new file mode 100644 index 0000000000000..b4cd0fc3798f5 --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-recursive.next.stderr @@ -0,0 +1,8 @@ +error: cycle detected when evaluating type-level constant + --> $DIR/type_const-recursive.rs:8:1 + | +LL | type const A: u8 = A; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/mgca/type_const-recursive.rs b/tests/ui/const-generics/mgca/type_const-recursive.rs index ebaab51bbc3b6..ce70fa146c655 100644 --- a/tests/ui/const-generics/mgca/type_const-recursive.rs +++ b/tests/ui/const-generics/mgca/type_const-recursive.rs @@ -1,8 +1,12 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + #![expect(incomplete_features)] #![feature(min_generic_const_args)] - type const A: u8 = A; -//~^ ERROR: overflow normalizing the unevaluated constant `A` [E0275] +//[current]~^ ERROR: overflow normalizing the unevaluated constant `A` [E0275] +//[next]~^^ ERROR cycle detected when evaluating type-level constant fn main() {} diff --git a/tests/ui/const-generics/type-const-cycle.rs b/tests/ui/const-generics/type-const-cycle.rs new file mode 100644 index 0000000000000..0d8d4df68fae4 --- /dev/null +++ b/tests/ui/const-generics/type-const-cycle.rs @@ -0,0 +1,16 @@ +//@ compile-flags: -Znext-solver=globally +#![feature(generic_const_items, min_generic_const_args)] +#![allow(incomplete_features)] + +trait Owner { + type const C: u32; + //~^ ERROR cycle detected when evaluating type-level constant +} + +impl Owner for () { + type const C: u32 = { <() as Owner>::C:: }; +} + +type Arr = [u8; <() as Owner>::C::<0>]; + +fn main() {} diff --git a/tests/ui/const-generics/type-const-cycle.stderr b/tests/ui/const-generics/type-const-cycle.stderr new file mode 100644 index 0000000000000..41987f465d171 --- /dev/null +++ b/tests/ui/const-generics/type-const-cycle.stderr @@ -0,0 +1,8 @@ +error: cycle detected when evaluating type-level constant + --> $DIR/type-const-cycle.rs:6:5 + | +LL | type const C: u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/type-const-ice-issue-151631.rs b/tests/ui/const-generics/type-const-ice-issue-151631.rs index 885b4d42c76ab..53c6d0c6dd6d4 100644 --- a/tests/ui/const-generics/type-const-ice-issue-151631.rs +++ b/tests/ui/const-generics/type-const-ice-issue-151631.rs @@ -1,38 +1,18 @@ -//@ compile-flags: -Znext-solver=globally -#![feature(generic_const_items, min_generic_const_args)] -#![feature(adt_const_params)] -#![allow(incomplete_features)] -#![allow(dead_code)] +// issue: +//@ compile-flags: -Znext-solver +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] -trait Owner: NewTrait { - #[type_const] - const C: u32; - #[type_const] - const K: u32; +trait SuperTrait {} +trait Trait: SuperTrait { + type const K: u32; } - -trait NewTrait {} - -impl NewTrait for () {} - -impl Owner for () { - #[type_const] - const C: u32 = N; - #[type_const] - const K: u32 = const { 99 + 1 }; +impl Trait for () { //~ ERROR: the trait bound `(): SuperTrait` is not satisfied + type const K: u32 = const { 1 }; } -fn take0(_: impl Owner = { N }>) {} -fn take1(_: impl Owner = 100>) {} - -#[derive(PartialEq, Eq, std::marker::ConstParamTy)] -enum Maybe { - Nothing, - Just(T), -} +fn check(_: impl Trait) {} fn main() { - take0::<128>(()); - take1(()); - //~^ ERROR type mismatch resolving `const { 99 + 1 } == 100` + check(()); //~ ERROR: the trait bound `(): SuperTrait` is not satisfied } diff --git a/tests/ui/const-generics/type-const-ice-issue-151631.stderr b/tests/ui/const-generics/type-const-ice-issue-151631.stderr index 36575efeec46b..6f287293e27cf 100644 --- a/tests/ui/const-generics/type-const-ice-issue-151631.stderr +++ b/tests/ui/const-generics/type-const-ice-issue-151631.stderr @@ -1,17 +1,37 @@ -error[E0271]: type mismatch resolving `const { 99 + 1 } == 100` - --> $DIR/type-const-ice-issue-151631.rs:36:11 +error[E0277]: the trait bound `(): SuperTrait` is not satisfied + --> $DIR/type-const-ice-issue-151631.rs:10:16 | -LL | take1(()); - | ----- ^^ types differ - | | - | required by a bound introduced by this call +LL | impl Trait for () { + | ^^ the trait `SuperTrait` is not implemented for `()` | -note: required by a bound in `take1` - --> $DIR/type-const-ice-issue-151631.rs:26:24 +help: this trait has no implementations, consider adding one + --> $DIR/type-const-ice-issue-151631.rs:6:1 | -LL | fn take1(_: impl Owner = 100>) {} - | ^^^^^^^^^^^ required by this bound in `take1` +LL | trait SuperTrait {} + | ^^^^^^^^^^^^^^^^ +note: required by a bound in `Trait` + --> $DIR/type-const-ice-issue-151631.rs:7:14 + | +LL | trait Trait: SuperTrait { + | ^^^^^^^^^^ required by this bound in `Trait` + +error[E0277]: the trait bound `(): SuperTrait` is not satisfied + --> $DIR/type-const-ice-issue-151631.rs:17:5 + | +LL | check(()); + | ^^^^^^^^^ the trait `SuperTrait` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/type-const-ice-issue-151631.rs:6:1 + | +LL | trait SuperTrait {} + | ^^^^^^^^^^^^^^^^ +note: required by a bound in `Trait` + --> $DIR/type-const-ice-issue-151631.rs:7:14 + | +LL | trait Trait: SuperTrait { + | ^^^^^^^^^^ required by this bound in `Trait` -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`.