Skip to content

indexing with T extends keyof <Large Union> causes OOM #23977

Closed
@weswigham

Description

@weswigham

This breaks glimmer, and thereby our RWC (once sufficiently fixed in other ways)

Code

Isolated repro (needs dom lib for ElementTagNameMap and associated types):

export function assertIsElement(node: Node | null): node is Element {
    let nodeType = node === null ? null : node.nodeType;
    return nodeType === 1;
}
  
export function assertNodeTagName<
    T extends keyof ElementTagNameMap,
    U extends ElementTagNameMap[T]>(node: Node | null, tagName: T): node is U {
    if (assertIsElement(node)) {
        const nodeTagName = node.tagName.toLowerCase();
         return nodeTagName === tagName;
    }
    return false;
}
  
export function assertNodeProperty<
    T extends keyof ElementTagNameMap,
    P extends keyof ElementTagNameMap[T],
    V extends HTMLElementTagNameMap[T][P]>(node: Node | null, tagName: T, prop: P, value: V) {
    if (assertNodeTagName(node, tagName)) {
        node[prop];
    }
}

Expected behavior:
No crash.

Actual behavior:
OOM crash after a very long delay.

Preliminary investigation shows the OOM occurs when we try to get the distributed form of keyof <Large Union> - namely the process is defined recursively, so when the union has ~170 members, we create 170 intermediate types (flattening one member at a time, while also wasting time recalculating type flags and other bits we will never need) before getting the final, distributed result. Now, picture doing this on every relation comparison operation for P (this distribution is uncached), and multiplying it for V in assertNodeProperty - the complexity is huge.

cc @DanielRosenwasser since I think you care about when we break glimmer.

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFixedA PR has been merged for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions