Repository: rust
Issue: Rust compiler hangs when compiling code with zip-related benchmarks
Labels: I-compiletime,C-bug

<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating the bug.
-->

I tried this code:
# Command
```sh
rustc -C opt-level=0  /home/interesting/hang_10.rs
```
# Code
```rust
#![allow(dead_code)]
#![feature(array_zip, maybe_uninit_array_assume_init, maybe_uninit_uninit_array)]
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rand::{rngs::OsRng, Rng};
use std::mem::MaybeUninit;
macro_rules! defbenches {
    ($c:ident, $fn:path, $intype:ty, [$($len:literal),+$(,)?]) => {{
        $(defbenches!(@ops $c, $fn, $intype, $len);)+
    }};
    (@ops $c:ident, $fn:path, $intype:ty, $len:literal) => {{
        let a: [$intype; $len] = OsRng.gen();
        let b: [$intype; $len] = OsRng.gen();
        defbenches!(@final $c, $fn, $intype, $len, +, a, b);
        defbenches!(@final $c, $fn, $intype, $len, -, a, b);
        defbenches!(@final $c, $fn, $intype, $len, *, a, b);
        defbenches!(@final $c, $fn, $intype, $len, &, a, b);
        defbenches!(@final $c, $fn, $intype, $len, |, a, b);
        defbenches!(@final $c, $fn, $intype, $len, ^, a, b);
    }};
    (@final $c:ident, $fn:path, $intype:ty, $len:literal, $op:tt, $a:ident, $b:ident) => {{
        $c.bench_function(

            || black_box($fn($a, $b, |a, b| a $op b)),
            || black_box($fn($a, $b, |a, b| b $op a)),
            || black_box($fn($a, $b, |a, b| a $op b)),
            || black_box($fn($a, $b, |a, b| b $op a)),
            || black_box($fn($a, $b, |a, b| a $op b)),
            || black_box($fn($a, $b, |a, b| b $op a)),
            || black_box($fn($a, $b, |a, b| a $op b)),
            || black_box($fn($a, $b, |a, b| b $op a)),
            || black_box($fn($a, $b, |a, b| a $op b)),
            || black_box($fn($a, $b, |a, b| b $op a)),
            || black_box($fn($a, $b, |a, b| a $op b)),
            || black_box($fn($a, $b, |a, b| b $op a)),
            || black_box($fn($a, $b, |a, b| a $op b)),
            || black_box($fn($a, $b, |a, b| b $op a)),
            || black_box($fn($a, $b, |a, b| a $op b)),

            |b| {
                b.iter(|| black_box($fn($a, $b, |a, b| a $op b)));
            },
        );
    }};
}
fn benchmark_primitives(c: &mut Criterion) {
    defbenches!(c, zip_with, u8, [8, 16, 32, 64, 128]);
    defbenches!(c, zip_map_std, u8, [8, 16, 32, 64, 128]);
    defbenches!(c, zip_map_fl, u8, [8, 16, 32, 64, 128]);
    defbenches!(c, zip_with, u16, [8, 16, 32, 64, 128, 256, 512]);
    defbenches!(c, zip_map_std, u16, [8, 16, 32, 64, 128, 256, 512]);
    defbenches!(c, zip_map_fl, u16, [8, 16, 32, 64, 128, 256, 512]);
    defbenches!(c, zip_with, u32, [8, 16, 32, 64, 128, 256, 512]);
    defbenches!(c, zip_map_std, u32, [8, 16, 32, 64, 128, 256, 512]);
    defbenches!(c, zip_map_fl, u32, [8, 16, 32, 64, 128, 256, 512]);
    defbenches!(c, zip_with, u64, [8, 16, 32, 64, 128, 256, 512]);
    defbenches!(c, zip_map_std, u64, [8, 16, 32, 64, 128, 256, 512]);
    defbenches!(c, zip_map_fl, u64, [8, 16, 32, 64, 128, 256, 512]);
}
struct ZipWithGuard<T, U, const N: usize> {
    a: *mut [T; N],
    b: *mut [U; N],
    moved: usize,
}
impl<T, U, const N: usize> Drop for ZipWithGuard<T, U, N> {
    fn drop(&mut self) {
        if needs_drop::<T>() || needs_drop::<U>() {
            for i in self.moved + 1..N {
                unsafe {
                    drop(self.a.cast::<T>().add(i).read());
                    drop(self.b.cast::<U>().add(i).read());
                }
            }
        }
    }
}
pub fn zip_with<T, U, V, F: FnMut(T, U) -> V, const N: usize>(
    a: [T; N],
    b: [U; N],
    mut f: F,
) -> [V; N] {
    let aref = &a as *const _ as *mut [ManuallyDrop<T>; N];
    forget(a);
    let bref = &b as *const _ as *mut [ManuallyDrop<U>; N];
    forget(b);
    let mut guard = ZipWithGuard {
        a: aref,
        b: bref,
        moved: 0,
    };
    let mut out: MaybeUninit<[V; N]> = unsafe { MaybeUninit::uninit().assume_init() };
    let out_ptr = out.as_mut_ptr().cast::<MaybeUninit<V>>();
    while guard.moved < N {
        let i = guard.moved;
        unsafe {
            *out_ptr.add(i) = MaybeUninit::new(f(
                guard.a.cast::<T>().add(i).read(),
                guard.b.cast::<U>().add(i).read(),
            ));
        }
        guard.moved += 1;
    }
    unsafe { out.assume_init() }
}
fn zip_map_fl<T: Copy, U: Copy, V, F: FnMut(T, U) -> V, const N: usize>(
    a: [T; N],
    b: [U; N],
    mut f: F,
) -> [V; N] {
    let mut out: [MaybeUninit<V>; N] = MaybeUninit::uninit_array();
    for i in 0..N {
        out[i] = MaybeUninit::new(f(a[i], b[i]));
    }
    unsafe { MaybeUninit::array_assume_init(out) }
}
fn zip_map_std<T, U, V, F: Fn(T, U) -> V, const N: usize>(a: [T; N], b: [U; N], f: F) -> [V; N] {
    a.zip(b).map(|(a, b)| f(a, b))
}
criterion_group! {
    name = benches;
    config = Criterion::default();
    targets = benchmark_primitives
}
criterion_main! {
    benches
}

```

I expected to see this happen: *The compiler compiles successfully or outputs an error message.*

Instead, this happened: *The code, as provided below, appears to encounter a hang*

### Meta
<!--
If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions.
-->

`rustc --version --verbose`:
```
rustc 1.73.0 (cc66ad468 2023-10-03)
binary: rustc
commit-hash: cc66ad468955717ab92600c770da8c1601a4ff33
commit-date: 2023-10-03
host: x86_64-unknown-linux-gnu
release: 1.73.0
LLVM version: 17.0.2
```
The same problem is reproduced on the nightly version(1.75.0-nightly (d627cf07c 2023-10-10)) as well. (and `-Ztrait-solver=next` cannot solve it)
what's more, to get more information,I also tried '-Z time-passes' (using nighly version):

```sh
$ rustc  -C opt-level=0 -Ztime-passes -Ztrait-solver=next /home/interesting/hang_10.rs
time:   0.002; rss:   30MB ->   32MB (   +2MB)  parse_crate
time:   0.000; rss:   35MB ->   35MB (   +1MB)  setup_global_ctxt
time:   0.072; rss:   35MB ->   75MB (  +40MB)  expand_crate
time:   0.072; rss:   35MB ->   75MB (  +40MB)  macro_expand_crate
error[E0433]: failed to resolve: maybe a missing crate `rand`?
 --> /home/interesting/hang_10.rs:4:5
  |
4 | use rand::{rngs::OsRng, Rng};
  |     ^^^^ maybe a missing crate `rand`?
  |
  = help: consider adding `extern crate rand` to use the `rand` crate

error[E0432]: unresolved import `criterion`
 --> /home/interesting/hang_10.rs:3:5
  |
3 | use criterion::{black_box, criterion_group, criterion_main, Criterion};
  |     ^^^^^^^^^ maybe a missing crate `criterion`?
  |
  = help: consider adding `extern crate criterion` to use the `criterion` crate

error[E0432]: unresolved import `rand`
 --> /home/interesting/hang_10.rs:4:5
  |
4 | use rand::{rngs::OsRng, Rng};
  |     ^^^^ maybe a missing crate `rand`?
  |
  = help: consider adding `extern crate rand` to use the `rand` crate

time:   0.010; rss:   75MB ->   90MB (  +15MB)  finalize_imports
error: cannot determine resolution for the macro `criterion_group`
   --> /home/interesting/hang_10.rs:118:1
    |
118 | criterion_group! {
    | ^^^^^^^^^^^^^^^
    |
    = note: import resolution is stuck, try simplifying macro imports

error: cannot determine resolution for the macro `criterion_main`
   --> /home/interesting/hang_10.rs:123:1
    |
123 | criterion_main! {
    | ^^^^^^^^^^^^^^
    |
    = note: import resolution is stuck, try simplifying macro imports

time:   0.004; rss:   90MB ->   94MB (   +4MB)  finalize_macro_resolutions
time:   0.038; rss:   94MB ->  103MB (   +9MB)  late_resolve_crate
error[E0425]: cannot find function `needs_drop` in this scope
  --> /home/interesting/hang_10.rs:66:12
   |
66 |         if needs_drop::<T>() || needs_drop::<U>() {
   |            ^^^^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
3  + use std::mem::needs_drop;
   |

error[E0425]: cannot find function `needs_drop` in this scope
  --> /home/interesting/hang_10.rs:66:33
   |
66 |         if needs_drop::<T>() || needs_drop::<U>() {
   |                                 ^^^^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
3  + use std::mem::needs_drop;
   |

error[E0412]: cannot find type `ManuallyDrop` in this scope
  --> /home/interesting/hang_10.rs:81:40
   |
81 |     let aref = &a as *const _ as *mut [ManuallyDrop<T>; N];
   |                                        ^^^^^^^^^^^^ not found in this scope
   |
help: consider importing this struct
   |
3  + use std::mem::ManuallyDrop;
   |

error[E0425]: cannot find function `forget` in this scope
  --> /home/interesting/hang_10.rs:82:5
   |
82 |     forget(a);
   |     ^^^^^^ not found in this scope
   |
help: consider importing this function
   |
3  + use std::mem::forget;
   |

error[E0412]: cannot find type `ManuallyDrop` in this scope
  --> /home/interesting/hang_10.rs:83:40
   |
83 |     let bref = &b as *const _ as *mut [ManuallyDrop<U>; N];
   |                                        ^^^^^^^^^^^^ not found in this scope
   |
help: consider importing this struct
   |
3  + use std::mem::ManuallyDrop;
   |

error[E0425]: cannot find function `forget` in this scope
  --> /home/interesting/hang_10.rs:84:5
   |
84 |     forget(b);
   |     ^^^^^^ not found in this scope
   |
help: consider importing this function
   |
3  + use std::mem::forget;
   |

time:   0.060; rss:   75MB ->  103MB (  +27MB)  resolve_crate
time:   0.008; rss:  124MB ->  124MB (   +0MB)  drop_ast
error[E0601]: `main` function not found in crate `hang_10`
   --> /home/interesting/hang_10.rs:125:2
    |
125 | }
    |  ^ consider adding a `main` function to `/home/interesting/hang_10.rs`

time:   0.080; rss:  103MB ->  124MB (  +21MB)  looking_for_entry_point
error[E0635]: unknown feature `array_zip`
 --> /home/interesting/hang_10.rs:2:12
  |
2 | #![feature(array_zip, maybe_uninit_array_assume_init, maybe_uninit_uninit_array)]
  |            ^^^^^^^^^

time:   0.106; rss:  103MB ->  124MB (  +21MB)  misc_checking_1
time:   0.024; rss:  124MB ->  127MB (   +3MB)  type_collecting
time:   0.002; rss:  127MB ->  130MB (   +3MB)  wf_checking
```
<!--
Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your
environment. E.g. `RUST_BACKTRACE=1 cargo build`.
-->
<details><summary>Backtrace</summary>
<p>

```
<backtrace>
```

</p>
</details>