Skip to content

Exponential compile time with recursive opaque type #87450

Closed
@Skepfyr

Description

@Skepfyr

Code

I tried this code:

fn bar() -> impl Fn() {
    wrap(wrap(wrap(wrap(foo()))))
}

fn foo() -> impl Fn() {
    wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
}

fn wrap(f: impl Fn()) -> impl Fn() {
    move || f()
}

I expected running cargo check to produce an error like:

error[E0720]: cannot resolve opaque type
 --> src/lib.rs:5:13
  |
5 | fn foo() -> impl Fn() {
  |             ^^^^^^^^^ recursive opaque type
6 |     ((wrap(wrap(wrap(wrap(wrap(foo())))))))
  |     --------------------------------------- returning here with type `impl Fn<()>`
...
9 | fn wrap(f: impl Fn()) -> impl Fn() {
  |                          --------- returning this opaque type `impl Fn<()>`

It does, but cargo check takes time exponential in the number of wrap calls, although doesn't appear to use any extra memory.
In foo the time take looks like:

Num wrapss Time taken (s)
4 0.5
5 2.1
6 28
7 436

I believe it's also exponential in the number of wrap calls in bar.

The reason I had code like this was because I was using nom's parser combinators which results in lots of nested closures. I spotted it because this caused rust-analyzer to hang because cargo clippy hung (it looks like check was the issue), I had to kill clippy to fix it.

Bisection results

I bisected this (with cargo-bisect-rustc) to find the regression in nightly-2019-10-16, which contained the following bors commits:

  1. Auto merge of Rollup of 4 pull requests #65433 - Centril:rollup-rzvry15, r=Centril
  2. Auto merge of Rollup of 14 pull requests #65454 - tmandry:rollup-0k6jiik, r=tmandry
  3. Auto merge of Update clippy #65450 - Manishearth:clippyup, r=Manishearth
  4. Auto merge of use precalculated dominators in explain_borrow #65172 - tanriol:explain_borrow-use-context-dominators, r=nagisa
  5. Auto merge of Update cargo, books #65445 - ehuss:update-cargo-books, r=alexcrichton

@rustbot modify labels: +regression-from-stable-to-stable -regression-untriaged

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.C-bugCategory: This is a bug.I-compiletimeIssue: Problems and improvements with respect to compile times.P-highHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions