mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 17:24:06 +00:00
037b27430b
Unions cannot have unsized fields, and as such, layout computation for unions asserts that each union field is sized (as this would normally have halted compilation earlier). However, if a generator ends up with an unsized local - a circumstance in which an error will always have been emitted earlier, for example, if attempting to dereference a `&str` - then the generator transform will produce a union with an unsized field. Since #110107, later passes will be run, such as constant propagation, and can attempt layout computation on the generator, which will result in layout computation of `str` in the context of it being a field of a union - and so the aforementioned assertion would cause an ICE. It didn't seem appropriate to try and detect this case in the MIR body and skip this specific pass; tainting the MIR body or delaying a bug from the generator transform (or elsewhere) wouldn't prevent this either (as neither would prevent the later pass from running); and tainting when the deref of `&str` is reported, if that's possible, would unnecessarily prevent potential other errors from being reported later in compilation, and is very tailored to this specific case of getting a unsized type in a generator. Given that this circumstance can only happen when an error should have already been reported, the correct fix appears to be just changing the assert to a delayed bug. This will still assert if there is some circumstance where this occurs and no error has been reported, but it won't crash the compiler in this instance. Signed-off-by: David Wood <david@davidtw.co>
28 lines
981 B
Rust
28 lines
981 B
Rust
#![feature(generators)]
|
|
|
|
// `foo` attempts to dereference `""`, which results in an error being reported. Later, the
|
|
// generator transform for `foo` then produces a union which contains a `str` type - unions should
|
|
// not contain unsized types, but this is okay because an error has been reported already.
|
|
// When const propagation happens later in compilation, it attempts to compute the layout of the
|
|
// generator (as part of checking whether something can be const propagated) and in turn attempts
|
|
// to compute the layout of `str` in the context of a union - where this caused an ICE. This test
|
|
// makes sure that doesn't happen again.
|
|
|
|
fn foo() {
|
|
let _y = static || {
|
|
let x = &mut 0;
|
|
*{
|
|
yield;
|
|
x
|
|
} += match { *"" }.len() {
|
|
//~^ ERROR cannot move a value of type `str` [E0161]
|
|
//~^^ ERROR cannot move out of a shared reference [E0507]
|
|
_ => 0,
|
|
};
|
|
};
|
|
}
|
|
|
|
fn main() {
|
|
foo()
|
|
}
|