Rollup merge of #142806 - compiler-errors:norm-ct-has-ty, r=lcnr,BoxyUwU

Normalize before computing ConstArgHasType goal in new solver

This is a fix for rust-lang/rust#139905. See the description I left in the test.

I chose to fix this by normalizing the type before matching on its `.kind()` in `compute_const_arg_has_type_goal` (since it feels somewhat consistent with how we normalize types before assembling their candidates, for example); however, there are several other solutions that come to mind for fixing this ICE:
1. (this solution)
2. Giving `ConstKind::Error` a proper type, like `ConstKind::Value`, so that consts don't go from failing to passing `ConstArgHasType` goals after normalization (i.e. `UNEVALUATED` would normalize into a `ConstKind::Error(_, bool)` type rather than losing its type altogether).
3. Just suppressing the errors and accepting the fact that goals can go from fail->pass after normalization.

Thoughts? Happy to discuss this fix further.

r? `@BoxyUwU`
This commit is contained in:
Matthias Krüger 2025-06-27 22:13:03 +02:00 committed by GitHub
commit 9108907a18
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 29 additions and 0 deletions

View file

@ -191,6 +191,7 @@ where
goal: Goal<I, (I::Const, I::Ty)>,
) -> QueryResult<I> {
let (ct, ty) = goal.predicate;
let ct = self.structurally_normalize_const(goal.param_env, ct)?;
let ct_ty = match ct.kind() {
ty::ConstKind::Infer(_) => {

View file

@ -0,0 +1,19 @@
trait A<const B: bool> {}
// vv- Let's call this const "UNEVALUATED" for the comment below.
impl A<{}> for () {}
//~^ ERROR mismatched types
// During overlap check, we end up trying to prove `(): A<?0c>`. Inference guides
// `?0c = UNEVALUATED` (which is the `{}` const in the erroneous impl). We then
// fail to prove `ConstArgHasType<UNEVALUATED, u8>` since `UNEVALUATED` has the
// type `bool` from the type_of query. We then deeply normalize the predicate for
// error reporting, which ends up normalizing `UNEVALUATED` to a ConstKind::Error.
// This ended up ICEing when trying to report an error for the `ConstArgHasType`
// predicate, since we don't expect `ConstArgHasType(ERROR, Ty)` to ever fail.
trait C<const D: u8> {}
impl<const D: u8> C<D> for () where (): A<D> {}
impl<const D: u8> C<D> for () {}
fn main() {}

View file

@ -0,0 +1,9 @@
error[E0308]: mismatched types
--> $DIR/normalize-before-const-arg-has-type-goal.rs:4:8
|
LL | impl A<{}> for () {}
| ^^ expected `bool`, found `()`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.