From 942fe2a3b4fed590cbf139549d4b86b803efc24c Mon Sep 17 00:00:00 2001 From: Ryan Leckey Date: Mon, 3 Aug 2026 12:59:37 -0700 Subject: [PATCH] Prove nested goals before const evaluation Const evaluation instantiates the item's body with its arguments, so an argument whose type does not match its parameter produced ill-formed MIR and ICEd the interpreter instead of the ConstArgHasType goal reporting the mismatch. --- .../src/solve/eval_ctxt/mod.rs | 8 ++ .../gca/mismatched-const-arg-type.rs | 55 +++++++++ .../gca/mismatched-const-arg-type.stderr | 111 ++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 tests/ui/const-generics/gca/mismatched-const-arg-type.rs create mode 100644 tests/ui/const-generics/gca/mismatched-const-arg-type.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 004d1df069d6e..f632481f24226 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 @@ -1405,6 +1405,14 @@ where expected_term: I::Term, alias_const: ty::AliasConst, ) -> QueryResultOrRerunNonErased { + // Evaluation instantiates the constant's body with its arguments. An argument whose + // type does not match its parameter makes that body ill-formed, which CTFE cannot run. + self.try_evaluate_added_goals().inspect_err(|_| { + // Without recording the response here we attribute the error to this goal rather + // than to the nested goal which actually failed. + self.inspect.make_canonical_response(Certainty::Yes); + })?; + match self.evaluate_const(param_env, alias_const)? { Some(evaluated) => { self.eq(param_env, expected_term, evaluated.into())?; diff --git a/tests/ui/const-generics/gca/mismatched-const-arg-type.rs b/tests/ui/const-generics/gca/mismatched-const-arg-type.rs new file mode 100644 index 0000000000000..063f207fecb71 --- /dev/null +++ b/tests/ui/const-generics/gca/mismatched-const-arg-type.rs @@ -0,0 +1,55 @@ +//! Regression test for . + +//@ compile-flags: -Znext-solver + +#![feature( + generic_const_args, + generic_const_items, + macroless_generic_const_args, + min_generic_const_args +)] +#![expect(incomplete_features)] + +const F: f64 = 1.0; + +const ADD1: usize = N + 1; + +const IGNORE: usize = 0; + +trait Tr { + const C: usize; +} + +impl Tr for () { + const C: usize = N + 1; +} + +fn main() { + let _: [(); ADD1::<1f64>]; + //~^ ERROR: the constant `1f64` is not of type `usize` + //~| ERROR: is not well-formed + let _: [(); ADD1::<1u8>]; + //~^ ERROR: the constant `1` is not of type `usize` + //~| ERROR: is not well-formed + let _: [(); ADD1::<1i32>]; + //~^ ERROR: the constant `1` is not of type `usize` + //~| ERROR: is not well-formed + let _: [(); ADD1::]; + //~^ ERROR: the constant `true` is not of type `usize` + //~| ERROR: is not well-formed + let _: [(); ADD1::<'a'>]; + //~^ ERROR: the constant `'a'` is not of type `usize` + //~| ERROR: is not well-formed + let _: [(); ADD1::<"s">]; + //~^ ERROR: the constant `"s"` is not of type `usize` + //~| ERROR: is not well-formed + let _: [(); ADD1::]; + //~^ ERROR: the constant `1f64` is not of type `usize` + //~| ERROR: is not well-formed + let _: [(); IGNORE::<1f64>]; + //~^ ERROR: the constant `1f64` is not of type `usize` + //~| ERROR: is not well-formed + let _: [(); <() as Tr>::C::<1f64>]; + //~^ ERROR: type mismatch resolving `<() as Tr>::C<1f64> == _` + //~| ERROR: is not well-formed +} diff --git a/tests/ui/const-generics/gca/mismatched-const-arg-type.stderr b/tests/ui/const-generics/gca/mismatched-const-arg-type.stderr new file mode 100644 index 0000000000000..5b1cbd2b9d8e1 --- /dev/null +++ b/tests/ui/const-generics/gca/mismatched-const-arg-type.stderr @@ -0,0 +1,111 @@ +error: the constant `1f64` is not of type `usize` + --> $DIR/mismatched-const-arg-type.rs:28:12 + | +LL | let _: [(); ADD1::<1f64>]; + | ^^^^^^^^^^^^^^^^^^ expected `usize`, found `f64` + +error: the constant `1` is not of type `usize` + --> $DIR/mismatched-const-arg-type.rs:31:12 + | +LL | let _: [(); ADD1::<1u8>]; + | ^^^^^^^^^^^^^^^^^ expected `usize`, found `u8` + +error: the constant `1` is not of type `usize` + --> $DIR/mismatched-const-arg-type.rs:34:12 + | +LL | let _: [(); ADD1::<1i32>]; + | ^^^^^^^^^^^^^^^^^^ expected `usize`, found `i32` + +error: the constant `true` is not of type `usize` + --> $DIR/mismatched-const-arg-type.rs:37:12 + | +LL | let _: [(); ADD1::]; + | ^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + +error: the constant `'a'` is not of type `usize` + --> $DIR/mismatched-const-arg-type.rs:40:12 + | +LL | let _: [(); ADD1::<'a'>]; + | ^^^^^^^^^^^^^^^^^ expected `usize`, found `char` + +error: the constant `"s"` is not of type `usize` + --> $DIR/mismatched-const-arg-type.rs:43:12 + | +LL | let _: [(); ADD1::<"s">]; + | ^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error: the constant `1f64` is not of type `usize` + --> $DIR/mismatched-const-arg-type.rs:46:12 + | +LL | let _: [(); ADD1::]; + | ^^^^^^^^^^^^^^^ expected `usize`, found `f64` + +error: the constant `1f64` is not of type `usize` + --> $DIR/mismatched-const-arg-type.rs:49:12 + | +LL | let _: [(); IGNORE::<1f64>]; + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `f64` + +error[E0271]: type mismatch resolving `<() as Tr>::C<1f64> == _` + --> $DIR/mismatched-const-arg-type.rs:52:12 + | +LL | let _: [(); <() as Tr>::C::<1f64>]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: the type `[(); ADD1::<1f64>]` is not well-formed + --> $DIR/mismatched-const-arg-type.rs:28:12 + | +LL | let _: [(); ADD1::<1f64>]; + | ^^^^^^^^^^^^^^^^^^ + +error: the type `[(); ADD1::<1>]` is not well-formed + --> $DIR/mismatched-const-arg-type.rs:31:12 + | +LL | let _: [(); ADD1::<1u8>]; + | ^^^^^^^^^^^^^^^^^ + +error: the type `[(); ADD1::<1>]` is not well-formed + --> $DIR/mismatched-const-arg-type.rs:34:12 + | +LL | let _: [(); ADD1::<1i32>]; + | ^^^^^^^^^^^^^^^^^^ + +error: the type `[(); ADD1::]` is not well-formed + --> $DIR/mismatched-const-arg-type.rs:37:12 + | +LL | let _: [(); ADD1::]; + | ^^^^^^^^^^^^^^^^^^ + +error: the type `[(); ADD1::<'a'>]` is not well-formed + --> $DIR/mismatched-const-arg-type.rs:40:12 + | +LL | let _: [(); ADD1::<'a'>]; + | ^^^^^^^^^^^^^^^^^ + +error: the type `[(); ADD1::<"s">]` is not well-formed + --> $DIR/mismatched-const-arg-type.rs:43:12 + | +LL | let _: [(); ADD1::<"s">]; + | ^^^^^^^^^^^^^^^^^ + +error: the type `[(); ADD1::<1f64>]` is not well-formed + --> $DIR/mismatched-const-arg-type.rs:46:12 + | +LL | let _: [(); ADD1::]; + | ^^^^^^^^^^^^^^^ + +error: the type `[(); IGNORE::<1f64>]` is not well-formed + --> $DIR/mismatched-const-arg-type.rs:49:12 + | +LL | let _: [(); IGNORE::<1f64>]; + | ^^^^^^^^^^^^^^^^^^^^ + +error: the type `[(); <() as Tr>::C::<1f64>]` is not well-formed + --> $DIR/mismatched-const-arg-type.rs:52:12 + | +LL | let _: [(); <() as Tr>::C::<1f64>]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 18 previous errors + +For more information about this error, try `rustc --explain E0271`.