about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform/src/coverage/graph.rs
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2025-02-22 01:01:42 +0100
committerGitHub <noreply@github.com>2025-02-22 01:01:42 +0100
commit63520442697e523ca2834a5ad81102a1db59c832 (patch)
tree06da38443eb89bca59eb35ba38af1aee8d7e9290 /compiler/rustc_mir_transform/src/coverage/graph.rs
parentfa62fbe4b804a7d814d6e9629e0275a4e1d3843f (diff)
parent7fea935ec5e2e5ab7f0c86e3b4f89c0da8d646c6 (diff)
downloadrust-63520442697e523ca2834a5ad81102a1db59c832.tar.gz
rust-63520442697e523ca2834a5ad81102a1db59c832.zip
Rollup merge of #137399 - lukas-code:oopsie-woopsie, r=compiler-errors
fix ICE in layout computation with unnormalizable const

The first commit reverts half of 7a667d206c45b96676c260030a4e3d9be1cc8495, where I removed a case from `layout_of` for handling non-generic unevaluated consts in array length, that I incorrectly assumed to be unreachable. This can actually happen with the combination of `feature(generic_const_exprs)` and `feature(trivial_bounds)`, because GCE makes anon consts inherit their parent's predicates and with an impossible predicate like `u8: A` it's possible to have an array whose length is an associated const like `<u8 as A>::B` that is not generic, but also can't be normalized:

```rust
#![feature(generic_const_exprs)]
#![feature(trivial_bounds)]

trait A {
    const B: usize;
}

// With GCE + trivial bounds this definition is not a compile error.
// Computing the layout of this type shouldn't ICE.
struct S([u8; <u8 as A>::B])
where
    u8: A;
```

---

The first commit also incidentally fixes https://github.com/rust-lang/rust/issues/137308, which also managed to get an unnormalizable assoc const into an array length:

```rust
trait A {
    const B: usize;
}

impl<C: ?Sized> A for u8 { //~ ERROR: the type parameter `C` is not constrained
    const B: usize = 42;
}

// Computing the layout of this type shouldn't ICE, even with the compile error above.
struct S([u8; <u8 as A>::B]);
```

This happens, because we bail out from `codegen_select_candidate` with an error if the selected impl has unconstrained params to avoid leaking infer vars out of a query. `Instance::try_resolve` will then return `Ok(None)`, which for assoc consts roughly means "this const can't be evaluated in a generic context" and is treated as such: https://github.com/rust-lang/rust/blob/71e06b9c59d6af50fdc55aed75620493d29baf98/compiler/rustc_middle/src/mir/interpret/queries.rs#L84 (and this can ICE if the const isn't generic: https://github.com/rust-lang/rust/issues/135617).

However, here `<u8 as A>::B` is definitely not "too generic" and also not unresolvable due to an unsatisfiable `u8: A` bound, so I've included the second commit to change the result of `Instance::try_resolve` from `Ok(None)` to `Err(ErrorGuaranteed)` when resolving an assoc item to an impl with unconstrained generic params. This has the effect that `<u8 as A>::B` will now be normalized to `ConstKind::Error` in the example above.

This properly fixes https://github.com/rust-lang/rust/issues/137308, by no longer treating `<u8 as A>::B` as unresolvable even though it clearly has a unique impl that it resolves to. It also has the effect of changing the layout error from `Unknown` ("the type may be valid but has no sensible layout") to `ReferencesError` ("a non-layout error is reported elsewhere") which seems more appropriate.

r? ```@compiler-errors```
Diffstat (limited to 'compiler/rustc_mir_transform/src/coverage/graph.rs')
0 files changed, 0 insertions, 0 deletions