Cache instantiation expression types early enough to prevent reentrancy during printback (#59931)

This commit is contained in:
Wesley Wigham 2024-09-23 10:46:57 -07:00 committed by GitHub
parent 88809467e8
commit e24cc01b08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 204 additions and 2 deletions

View File

@ -37401,9 +37401,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (exprType === silentNeverType || isErrorType(exprType) || !some(typeArguments)) {
return exprType;
}
const links = getNodeLinks(node);
if (!links.instantiationExpressionTypes) {
links.instantiationExpressionTypes = new Map();
}
if (links.instantiationExpressionTypes.has(exprType.id)) {
return links.instantiationExpressionTypes.get(exprType.id)!;
}
let hasSomeApplicableSignature = false;
let nonApplicableType: Type | undefined;
const result = getInstantiatedType(exprType);
links.instantiationExpressionTypes.set(exprType.id, result);
const errorType = hasSomeApplicableSignature ? nonApplicableType : exprType;
if (errorType) {
diagnostics.add(createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Type_0_has_no_signatures_for_which_the_type_argument_list_is_applicable, typeToString(errorType)));

View File

@ -6239,6 +6239,7 @@ export interface NodeLinks {
potentialReflectCollisions?: Node[];
potentialUnusedRenamedBindingElementsInTypes?: BindingElement[];
externalHelpersModule?: Symbol; // Resolved symbol for the external helpers module
instantiationExpressionTypes?: Map<number, Type>; // Cache of instantiation expression types for the node
}
/** @internal */

View File

@ -0,0 +1,28 @@
instantiationExpressionErrorNoCrash.ts(15,38): error TS2344: Type 'typeof createCacheReducer<QR>' does not satisfy the constraint '(...args: any) => any'.
Type 'typeof createCacheReducer<QR>' provides no match for the signature '(...args: any): any'.
instantiationExpressionErrorNoCrash.ts(15,64): error TS2635: Type '<N extends string, QR>(queries: { [QK in keyof QR]: any; }) => (state?: { queries: QR; }) => { queries: QR; }' has no signatures for which the type argument list is applicable.
==== instantiationExpressionErrorNoCrash.ts (2 errors) ====
const createCacheReducer = <N extends string, QR>(
queries: Cache<N, QR>["queries"],
) => {
const queriesMap = {} as QR;
const initialState = {
queries: queriesMap,
};
return (state = initialState) => state;
};
export type Cache<N extends string, QR> = {
queries: {
[QK in keyof QR]: ReturnType<typeof createCacheReducer<QR>>;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2344: Type 'typeof createCacheReducer<QR>' does not satisfy the constraint '(...args: any) => any'.
!!! error TS2344: Type 'typeof createCacheReducer<QR>' provides no match for the signature '(...args: any): any'.
~~
!!! error TS2635: Type '<N extends string, QR>(queries: { [QK in keyof QR]: any; }) => (state?: { queries: QR; }) => { queries: QR; }' has no signatures for which the type argument list is applicable.
};
};

View File

@ -0,0 +1,34 @@
//// [tests/cases/compiler/instantiationExpressionErrorNoCrash.ts] ////
//// [instantiationExpressionErrorNoCrash.ts]
const createCacheReducer = <N extends string, QR>(
queries: Cache<N, QR>["queries"],
) => {
const queriesMap = {} as QR;
const initialState = {
queries: queriesMap,
};
return (state = initialState) => state;
};
export type Cache<N extends string, QR> = {
queries: {
[QK in keyof QR]: ReturnType<typeof createCacheReducer<QR>>;
};
};
//// [instantiationExpressionErrorNoCrash.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var createCacheReducer = function (queries) {
var queriesMap = {};
var initialState = {
queries: queriesMap,
};
return function (state) {
if (state === void 0) { state = initialState; }
return state;
};
};

View File

@ -0,0 +1,52 @@
//// [tests/cases/compiler/instantiationExpressionErrorNoCrash.ts] ////
=== instantiationExpressionErrorNoCrash.ts ===
const createCacheReducer = <N extends string, QR>(
>createCacheReducer : Symbol(createCacheReducer, Decl(instantiationExpressionErrorNoCrash.ts, 0, 5))
>N : Symbol(N, Decl(instantiationExpressionErrorNoCrash.ts, 0, 28))
>QR : Symbol(QR, Decl(instantiationExpressionErrorNoCrash.ts, 0, 45))
queries: Cache<N, QR>["queries"],
>queries : Symbol(queries, Decl(instantiationExpressionErrorNoCrash.ts, 0, 50))
>Cache : Symbol(Cache, Decl(instantiationExpressionErrorNoCrash.ts, 10, 2))
>N : Symbol(N, Decl(instantiationExpressionErrorNoCrash.ts, 0, 28))
>QR : Symbol(QR, Decl(instantiationExpressionErrorNoCrash.ts, 0, 45))
) => {
const queriesMap = {} as QR;
>queriesMap : Symbol(queriesMap, Decl(instantiationExpressionErrorNoCrash.ts, 3, 9))
>QR : Symbol(QR, Decl(instantiationExpressionErrorNoCrash.ts, 0, 45))
const initialState = {
>initialState : Symbol(initialState, Decl(instantiationExpressionErrorNoCrash.ts, 5, 9))
queries: queriesMap,
>queries : Symbol(queries, Decl(instantiationExpressionErrorNoCrash.ts, 5, 26))
>queriesMap : Symbol(queriesMap, Decl(instantiationExpressionErrorNoCrash.ts, 3, 9))
};
return (state = initialState) => state;
>state : Symbol(state, Decl(instantiationExpressionErrorNoCrash.ts, 9, 12))
>initialState : Symbol(initialState, Decl(instantiationExpressionErrorNoCrash.ts, 5, 9))
>state : Symbol(state, Decl(instantiationExpressionErrorNoCrash.ts, 9, 12))
};
export type Cache<N extends string, QR> = {
>Cache : Symbol(Cache, Decl(instantiationExpressionErrorNoCrash.ts, 10, 2))
>N : Symbol(N, Decl(instantiationExpressionErrorNoCrash.ts, 12, 18))
>QR : Symbol(QR, Decl(instantiationExpressionErrorNoCrash.ts, 12, 35))
queries: {
>queries : Symbol(queries, Decl(instantiationExpressionErrorNoCrash.ts, 12, 43))
[QK in keyof QR]: ReturnType<typeof createCacheReducer<QR>>;
>QK : Symbol(QK, Decl(instantiationExpressionErrorNoCrash.ts, 14, 9))
>QR : Symbol(QR, Decl(instantiationExpressionErrorNoCrash.ts, 12, 35))
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
>createCacheReducer : Symbol(createCacheReducer, Decl(instantiationExpressionErrorNoCrash.ts, 0, 5))
>QR : Symbol(QR, Decl(instantiationExpressionErrorNoCrash.ts, 12, 35))
};
};

View File

@ -0,0 +1,62 @@
//// [tests/cases/compiler/instantiationExpressionErrorNoCrash.ts] ////
=== instantiationExpressionErrorNoCrash.ts ===
const createCacheReducer = <N extends string, QR>(
>createCacheReducer : <N extends string, QR>(queries: Cache<N, QR>["queries"]) => (state?: { queries: QR; }) => { queries: QR; }
> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
><N extends string, QR>( queries: Cache<N, QR>["queries"],) => { const queriesMap = {} as QR; const initialState = { queries: queriesMap, }; return (state = initialState) => state;} : <N extends string, QR>(queries: Cache<N, QR>["queries"]) => (state?: { queries: QR; }) => { queries: QR; }
> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
queries: Cache<N, QR>["queries"],
>queries : { [QK in keyof QR]: any; }
> : ^^^ ^^^^^^^^^^^^^^^^^^^^^
) => {
const queriesMap = {} as QR;
>queriesMap : QR
> : ^^
>{} as QR : QR
> : ^^
>{} : {}
> : ^^
const initialState = {
>initialState : { queries: QR; }
> : ^^^^^^^^^^^^^^^^
>{ queries: queriesMap, } : { queries: QR; }
> : ^^^^^^^^^^^^^^^^
queries: queriesMap,
>queries : QR
> : ^^
>queriesMap : QR
> : ^^
};
return (state = initialState) => state;
>(state = initialState) => state : (state?: { queries: QR; }) => { queries: QR; }
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>state : { queries: QR; }
> : ^^^^^^^^^^^^^^^^
>initialState : { queries: QR; }
> : ^^^^^^^^^^^^^^^^
>state : { queries: QR; }
> : ^^^^^^^^^^^^^^^^
};
export type Cache<N extends string, QR> = {
>Cache : Cache<N, QR>
> : ^^^^^^^^^^^^
queries: {
>queries : { [QK in keyof QR]: any; }
> : ^^^ ^^^^^^^^^^^^^^^^^^^^^
[QK in keyof QR]: ReturnType<typeof createCacheReducer<QR>>;
>createCacheReducer : <N_1 extends string, QR_1>(queries: Cache<N_1, QR_1>["queries"]) => (state?: { queries: QR_1; }) => { queries: QR_1; }
> : ^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
};
};

View File

@ -179,7 +179,7 @@ const c1 = g<string> || ((x: string) => x);
>c1 : (x: string) => string
> : ^ ^^^^^^^^^^^^^^^^^^^
>g<string> || ((x: string) => x) : (x: string) => string
> : ^ ^^ ^^^^^^^^^^^
> : ^ ^^^^^^^^^^^^^^^^^^^
>g<string> : ((x: string) => string) | undefined
> : ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>g : (<T>(x: T) => T) | undefined
@ -197,7 +197,7 @@ const c2 = g<string> ?? ((x: string) => x);
>c2 : (x: string) => string
> : ^ ^^^^^^^^^^^^^^^^^^^
>g<string> ?? ((x: string) => x) : (x: string) => string
> : ^ ^^ ^^^^^^^^^^^
> : ^ ^^^^^^^^^^^^^^^^^^^
>g<string> : ((x: string) => string) | undefined
> : ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>g : (<T>(x: T) => T) | undefined

View File

@ -0,0 +1,17 @@
const createCacheReducer = <N extends string, QR>(
queries: Cache<N, QR>["queries"],
) => {
const queriesMap = {} as QR;
const initialState = {
queries: queriesMap,
};
return (state = initialState) => state;
};
export type Cache<N extends string, QR> = {
queries: {
[QK in keyof QR]: ReturnType<typeof createCacheReducer<QR>>;
};
};