From c32ffdda41fc86e65f5377fa564a1e9a8d735e41 Mon Sep 17 00:00:00 2001 From: zedddie Date: Fri, 24 Jul 2026 21:52:16 +0200 Subject: [PATCH 1/4] check wf before const-evaluating --- .../src/solve/eval_ctxt/mod.rs | 26 +++++++++--- .../rustc_next_trait_solver/src/solve/mod.rs | 11 +++-- compiler/rustc_type_ir/src/const_kind.rs | 5 +++ .../gca/type-const-arg-type-mismatch-1.rs | 10 +++++ .../gca/type-const-arg-type-mismatch-1.stderr | 27 +++++++++++++ .../gca/type-const-arg-type-mismatch-2.rs | 11 +++++ .../gca/type-const-arg-type-mismatch-2.stderr | 27 +++++++++++++ .../unevaluated-const-ice-119731.rs | 4 -- .../unevaluated-const-ice-119731.stderr | 40 ++----------------- ...nown-alias-defkind-anonconst-ice-116710.rs | 1 + ...-alias-defkind-anonconst-ice-116710.stderr | 14 ++++++- 11 files changed, 124 insertions(+), 52 deletions(-) create mode 100644 tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.rs create mode 100644 tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.stderr create mode 100644 tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.rs create mode 100644 tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.stderr 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 c3ccb46069063..a8288cd691a36 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 @@ -1289,12 +1289,26 @@ where &mut self, param_env: I::ParamEnv, alias_const: ty::AliasConst, - ) -> Result, RerunNonErased> { + ) -> Result<(Option, Certainty), NoSolutionOrRerunNonErased> { + let cx = self.cx(); + let goal = Goal::new( + cx, + param_env, + ty::ClauseKind::WellFormed(alias_const.to_const(cx, ty::IsRigid::Yes).into()), + ); + self.add_goal(GoalSource::AliasWellFormed, goal)?; + + let certainty = self.try_evaluate_added_goals()?; + + if matches!(certainty, Certainty::Maybe(_)) { + return Ok((None, certainty)); + } + if self.typing_mode().is_erased_not_coherence() { match self.opaque_accesses.rerun_always(RerunReason::EvaluateConst)? {} } - Ok(self.delegate.evaluate_const(param_env, alias_const)) + Ok((self.delegate.evaluate_const(param_env, alias_const), certainty)) } pub(super) fn evaluate_const_and_instantiate_projection_term( @@ -1305,11 +1319,11 @@ where alias_const: ty::AliasConst, ) -> QueryResultOrRerunNonErased { match self.evaluate_const(param_env, alias_const)? { - Some(evaluated) => { + (Some(evaluated), _) => { self.eq(param_env, expected_term, evaluated.into())?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } - None if self.cx().features().generic_const_args() => { + (None, certainty) if self.cx().features().generic_const_args() => { // HACK(khyperia): calling `resolve_vars_if_possible` here shouldn't be necessary, // `try_evaluate_const` calls `resolve_vars_if_possible` already. However, we want // to check `has_non_region_infer` against the type with vars resolved (i.e. check @@ -1331,10 +1345,10 @@ where projection_term.to_term(self.cx(), ty::IsRigid::Yes), expected_term, )?; - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + self.evaluate_added_goals_and_make_canonical_response(certainty) } } - None => { + (None, _) => { // Legacy behavior: always treat as ambiguous self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 195f08dfafd59..07c6219203807 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -215,10 +215,13 @@ where // FIXME(generic_const_exprs): Implement handling for generic // const expressions here. - if let Some(_normalized) = self.evaluate_const(param_env, alias_const)? { - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } else { - self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + match self.evaluate_const(param_env, alias_const)? { + (None, certainty) => self.evaluate_added_goals_and_make_canonical_response( + certainty.and(Certainty::AMBIGUOUS), + ), + (Some(_normalized), _) => { + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } } } diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 29c65974d8b28..a48ad4cfe1ac8 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -9,6 +9,7 @@ use rustc_type_ir_macros::{ GenericTypeVisitable, Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic, }; +use crate::inherent::*; use crate::{self as ty, AliasConst, BoundVarIndexKind, Interner}; /// Represents a constant in Rust. @@ -84,6 +85,10 @@ impl AliasConst { AliasConst { kind, args, _use_alias_new_instead: () } } + pub fn to_const(self, interner: I, is_rigid: ty::IsRigid) -> I::Const { + I::Const::new_alias(interner, is_rigid, self) + } + pub fn type_of(self, interner: I) -> ty::Unnormalized { let def_id = match self.kind { ty::AliasConstKind::Projection { def_id } => def_id.into(), diff --git a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.rs b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.rs new file mode 100644 index 0000000000000..b5207c7ecfa38 --- /dev/null +++ b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.rs @@ -0,0 +1,10 @@ +//@ compile-flags: -Znext-solver=globally +#![feature(min_generic_const_args)] +#![feature(generic_const_args)] +#![feature(generic_const_items)] + +const ADD1: usize = N + 1; +type const ONE: usize = ADD1::; //~ ERROR type mismatch resolving +//~| ERROR the constant `*b""` is not of type `usize` +//~| ERROR the constant `ADD1::<*b"">` is not of type `usize` +fn main() {} diff --git a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.stderr b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.stderr new file mode 100644 index 0000000000000..545f3036972b9 --- /dev/null +++ b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.stderr @@ -0,0 +1,27 @@ +error[E0271]: type mismatch resolving `ADD1<*b""> == _` + --> $DIR/type-const-arg-type-mismatch-1.rs:7:1 + | +LL | type const ONE: usize = ADD1::; + | ^^^^^^^^^^^^^^^^^^^^^ types differ + +error: the constant `*b""` is not of type `usize` + --> $DIR/type-const-arg-type-mismatch-1.rs:7:1 + | +LL | type const ONE: usize = ADD1::; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `[u8; 0]` + | +note: required by a const generic parameter in `ADD1` + --> $DIR/type-const-arg-type-mismatch-1.rs:6:12 + | +LL | const ADD1: usize = N + 1; + | ^^^^^^^^^^^^^^ required by this const generic parameter in `ADD1` + +error: the constant `ADD1::<*b"">` is not of type `usize` + --> $DIR/type-const-arg-type-mismatch-1.rs:7:1 + | +LL | type const ONE: usize = ADD1::; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found a different `usize` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.rs b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.rs new file mode 100644 index 0000000000000..88743e6382e0e --- /dev/null +++ b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.rs @@ -0,0 +1,11 @@ +//@ compile-flags: -Znext-solver=globally +#![feature(min_generic_const_args)] +#![feature(macroless_generic_const_args)] +#![feature(generic_const_args)] +#![feature(generic_const_items)] + +const ADD1: usize = N + 1; +type const ONE: usize = ADD1::; //~ ERROR type mismatch resolving +//~| ERROR the constant `*b""` is not of type `usize` +//~| ERROR the constant `ADD1::<*b"">` is not of type `usize` +fn main() {} diff --git a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.stderr b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.stderr new file mode 100644 index 0000000000000..2bc1c914ae9df --- /dev/null +++ b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.stderr @@ -0,0 +1,27 @@ +error[E0271]: type mismatch resolving `ADD1<*b""> == _` + --> $DIR/type-const-arg-type-mismatch-2.rs:8:1 + | +LL | type const ONE: usize = ADD1::; + | ^^^^^^^^^^^^^^^^^^^^^ types differ + +error: the constant `*b""` is not of type `usize` + --> $DIR/type-const-arg-type-mismatch-2.rs:8:1 + | +LL | type const ONE: usize = ADD1::; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `[u8; 0]` + | +note: required by a const generic parameter in `ADD1` + --> $DIR/type-const-arg-type-mismatch-2.rs:7:12 + | +LL | const ADD1: usize = N + 1; + | ^^^^^^^^^^^^^^ required by this const generic parameter in `ADD1` + +error: the constant `ADD1::<*b"">` is not of type `usize` + --> $DIR/type-const-arg-type-mismatch-2.rs:8:1 + | +LL | type const ONE: usize = ADD1::; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found a different `usize` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs index 99130689d7ce2..0107bbc2aae0b 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs @@ -27,10 +27,6 @@ mod v20 { impl v17 { //~^ ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} - //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} - //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} - //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} - //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} pub const fn v21() -> v18 { //~^ ERROR cannot find type `v18` in this scope diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index 022074181cecd..e0faf1e926c0f 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `v20::v13` - --> $DIR/unevaluated-const-ice-119731.rs:42:15 + --> $DIR/unevaluated-const-ice-119731.rs:38:15 | LL | pub use v20::{v13, v17}; | ^^^ no `v13` in `v20` @@ -32,7 +32,7 @@ LL + pub const fn v21() -> v11 {} | error[E0425]: cannot find type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:35:31 + --> $DIR/unevaluated-const-ice-119731.rs:31:31 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -47,7 +47,7 @@ LL + pub const fn v21() -> v11 { | error[E0422]: cannot find struct, variant or union type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:37:13 + --> $DIR/unevaluated-const-ice-119731.rs:33:13 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -107,38 +107,6 @@ LL | impl v17 { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} - --> $DIR/unevaluated-const-ice-119731.rs:28:37 - | -LL | impl v17 { - | ^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} - --> $DIR/unevaluated-const-ice-119731.rs:28:37 - | -LL | impl v17 { - | ^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} - --> $DIR/unevaluated-const-ice-119731.rs:28:37 - | -LL | impl v17 { - | ^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} - --> $DIR/unevaluated-const-ice-119731.rs:28:37 - | -LL | impl v17 { - | ^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error[E0592]: duplicate definitions with name `v21` --> $DIR/unevaluated-const-ice-119731.rs:23:9 | @@ -148,7 +116,7 @@ LL | pub const fn v21() -> v18 {} LL | pub const fn v21() -> v18 { | ------------------------- other definition for `v21` -error: aborting due to 14 previous errors; 2 warnings emitted +error: aborting due to 10 previous errors; 2 warnings emitted Some errors have detailed explanations: E0422, E0425, E0432, E0592. For more information about an error, try `rustc --explain E0422`. diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs index 3685e71a4808d..219b0eac16c0f 100644 --- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs +++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs @@ -10,5 +10,6 @@ trait Trait {} impl Trait for A {} impl Trait for A {} +//~^ ERROR conflicting implementations of trait `Trait` for type `A<_>` pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr index a3b33fcbe6246..31bfe88cc8cbd 100644 --- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr @@ -6,6 +6,16 @@ LL | struct A; | = note: a builtin type named `u8` exists in another namespace -error: aborting due to 1 previous error +error[E0119]: conflicting implementations of trait `Trait` for type `A<_>` + --> $DIR/unknown-alias-defkind-anonconst-ice-116710.rs:12:1 + | +LL | impl Trait for A {} + | --------------------------------- first implementation here +LL | +LL | impl Trait for A {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A<_>` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0423`. +Some errors have detailed explanations: E0119, E0423. +For more information about an error, try `rustc --explain E0119`. From 16afb23245d3e883234a5ef8af88574152f69249 Mon Sep 17 00:00:00 2001 From: zedddie Date: Tue, 11 Aug 2026 07:16:15 +0200 Subject: [PATCH 2/4] skip pre-eval wf check under GCE --- .../src/solve/eval_ctxt/mod.rs | 31 +++++++------- .../impl-block-type-const-type-mismatch.rs | 13 ++++++ ...impl-block-type-const-type-mismatch.stderr | 24 +++++++++++ .../gca/type-const-arg-type-mismatch-1.rs | 1 + .../gca/type-const-arg-type-mismatch-1.stderr | 8 ++-- .../gca/type-const-arg-type-mismatch-2.rs | 1 + .../gca/type-const-arg-type-mismatch-2.stderr | 8 ++-- .../unevaluated-const-ice-119731.rs | 4 ++ .../unevaluated-const-ice-119731.stderr | 40 +++++++++++++++++-- ...nown-alias-defkind-anonconst-ice-116710.rs | 1 - ...-alias-defkind-anonconst-ice-116710.stderr | 14 +------ 11 files changed, 106 insertions(+), 39 deletions(-) create mode 100644 tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.rs create mode 100644 tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.stderr 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 a8288cd691a36..b9788d49efed8 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 @@ -1290,23 +1290,26 @@ where param_env: I::ParamEnv, alias_const: ty::AliasConst, ) -> Result<(Option, Certainty), NoSolutionOrRerunNonErased> { - let cx = self.cx(); - let goal = Goal::new( - cx, - param_env, - ty::ClauseKind::WellFormed(alias_const.to_const(cx, ty::IsRigid::Yes).into()), - ); - self.add_goal(GoalSource::AliasWellFormed, goal)?; - - let certainty = self.try_evaluate_added_goals()?; - - if matches!(certainty, Certainty::Maybe(_)) { - return Ok((None, certainty)); - } - if self.typing_mode().is_erased_not_coherence() { match self.opaque_accesses.rerun_always(RerunReason::EvaluateConst)? {} } + let cx = self.cx(); + let certainty = if cx.features().generic_const_exprs() { + Certainty::Yes + } else { + let goal = Goal::new( + cx, + param_env, + ty::ClauseKind::WellFormed(alias_const.to_const(cx, ty::IsRigid::Yes).into()), + ); + self.add_goal(GoalSource::AliasWellFormed, goal)?; + let certainty = self.try_evaluate_added_goals()?; + + if matches!(certainty, Certainty::Maybe(_)) { + return Ok((None, certainty)); + } + certainty + }; Ok((self.delegate.evaluate_const(param_env, alias_const), certainty)) } diff --git a/tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.rs b/tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.rs new file mode 100644 index 0000000000000..a0731e8daf277 --- /dev/null +++ b/tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.rs @@ -0,0 +1,13 @@ +//! Regression test for . +//@ compile-flags: -Znext-solver=globally +#![feature(min_generic_const_args)] +#![feature(generic_const_args)] +#![feature(generic_const_items)] +#![feature(macroless_generic_const_args)] + +const ADD1: usize = N + 1; +type const A: usize = ADD1::; +impl [(); A::<1f64>] {} //~ ERROR: type mismatch resolving `A<1f64> == _` [E0271] +//~| ERROR: cannot define inherent `impl` for primitive types [E0390] + //~^^ ERROR: the type `[(); A::<1f64>]` is not well-formed +fn main() {} diff --git a/tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.stderr b/tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.stderr new file mode 100644 index 0000000000000..d274f9e233121 --- /dev/null +++ b/tests/ui/const-generics/gca/impl-block-type-const-type-mismatch.stderr @@ -0,0 +1,24 @@ +error[E0271]: type mismatch resolving `A<1f64> == _` + --> $DIR/impl-block-type-const-type-mismatch.rs:10:1 + | +LL | impl [(); A::<1f64>] {} + | ^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: the type `[(); A::<1f64>]` is not well-formed + --> $DIR/impl-block-type-const-type-mismatch.rs:10:6 + | +LL | impl [(); A::<1f64>] {} + | ^^^^^^^^^^^^^^^ + +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/impl-block-type-const-type-mismatch.rs:10:1 + | +LL | impl [(); A::<1f64>] {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using an extension trait instead + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0271, E0390. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.rs b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.rs index b5207c7ecfa38..42620ca444389 100644 --- a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.rs +++ b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.rs @@ -1,3 +1,4 @@ +//! Regression test for . //@ compile-flags: -Znext-solver=globally #![feature(min_generic_const_args)] #![feature(generic_const_args)] diff --git a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.stderr b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.stderr index 545f3036972b9..3ecedd7a4353b 100644 --- a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.stderr +++ b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-1.stderr @@ -1,23 +1,23 @@ error[E0271]: type mismatch resolving `ADD1<*b""> == _` - --> $DIR/type-const-arg-type-mismatch-1.rs:7:1 + --> $DIR/type-const-arg-type-mismatch-1.rs:8:1 | LL | type const ONE: usize = ADD1::; | ^^^^^^^^^^^^^^^^^^^^^ types differ error: the constant `*b""` is not of type `usize` - --> $DIR/type-const-arg-type-mismatch-1.rs:7:1 + --> $DIR/type-const-arg-type-mismatch-1.rs:8:1 | LL | type const ONE: usize = ADD1::; | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `[u8; 0]` | note: required by a const generic parameter in `ADD1` - --> $DIR/type-const-arg-type-mismatch-1.rs:6:12 + --> $DIR/type-const-arg-type-mismatch-1.rs:7:12 | LL | const ADD1: usize = N + 1; | ^^^^^^^^^^^^^^ required by this const generic parameter in `ADD1` error: the constant `ADD1::<*b"">` is not of type `usize` - --> $DIR/type-const-arg-type-mismatch-1.rs:7:1 + --> $DIR/type-const-arg-type-mismatch-1.rs:8:1 | LL | type const ONE: usize = ADD1::; | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found a different `usize` diff --git a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.rs b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.rs index 88743e6382e0e..e4d7e20fcfce4 100644 --- a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.rs +++ b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.rs @@ -1,3 +1,4 @@ +//! Regression test for . //@ compile-flags: -Znext-solver=globally #![feature(min_generic_const_args)] #![feature(macroless_generic_const_args)] diff --git a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.stderr b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.stderr index 2bc1c914ae9df..0dbab7e09a7ce 100644 --- a/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.stderr +++ b/tests/ui/const-generics/gca/type-const-arg-type-mismatch-2.stderr @@ -1,23 +1,23 @@ error[E0271]: type mismatch resolving `ADD1<*b""> == _` - --> $DIR/type-const-arg-type-mismatch-2.rs:8:1 + --> $DIR/type-const-arg-type-mismatch-2.rs:9:1 | LL | type const ONE: usize = ADD1::; | ^^^^^^^^^^^^^^^^^^^^^ types differ error: the constant `*b""` is not of type `usize` - --> $DIR/type-const-arg-type-mismatch-2.rs:8:1 + --> $DIR/type-const-arg-type-mismatch-2.rs:9:1 | LL | type const ONE: usize = ADD1::; | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `[u8; 0]` | note: required by a const generic parameter in `ADD1` - --> $DIR/type-const-arg-type-mismatch-2.rs:7:12 + --> $DIR/type-const-arg-type-mismatch-2.rs:8:12 | LL | const ADD1: usize = N + 1; | ^^^^^^^^^^^^^^ required by this const generic parameter in `ADD1` error: the constant `ADD1::<*b"">` is not of type `usize` - --> $DIR/type-const-arg-type-mismatch-2.rs:8:1 + --> $DIR/type-const-arg-type-mismatch-2.rs:9:1 | LL | type const ONE: usize = ADD1::; | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found a different `usize` diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs index 0107bbc2aae0b..99130689d7ce2 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs @@ -27,6 +27,10 @@ mod v20 { impl v17 { //~^ ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} pub const fn v21() -> v18 { //~^ ERROR cannot find type `v18` in this scope diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index e0faf1e926c0f..022074181cecd 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `v20::v13` - --> $DIR/unevaluated-const-ice-119731.rs:38:15 + --> $DIR/unevaluated-const-ice-119731.rs:42:15 | LL | pub use v20::{v13, v17}; | ^^^ no `v13` in `v20` @@ -32,7 +32,7 @@ LL + pub const fn v21() -> v11 {} | error[E0425]: cannot find type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:31:31 + --> $DIR/unevaluated-const-ice-119731.rs:35:31 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -47,7 +47,7 @@ LL + pub const fn v21() -> v11 { | error[E0422]: cannot find struct, variant or union type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:33:13 + --> $DIR/unevaluated-const-ice-119731.rs:37:13 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -107,6 +107,38 @@ LL | impl v17 { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + --> $DIR/unevaluated-const-ice-119731.rs:28:37 + | +LL | impl v17 { + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + --> $DIR/unevaluated-const-ice-119731.rs:28:37 + | +LL | impl v17 { + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + --> $DIR/unevaluated-const-ice-119731.rs:28:37 + | +LL | impl v17 { + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + --> $DIR/unevaluated-const-ice-119731.rs:28:37 + | +LL | impl v17 { + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0592]: duplicate definitions with name `v21` --> $DIR/unevaluated-const-ice-119731.rs:23:9 | @@ -116,7 +148,7 @@ LL | pub const fn v21() -> v18 {} LL | pub const fn v21() -> v18 { | ------------------------- other definition for `v21` -error: aborting due to 10 previous errors; 2 warnings emitted +error: aborting due to 14 previous errors; 2 warnings emitted Some errors have detailed explanations: E0422, E0425, E0432, E0592. For more information about an error, try `rustc --explain E0422`. diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs index 219b0eac16c0f..3685e71a4808d 100644 --- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs +++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs @@ -10,6 +10,5 @@ trait Trait {} impl Trait for A {} impl Trait for A {} -//~^ ERROR conflicting implementations of trait `Trait` for type `A<_>` pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr index 31bfe88cc8cbd..a3b33fcbe6246 100644 --- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr @@ -6,16 +6,6 @@ LL | struct A; | = note: a builtin type named `u8` exists in another namespace -error[E0119]: conflicting implementations of trait `Trait` for type `A<_>` - --> $DIR/unknown-alias-defkind-anonconst-ice-116710.rs:12:1 - | -LL | impl Trait for A {} - | --------------------------------- first implementation here -LL | -LL | impl Trait for A {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A<_>` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0119, E0423. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0423`. From c9945f1c55c6057748c98483dab897e470f1f4ca Mon Sep 17 00:00:00 2001 From: zedddie Date: Tue, 18 Aug 2026 22:04:52 +0200 Subject: [PATCH 3/4] yet another test --- .../gca/rp-type-const-type-mismatch.rs | 12 +++++++ .../gca/rp-type-const-type-mismatch.stderr | 32 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 tests/ui/const-generics/gca/rp-type-const-type-mismatch.rs create mode 100644 tests/ui/const-generics/gca/rp-type-const-type-mismatch.stderr diff --git a/tests/ui/const-generics/gca/rp-type-const-type-mismatch.rs b/tests/ui/const-generics/gca/rp-type-const-type-mismatch.rs new file mode 100644 index 0000000000000..121cafe8c22d9 --- /dev/null +++ b/tests/ui/const-generics/gca/rp-type-const-type-mismatch.rs @@ -0,0 +1,12 @@ +//! Regression test for . +//@ compile-flags: -Znext-solver=globally +#![feature(generic_const_items,min_generic_const_args)] +#![feature(macroless_generic_const_args, generic_const_args)] +const ADD1: usize = N + 1; +fn a() -> [usize; ADD1::] {} //~ ERROR: type mismatch resolving `ADD1<*b""> == _` [E0271] +//~| ERROR: the type `[usize; ADD1::<*b"">]` is not well-formed +//~| ERROR: mismatched types [E0308] +//~| ERROR: type mismatch resolving `ADD1<*b""> == _` [E0271] + + +fn main() {} diff --git a/tests/ui/const-generics/gca/rp-type-const-type-mismatch.stderr b/tests/ui/const-generics/gca/rp-type-const-type-mismatch.stderr new file mode 100644 index 0000000000000..86ff0f2facccd --- /dev/null +++ b/tests/ui/const-generics/gca/rp-type-const-type-mismatch.stderr @@ -0,0 +1,32 @@ +error[E0271]: type mismatch resolving `ADD1<*b""> == _` + --> $DIR/rp-type-const-type-mismatch.rs:6:11 + | +LL | fn a() -> [usize; ADD1::] {} + | ^^^^^^^^^^^^^^^^^^^^ types differ + +error: the type `[usize; ADD1::<*b"">]` is not well-formed + --> $DIR/rp-type-const-type-mismatch.rs:6:11 + | +LL | fn a() -> [usize; ADD1::] {} + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/rp-type-const-type-mismatch.rs:6:11 + | +LL | fn a() -> [usize; ADD1::] {} + | - ^^^^^^^^^^^^^^^^^^^^ expected `[usize; _]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error[E0271]: type mismatch resolving `ADD1<*b""> == _` + --> $DIR/rp-type-const-type-mismatch.rs:6:11 + | +LL | fn a() -> [usize; ADD1::] {} + | ^^^^^^^^^^^^^^^^^^^^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0271, E0308. +For more information about an error, try `rustc --explain E0271`. From dd0d6e7c88541d35e8ce25d48ceedd58c0fb193a Mon Sep 17 00:00:00 2001 From: zedddie Date: Tue, 18 Aug 2026 22:06:23 +0200 Subject: [PATCH 4/4] use empty param env --- compiler/rustc_middle/src/ty/mod.rs | 5 +++ .../src/solve/eval_ctxt/mod.rs | 34 +++++++++++++++---- .../rustc_next_trait_solver/src/solve/mod.rs | 3 ++ compiler/rustc_type_ir/src/inherent.rs | 8 +++++ 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9b582eeb2c520..121ac0a2f332d 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1046,6 +1046,11 @@ impl<'tcx> rustc_type_ir::inherent::ParamEnv> for ParamEnv<'tcx> { fn caller_bounds(self) -> impl inherent::SliceLike> { self.caller_bounds() } + + #[inline] + fn empty() -> Self { + Self::empty() + } } impl<'tcx> ParamEnv<'tcx> { 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 b9788d49efed8..808bc6374392a 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 @@ -1282,9 +1282,14 @@ 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, returning `(Option, Certainty)`, this returns + // `NoSolution` when concrete const fails to prove well-formedness in empty env. + // + // `(None, Maybe(_))` means we couldn't fully check const's well-formedness, and + // bailed without evaluation. + // + // `(None, Certainty::Yes)` means const is too generic, and doesn't indicate the + // const isn't evaluatable, should be treated as an ambiguity rather than no-solution. pub(super) fn evaluate_const( &mut self, param_env: I::ParamEnv, @@ -1294,12 +1299,27 @@ where match self.opaque_accesses.rerun_always(RerunReason::EvaluateConst)? {} } let cx = self.cx(); - let certainty = if cx.features().generic_const_exprs() { + + // Checking in empty env to be sure const is WF without relying on assumptions from env, + // preventing ill-formed consts from reaching CTFE. + // + // For example without this check const with `[u8]: Sized` bound could get to be evaluated + // in environment with the same assumption, pass and ICE later in CTFE. + let certainty = if alias_const.has_non_region_infer() + || alias_const.has_non_region_param() + || alias_const.has_non_region_placeholders() + { + // Skip proving for not fully concrete consts as they either won't reach CTFE or + // can't depend on generics even if they have them to pass CTFE. Certainty::Yes - } else { + } + // We do this only for GCA consts. Doing this check for GCE introduces cycles with anon + // consts in impl blocks. + else if cx.features().generic_const_args() { + // FIXME(zedddie): we should check this in `fully_monomorphized()` Typing mode. let goal = Goal::new( cx, - param_env, + ParamEnv::empty(), ty::ClauseKind::WellFormed(alias_const.to_const(cx, ty::IsRigid::Yes).into()), ); self.add_goal(GoalSource::AliasWellFormed, goal)?; @@ -1309,6 +1329,8 @@ where return Ok((None, certainty)); } certainty + } else { + Certainty::Yes }; Ok((self.delegate.evaluate_const(param_env, alias_const), certainty)) diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 07c6219203807..ec04732e92eb0 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -212,6 +212,9 @@ where // error in that case is unnecessary noise. This may change in the future once // evaluation failures are allowed to impact selection, e.g. generic const // expressions in impl headers or `where`-clauses. + // + // `evaluate_const` itself can return `NoSolution` if alias' WF doesn't hold in + // empty environment. // FIXME(generic_const_exprs): Implement handling for generic // const expressions here. diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 4776771f5e7f8..97ba6891c7e95 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -619,6 +619,14 @@ pub trait AdtDef: Copy + Debug + Hash + Eq { #[rust_analyzer::prefer_underscore_import] pub trait ParamEnv: Copy + Debug + Hash + Eq + TypeFoldable { fn caller_bounds(self) -> impl SliceLike; + + /// Construct a trait environment suitable for contexts where there are + /// no where-clauses in scope. In the majority of cases it is incorrect + /// to use an empty environment. See the [dev guide section][param_env_guide] + /// for information on what a `ParamEnv` is and how to acquire one. + /// + /// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html + fn empty() -> Self; } #[rust_analyzer::prefer_underscore_import]