rust-lang / rust-lang/rust

1 million item array spends inordinate time on error path of typechecking

Open
#137,678 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-diagnostics I-compiletime T-compiler T-types
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code

(The actual data is for indices in a 100³ gilbert curve but isn't relevant here.)

$ { echo '['; seq $(( 100 * 100 * 100 )) | sed 's/.*/(0,0,0),/'; echo ']'; } > 100.rs
const GRID_SIZE: usize = 100;
static GRID_GILBERT: [(u8,u8,u8); GRID_SIZE*GRID_SIZE*GRID_SIZE] = include!("100.rs");
fn main() {}

this is the good state

$ time rustc bugowcy.rs
warning: constant `GRID_SIZE` is never used
 --> bugowcy.rs:1:7
  |
1 | const GRID_SIZE: usize = 100;
  |       ^^^^^^^^^
  |
  = note: `#[warn(dead_code)]` on by default

warning: static `GRID_GILBERT` is never used
 --> bugowcy.rs:2:8
  |
2 | static GRID_GILBERT: [(u8,u8,u8); GRID_SIZE*GRID_SIZE*GRID_SIZE] = include!("100.rs");
  |        ^^^^^^^^^^^^

warning: 2 warnings emitted


real    0m32.666s
user    0m0.031s
sys     0m0.015s

Change line 2 to

static GRID_GILBERT: &[(u8,u8,u8)] = include!("100.rs");

to trigger

$ time rustc bugowcy.rs
error[E0308]: mismatched types
       --> 100.rs:1:1
        |
1       | / [
2       | | (0,0,0),
3       | | (0,0,0),
4       | | (0,0,0),
...       |
1000001 | | (0,0,0),
1000002 | | ]
        | |_^ expected `&[(u8, u8, u8)]`, found `[({integer}, {integer}, {integer}); 1000000]`
        |
        = note: expected reference `&'static [(u8, u8, u8)]`
                       found array `[({integer}, {integer}, {integer}); 1000000]`
help: consider borrowing here
        |
1       | &[
        | +

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.

real    2m12.583s
user    0m0.000s
sys     0m0.000s
Current output
$ time cargo build -r
warning: `D:\Users\nabijaczleweli\.cargo\config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
warning: no edition set: defaulting to the 2015 edition while the latest is 2021
   Compiling posteriser v0.0.0 (P:\Rust\posteriser)
error[E0308]: mismatched types
       --> src\../gilbert/100.rs:1:1
        |
1       | / [
2       | | (0,0,0),
3       | | (0,1,0),
4       | | (0,1,1),
...       |
1000001 | | (99,0,0),
1000002 | | ]
        | |_^ expected `&[(u8, u8, u8)]`, found `[(..., ..., ...); 1000000]`
        |
        = note: expected reference `&'static [(u8, u8, u8)]`
                       found array `[({integer}, {integer}, {integer}); 1000000]`
help: consider borrowing here
        |
1       | &[
        | +

error[E0277]: `&&[(u8, u8, u8)]` is not an iterator
   --> src\posterise_gpu.rs:825:30
    |
825 |             for (x, y, z) in &GRID_GILBERT {
    |                              ^^^^^^^^^^^^^ `&&[(u8, u8, u8)]` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `&&[(u8, u8, u8)]`
    = note: required for `&&[(u8, u8, u8)]` to implement `IntoIterator`
help: consider removing the leading `&`-reference
    |
825 -             for (x, y, z) in &GRID_GILBERT {
825 +             for (x, y, z) in GRID_GILBERT {
    |

real 2m14s


The base speed of a full build is 42s.
Desired output
$ time cargo build -r
warning: `D:\Users\nabijaczleweli\.cargo\config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
warning: no edition set: defaulting to the 2015 edition while the latest is 2021
   Compiling posteriser v0.0.0 (P:\Rust\posteriser)
error[E0308]: mismatched types
       --> src\../gilbert/100.rs:1:1
        | expected `&[(u8, u8, u8)]`, found `[(..., ..., ...); 1000000]`
        |
        = note: expected reference `&'static [(u8, u8, u8)]`
                       found array `[({integer}, {integer}, {integer}); 1000000]`

error[E0277]: `&&[(u8, u8, u8)]` is not an iterator
   --> src\posterise_gpu.rs:825:30
    |
825 |             for (x, y, z) in &GRID_GILBERT {
    |                              ^^^^^^^^^^^^^ `&&[(u8, u8, u8)]` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `&&[(u8, u8, u8)]`
    = note: required for `&&[(u8, u8, u8)]` to implement `IntoIterator`
help: consider removing the leading `&`-reference
    |
825 -             for (x, y, z) in &GRID_GILBERT {
825 +             for (x, y, z) in GRID_GILBERT {
    |

real <40s
Rationale and extra context

I think in this case (and in general) having rustc churn for two full minutes is. Not good. And value to the user is bigger when you get the error without source-level diagnostics.

Rust Version
$ rustc --version --verbose
rustc 1.84.1 (e71f9a9a9 2025-01-27)
binary: rustc
commit-hash: e71f9a9a98b0faf423844bf0ba7438f29dc27d58
commit-date: 2025-01-27
host: x86_64-pc-windows-gnu
release: 1.84.1
LLVM version: 19.1.5

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the report with the one-million-item array in 100.rs or bugowcy.rs, then compare rustc bugowcy.rs and cargo build -r; the affected project location is src/posterise_gpu.rs:825. Trace the typechecking and diagnostic path responsible for the two-minute delay. Done means the same errors are reported without the large source-level diagnostic and the build returns in under 40 seconds.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.