Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache property name widening contexts #40732

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
@@ -19212,8 +19212,20 @@ namespace ts {
return regularNew;
}

function createWideningContext(parent: WideningContext | undefined, propertyName: __String | undefined, siblings: Type[] | undefined): WideningContext {
return { parent, propertyName, siblings, resolvedProperties: undefined };
function createSiblingWideningContext(siblings: Type[]): WideningContext {
return { siblings };
}

function createPropertyWideningContext(parent: WideningContext, propertyName: __String): WideningContext {
const cache = (parent.childContexts ??= new Map<__String, WideningContext>());
const existing = cache.get(propertyName);
if (existing) {
return existing;
}

const context: WideningContext = { parent, propertyName };
cache.set(propertyName, context);
return context;
}

function getSiblingsOfContext(context: WideningContext): Type[] {
@@ -19256,7 +19268,7 @@ namespace ts {
return prop;
}
const original = getTypeOfSymbol(prop);
const propContext = context && createWideningContext(context, prop.escapedName, /*siblings*/ undefined);
const propContext = context && createPropertyWideningContext(context, prop.escapedName);
const widened = getWidenedTypeWithContext(original, propContext);
return widened === original ? prop : createSymbolWithType(prop, widened);
}
@@ -19310,7 +19322,7 @@ namespace ts {
result = getWidenedTypeOfObjectLiteral(type, context);
}
else if (type.flags & TypeFlags.Union) {
const unionContext = context || createWideningContext(/*parent*/ undefined, /*propertyName*/ undefined, (<UnionType>type).types);
const unionContext = context || createSiblingWideningContext((<UnionType>type).types);
const widenedTypes = sameMap((<UnionType>type).types, t => t.flags & TypeFlags.Nullable ? t : getWidenedTypeWithContext(t, unionContext));
// Widening an empty object literal transitions from a highly restrictive type to
// a highly inclusive one. For that reason we perform subtype reduction here if the
9 changes: 5 additions & 4 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
@@ -5550,10 +5550,11 @@ namespace ts {

/* @internal */
export interface WideningContext {
parent?: WideningContext; // Parent context
propertyName?: __String; // Name of property in parent
siblings?: Type[]; // Types of siblings
resolvedProperties?: Symbol[]; // Properties occurring in sibling object literals
parent?: WideningContext; // Parent context
propertyName?: __String; // Name of property in parent
siblings?: Type[]; // Types of siblings
resolvedProperties?: Symbol[]; // Properties occurring in sibling object literals
childContexts?: ESMap<__String, WideningContext>; // WideningContexts with parent === this and propertyName as the key
}

/* @internal */