diff options
| author | Matthias Krüger <476013+matthiaskrgr@users.noreply.github.com> | 2025-06-27 22:13:03 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-27 22:13:03 +0200 |
| commit | 9108907a18d9b9ac46e361cced0fbfca6252f170 (patch) | |
| tree | 284d896275a3b2ceb1a211546997924c7147d337 | |
| parent | 190a1a7f747408d1936a81065665c687013f6141 (diff) | |
| parent | 87c8aa1ff6f320241e4161324946c1e23bc1617c (diff) | |
| download | rust-9108907a18d9b9ac46e361cced0fbfca6252f170.tar.gz rust-9108907a18d9b9ac46e361cced0fbfca6252f170.zip | |
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`
3 files changed, 29 insertions, 0 deletions
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 4f845ef9cd9..e68ea22c7a2 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -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(_) => { diff --git a/tests/ui/consts/normalize-before-const-arg-has-type-goal.rs b/tests/ui/consts/normalize-before-const-arg-has-type-goal.rs new file mode 100644 index 00000000000..9caa3c9e214 --- /dev/null +++ b/tests/ui/consts/normalize-before-const-arg-has-type-goal.rs @@ -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() {} diff --git a/tests/ui/consts/normalize-before-const-arg-has-type-goal.stderr b/tests/ui/consts/normalize-before-const-arg-has-type-goal.stderr new file mode 100644 index 00000000000..a53231846b7 --- /dev/null +++ b/tests/ui/consts/normalize-before-const-arg-has-type-goal.stderr @@ -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`. |
