Skip to content

Arithmetic operations with inferred variables take quadratic time to type-check #25916

Closed
@huonw

Description

@huonw

This takes ~2 seconds to type check (according to -Z time-passes):

fn main() {
    macro_rules! f {
        () => { 0 + 0 }
    }
    // 16 per line
    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();

    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();

    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();

    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
}

Doubling (respectively, halving) the number of f!() invocations multiplies (resp. divides) the time by 4.

It applies to arithmetic in consts/statics too which is, I imagine, where this will occur most often in practice (it's how I found it).

Observations:

  • for +, -, * and /, annotating either side (e.g. 0 + 0u8) or both sides makes it take only 0.03s and behave linearly (AFAICT)
  • for << and >>:
    • annotating the LHS (0u8 >> 0) reduces the time to ~1.5s,
    • annotating the RHS (0 >> 0u8) reduces it to ~1.1s but both are still quadratic,
    • annotating both takes it to 0.04s and linear
  • it seems to only be dependent on the number of operations in a single function/item, separating the 4 big chunks above across 4 functions reduces the time to ~0.5s.
  • there's no significant difference between using the macro or writing the operations inline (I only use f! to allow easier experimentation)

cc @rust-lang/compiler

Metadata

Metadata

Assignees

No one assigned

    Labels

    I-compiletimeIssue: Problems and improvements with respect to compile times.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions