diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4b8d44e62fc9f..0060c38520c2e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22810,6 +22810,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { tracing?.pop(); } + // if (entry !== undefined) { + // // If the previous entry and the result disagree, then something has gone wrong. + // const entrySucceeded = !!(entry & RelationComparisonResult.Succeeded); + // const resultSucceeded = result !== Ternary.False; + // Debug.assertEqual(entrySucceeded, resultSucceeded, "Cached relationship does not match recalculated result"); + // } + if (outofbandVarianceMarkerHandler) { outofbandVarianceMarkerHandler = originalHandler; } @@ -23522,9 +23529,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // types are invariant, if any of the type parameters are invariant we reset the reported // errors and instead force a structural comparison (which will include elaborations that // reveal the reason). - // We can switch on `reportErrors` here, since varianceCheckFailed guarantees we return `False`, // we can return `False` early here to skip calculating the structural error message we don't need. - if (varianceCheckFailed && !(reportErrors && some(variances, v => (v & VarianceFlags.VarianceMask) === VarianceFlags.Invariant))) { + if (varianceCheckFailed && !some(variances, v => (v & VarianceFlags.VarianceMask) === VarianceFlags.Invariant)) { return Ternary.False; } // We remember the original error information so we can restore it in case the structural diff --git a/tests/baselines/reference/conditionalTypeDoesntSpinForever.types b/tests/baselines/reference/conditionalTypeDoesntSpinForever.types index 73fb1f2d6e19d..529ca4c2247e5 100644 --- a/tests/baselines/reference/conditionalTypeDoesntSpinForever.types +++ b/tests/baselines/reference/conditionalTypeDoesntSpinForever.types @@ -1,8 +1,9 @@ //// [tests/cases/compiler/conditionalTypeDoesntSpinForever.ts] //// === Performance Stats === -Type Count: 1,000 -Instantiation count: 2,500 -> 5,000 +Assignability cache: 1,000 +Type Count: 2,500 +Instantiation count: 5,000 === conditionalTypeDoesntSpinForever.ts === // A *self-contained* demonstration of the problem follows... diff --git a/tests/baselines/reference/issue55217.js b/tests/baselines/reference/issue55217.js new file mode 100644 index 0000000000000..c67a229237da6 --- /dev/null +++ b/tests/baselines/reference/issue55217.js @@ -0,0 +1,45 @@ +//// [tests/cases/compiler/issue55217.ts] //// + +//// [types.ts] +export type ProductName = 'a' | 'b' + +export type SubproductNameForProductName

= P extends unknown + ? keyof EntitiesByProductName[P] + : never + +type EntitiesByProductName = { + a: { a1: { value: 'a-a1' } } + b: { b1: { value: 'b-b1' } } +} + +export type DiscriminatedUnion< + P extends ProductName = ProductName, + E extends SubproductNameForProductName

= SubproductNameForProductName

, +> = P extends ProductName + ? E extends SubproductNameForProductName

+ // ? E extends unknown // With unknown, the exception doesn't happen. + ? EntitiesByProductName[P][E] + : never + : never + +//// [app.ts] +import { SubproductNameForProductName, DiscriminatedUnion, ProductName } from './types' + +export const bug =

() => { + const subproducts: DiscriminatedUnion>[] = [] + subproducts.map((_: DiscriminatedUnion) => null) +} + + +//// [types.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [app.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.bug = void 0; +var bug = function () { + var subproducts = []; + subproducts.map(function (_) { return null; }); +}; +exports.bug = bug; diff --git a/tests/baselines/reference/issue55217.symbols b/tests/baselines/reference/issue55217.symbols new file mode 100644 index 0000000000000..24711a7693320 --- /dev/null +++ b/tests/baselines/reference/issue55217.symbols @@ -0,0 +1,91 @@ +//// [tests/cases/compiler/issue55217.ts] //// + +=== types.ts === +export type ProductName = 'a' | 'b' +>ProductName : Symbol(ProductName, Decl(types.ts, 0, 0)) + +export type SubproductNameForProductName

= P extends unknown +>SubproductNameForProductName : Symbol(SubproductNameForProductName, Decl(types.ts, 0, 35)) +>P : Symbol(P, Decl(types.ts, 2, 41)) +>ProductName : Symbol(ProductName, Decl(types.ts, 0, 0)) +>P : Symbol(P, Decl(types.ts, 2, 41)) + + ? keyof EntitiesByProductName[P] +>EntitiesByProductName : Symbol(EntitiesByProductName, Decl(types.ts, 4, 9)) +>P : Symbol(P, Decl(types.ts, 2, 41)) + + : never + +type EntitiesByProductName = { +>EntitiesByProductName : Symbol(EntitiesByProductName, Decl(types.ts, 4, 9)) + + a: { a1: { value: 'a-a1' } } +>a : Symbol(a, Decl(types.ts, 6, 30)) +>a1 : Symbol(a1, Decl(types.ts, 7, 6)) +>value : Symbol(value, Decl(types.ts, 7, 12)) + + b: { b1: { value: 'b-b1' } } +>b : Symbol(b, Decl(types.ts, 7, 30)) +>b1 : Symbol(b1, Decl(types.ts, 8, 6)) +>value : Symbol(value, Decl(types.ts, 8, 12)) +} + +export type DiscriminatedUnion< +>DiscriminatedUnion : Symbol(DiscriminatedUnion, Decl(types.ts, 9, 1)) + + P extends ProductName = ProductName, +>P : Symbol(P, Decl(types.ts, 11, 31)) +>ProductName : Symbol(ProductName, Decl(types.ts, 0, 0)) +>ProductName : Symbol(ProductName, Decl(types.ts, 0, 0)) + + E extends SubproductNameForProductName

= SubproductNameForProductName

, +>E : Symbol(E, Decl(types.ts, 12, 38)) +>SubproductNameForProductName : Symbol(SubproductNameForProductName, Decl(types.ts, 0, 35)) +>P : Symbol(P, Decl(types.ts, 11, 31)) +>SubproductNameForProductName : Symbol(SubproductNameForProductName, Decl(types.ts, 0, 35)) +>P : Symbol(P, Decl(types.ts, 11, 31)) + +> = P extends ProductName +>P : Symbol(P, Decl(types.ts, 11, 31)) +>ProductName : Symbol(ProductName, Decl(types.ts, 0, 0)) + + ? E extends SubproductNameForProductName

+>E : Symbol(E, Decl(types.ts, 12, 38)) +>SubproductNameForProductName : Symbol(SubproductNameForProductName, Decl(types.ts, 0, 35)) +>P : Symbol(P, Decl(types.ts, 11, 31)) + + // ? E extends unknown // With unknown, the exception doesn't happen. + ? EntitiesByProductName[P][E] +>EntitiesByProductName : Symbol(EntitiesByProductName, Decl(types.ts, 4, 9)) +>P : Symbol(P, Decl(types.ts, 11, 31)) +>E : Symbol(E, Decl(types.ts, 12, 38)) + + : never + : never + +=== app.ts === +import { SubproductNameForProductName, DiscriminatedUnion, ProductName } from './types' +>SubproductNameForProductName : Symbol(SubproductNameForProductName, Decl(app.ts, 0, 8)) +>DiscriminatedUnion : Symbol(DiscriminatedUnion, Decl(app.ts, 0, 38)) +>ProductName : Symbol(ProductName, Decl(app.ts, 0, 58)) + +export const bug =

() => { +>bug : Symbol(bug, Decl(app.ts, 2, 12)) +>P : Symbol(P, Decl(app.ts, 2, 20)) +>ProductName : Symbol(ProductName, Decl(app.ts, 0, 58)) + + const subproducts: DiscriminatedUnion>[] = [] +>subproducts : Symbol(subproducts, Decl(app.ts, 3, 7)) +>DiscriminatedUnion : Symbol(DiscriminatedUnion, Decl(app.ts, 0, 38)) +>P : Symbol(P, Decl(app.ts, 2, 20)) +>SubproductNameForProductName : Symbol(SubproductNameForProductName, Decl(app.ts, 0, 8)) +>P : Symbol(P, Decl(app.ts, 2, 20)) + + subproducts.map((_: DiscriminatedUnion) => null) +>subproducts.map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>subproducts : Symbol(subproducts, Decl(app.ts, 3, 7)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>_ : Symbol(_, Decl(app.ts, 4, 19)) +>DiscriminatedUnion : Symbol(DiscriminatedUnion, Decl(app.ts, 0, 38)) +} + diff --git a/tests/baselines/reference/issue55217.types b/tests/baselines/reference/issue55217.types new file mode 100644 index 0000000000000..c816217b7eeab --- /dev/null +++ b/tests/baselines/reference/issue55217.types @@ -0,0 +1,84 @@ +//// [tests/cases/compiler/issue55217.ts] //// + +=== types.ts === +export type ProductName = 'a' | 'b' +>ProductName : ProductName +> : ^^^^^^^^^^^ + +export type SubproductNameForProductName

= P extends unknown +>SubproductNameForProductName : SubproductNameForProductName

+> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ? keyof EntitiesByProductName[P] + : never + +type EntitiesByProductName = { +>EntitiesByProductName : EntitiesByProductName +> : ^^^^^^^^^^^^^^^^^^^^^ + + a: { a1: { value: 'a-a1' } } +>a : { a1: { value: "a-a1"; }; } +> : ^^^^^^ ^^^ +>a1 : { value: "a-a1"; } +> : ^^^^^^^^^ ^^^ +>value : "a-a1" +> : ^^^^^^ + + b: { b1: { value: 'b-b1' } } +>b : { b1: { value: "b-b1"; }; } +> : ^^^^^^ ^^^ +>b1 : { value: "b-b1"; } +> : ^^^^^^^^^ ^^^ +>value : "b-b1" +> : ^^^^^^ +} + +export type DiscriminatedUnion< +>DiscriminatedUnion : DiscriminatedUnion +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + P extends ProductName = ProductName, + E extends SubproductNameForProductName

= SubproductNameForProductName

, +> = P extends ProductName + ? E extends SubproductNameForProductName

+ // ? E extends unknown // With unknown, the exception doesn't happen. + ? EntitiesByProductName[P][E] + : never + : never + +=== app.ts === +import { SubproductNameForProductName, DiscriminatedUnion, ProductName } from './types' +>SubproductNameForProductName : any +> : ^^^ +>DiscriminatedUnion : any +> : ^^^ +>ProductName : any +> : ^^^ + +export const bug =

() => { +>bug :

() => void +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ +>

() => { const subproducts: DiscriminatedUnion>[] = [] subproducts.map((_: DiscriminatedUnion) => null)} :

() => void +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ + + const subproducts: DiscriminatedUnion>[] = [] +>subproducts : DiscriminatedUnion>[] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>[] : never[] +> : ^^^^^^^ + + subproducts.map((_: DiscriminatedUnion) => null) +>subproducts.map((_: DiscriminatedUnion) => null) : null[] +> : ^^^^^^ +>subproducts.map : (callbackfn: (value: DiscriminatedUnion>, index: number, array: DiscriminatedUnion>[]) => U, thisArg?: any) => U[] +> : ^ ^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^ +>subproducts : DiscriminatedUnion>[] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>map : (callbackfn: (value: DiscriminatedUnion>, index: number, array: DiscriminatedUnion>[]) => U, thisArg?: any) => U[] +> : ^ ^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^ +>(_: DiscriminatedUnion) => null : (_: DiscriminatedUnion) => null +> : ^ ^^ ^^^^^^^^^ +>_ : DiscriminatedUnion +> : ^^^^^^^^^^^^^^^^^^ +} + diff --git a/tests/baselines/reference/styledComponentsInstantiaionLimitNotReached.types b/tests/baselines/reference/styledComponentsInstantiaionLimitNotReached.types index 4aebbfa368533..ece3f14b2679c 100644 --- a/tests/baselines/reference/styledComponentsInstantiaionLimitNotReached.types +++ b/tests/baselines/reference/styledComponentsInstantiaionLimitNotReached.types @@ -3,7 +3,7 @@ === Performance Stats === Assignability cache: 10,000 Type Count: 25,000 -Instantiation count: 250,000 -> 500,000 +Instantiation count: 500,000 Symbol count: 100,000 === styledComponentsInstantiaionLimitNotReached.ts === diff --git a/tests/cases/compiler/issue55217.ts b/tests/cases/compiler/issue55217.ts new file mode 100644 index 0000000000000..c94786b221415 --- /dev/null +++ b/tests/cases/compiler/issue55217.ts @@ -0,0 +1,31 @@ +// @strict: true + +// @filename: types.ts +export type ProductName = 'a' | 'b' + +export type SubproductNameForProductName

= P extends unknown + ? keyof EntitiesByProductName[P] + : never + +type EntitiesByProductName = { + a: { a1: { value: 'a-a1' } } + b: { b1: { value: 'b-b1' } } +} + +export type DiscriminatedUnion< + P extends ProductName = ProductName, + E extends SubproductNameForProductName

= SubproductNameForProductName

, +> = P extends ProductName + ? E extends SubproductNameForProductName

+ // ? E extends unknown // With unknown, the exception doesn't happen. + ? EntitiesByProductName[P][E] + : never + : never + +// @filename: app.ts +import { SubproductNameForProductName, DiscriminatedUnion, ProductName } from './types' + +export const bug =

() => { + const subproducts: DiscriminatedUnion>[] = [] + subproducts.map((_: DiscriminatedUnion) => null) +}