Skip to content

Bug: Recursive generic union type synonyms cause poor compiler performance #10451

@benjamin-hodgson

Description

@benjamin-hodgson

TypeScript Version: 1.8.10 and 2.1.0-dev.20160818

Code

type T<A> = { a: TSynonym<A> }
          | { b: TSynonym<A> }
          | { c: TSynonym<A> }
          //| { d: TSynonym<A> }
type TSynonym<A> = T<A>

function f<A>(): T<A> {
    return g<A>()
}
function g<A>(): T<A> {
    // return h<A>()
}
function h<A>(): T<A> {

}

Expected behavior:
Type error, in a reasonable length of time (because g and h do not return a value).

Actual behavior:
This example takes over 7 seconds to (fail to) compile on my machine (a new, maxed-out MacBook Pro) and peaks at over 400MB of memory. Uncommenting the fourth line of T's declaration causes the compiler to crash with an out-of-memory error after about a minute. Uncommenting the call to h doubles the compilation time to 14 seconds and increases peak memory usage to over 1GB.

Removing TSynonym (so that the body of T uses T directly), or removing all the generic types, improves the performance significantly.

My guess is that the type-checker is recursively expanding the definitions of T and TSynonym when it tries to type-check the functions, resulting in a very large quantity of nested union types.

Here is the output of tsc with the --diagnostics flag:

Files:               2
Lines:           19030
Nodes:           98142
Identifiers:     35533
Symbols:        354868
Types:          755366
Memory used:   611459K
I/O read:        0.00s
I/O write:       0.00s
Parse time:      0.14s
Bind time:       0.10s
Check time:      6.73s
Emit time:       0.00s
Total time:      6.97s

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already createdFixedA PR has been merged for this issue

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions