diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 48a4bdf3a5992..7194fa80ec7da 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2156,6 +2156,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { var resolutionTargets: TypeSystemEntity[] = []; var resolutionResults: boolean[] = []; var resolutionPropertyNames: TypeSystemPropertyName[] = []; + var resolutionStart = 0; + var inVarianceComputation = false; var suggestionCount = 0; var maximumSuggestionCount = 10; @@ -10105,7 +10107,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function findResolutionCycleStartIndex(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): number { - for (let i = resolutionTargets.length - 1; i >= 0; i--) { + for (let i = resolutionTargets.length - 1; i >= resolutionStart; i--) { if (resolutionTargetHasProperty(resolutionTargets[i], resolutionPropertyNames[i])) { return -1; } @@ -22678,6 +22680,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const links = getSymbolLinks(symbol); if (!links.variances) { tracing?.push(tracing.Phase.CheckTypes, "getVariancesWorker", { arity: typeParameters.length, id: getTypeId(getDeclaredTypeOfSymbol(symbol)) }); + const oldVarianceComputation = inVarianceComputation; + if (!inVarianceComputation) { + inVarianceComputation = true; + resolutionStart = resolutionTargets.length; + } links.variances = emptyArray; const variances = []; for (const tp of typeParameters) { @@ -22716,6 +22723,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } variances.push(variance); } + if (!oldVarianceComputation) { + inVarianceComputation = false; + resolutionStart = 0; + } links.variances = variances; tracing?.pop({ variances: variances.map(Debug.formatVariance) }); } diff --git a/tests/baselines/reference/classVarianceResolveCircularity.errors.txt b/tests/baselines/reference/classVarianceResolveCircularity.errors.txt deleted file mode 100644 index faff1bf64260a..0000000000000 --- a/tests/baselines/reference/classVarianceResolveCircularity.errors.txt +++ /dev/null @@ -1,15 +0,0 @@ -tests/cases/compiler/classVarianceResolveCircularity.ts(5,5): error TS7022: 'Value' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. - - -==== tests/cases/compiler/classVarianceResolveCircularity.ts (1 errors) ==== - // Issue #52813 - - class Bar { - num!: number; // Swap to remove error - Value = callme(this).num; - ~~~~~ -!!! error TS7022: 'Value' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. - Field: number = callme(this).num; - } - declare function callme(x: Bar): Bar; - declare function callme(x: object): string; \ No newline at end of file diff --git a/tests/baselines/reference/classVarianceResolveCircularity.symbols b/tests/baselines/reference/classVarianceResolveCircularity.symbols deleted file mode 100644 index a3bf2bc878ff6..0000000000000 --- a/tests/baselines/reference/classVarianceResolveCircularity.symbols +++ /dev/null @@ -1,34 +0,0 @@ -=== tests/cases/compiler/classVarianceResolveCircularity.ts === -// Issue #52813 - -class Bar { ->Bar : Symbol(Bar, Decl(classVarianceResolveCircularity.ts, 0, 0)) ->T : Symbol(T, Decl(classVarianceResolveCircularity.ts, 2, 10)) - - num!: number; // Swap to remove error ->num : Symbol(Bar.num, Decl(classVarianceResolveCircularity.ts, 2, 14)) - - Value = callme(this).num; ->Value : Symbol(Bar.Value, Decl(classVarianceResolveCircularity.ts, 3, 17)) ->callme(this).num : Symbol(Bar.num, Decl(classVarianceResolveCircularity.ts, 2, 14)) ->callme : Symbol(callme, Decl(classVarianceResolveCircularity.ts, 6, 1), Decl(classVarianceResolveCircularity.ts, 7, 47)) ->this : Symbol(Bar, Decl(classVarianceResolveCircularity.ts, 0, 0)) ->num : Symbol(Bar.num, Decl(classVarianceResolveCircularity.ts, 2, 14)) - - Field: number = callme(this).num; ->Field : Symbol(Bar.Field, Decl(classVarianceResolveCircularity.ts, 4, 29)) ->callme(this).num : Symbol(Bar.num, Decl(classVarianceResolveCircularity.ts, 2, 14)) ->callme : Symbol(callme, Decl(classVarianceResolveCircularity.ts, 6, 1), Decl(classVarianceResolveCircularity.ts, 7, 47)) ->this : Symbol(Bar, Decl(classVarianceResolveCircularity.ts, 0, 0)) ->num : Symbol(Bar.num, Decl(classVarianceResolveCircularity.ts, 2, 14)) -} -declare function callme(x: Bar): Bar; ->callme : Symbol(callme, Decl(classVarianceResolveCircularity.ts, 6, 1), Decl(classVarianceResolveCircularity.ts, 7, 47)) ->x : Symbol(x, Decl(classVarianceResolveCircularity.ts, 7, 24)) ->Bar : Symbol(Bar, Decl(classVarianceResolveCircularity.ts, 0, 0)) ->Bar : Symbol(Bar, Decl(classVarianceResolveCircularity.ts, 0, 0)) - -declare function callme(x: object): string; ->callme : Symbol(callme, Decl(classVarianceResolveCircularity.ts, 6, 1), Decl(classVarianceResolveCircularity.ts, 7, 47)) ->x : Symbol(x, Decl(classVarianceResolveCircularity.ts, 8, 24)) - diff --git a/tests/baselines/reference/classVarianceResolveCircularity.js b/tests/baselines/reference/classVarianceResolveCircularity1.js similarity index 73% rename from tests/baselines/reference/classVarianceResolveCircularity.js rename to tests/baselines/reference/classVarianceResolveCircularity1.js index 2518fa84c7bdc..509d8e1238e6d 100644 --- a/tests/baselines/reference/classVarianceResolveCircularity.js +++ b/tests/baselines/reference/classVarianceResolveCircularity1.js @@ -1,15 +1,15 @@ -//// [classVarianceResolveCircularity.ts] +//// [classVarianceResolveCircularity1.ts] // Issue #52813 class Bar { - num!: number; // Swap to remove error + num!: number; Value = callme(this).num; Field: number = callme(this).num; } declare function callme(x: Bar): Bar; declare function callme(x: object): string; -//// [classVarianceResolveCircularity.js] +//// [classVarianceResolveCircularity1.js] "use strict"; // Issue #52813 var Bar = /** @class */ (function () { diff --git a/tests/baselines/reference/classVarianceResolveCircularity1.symbols b/tests/baselines/reference/classVarianceResolveCircularity1.symbols new file mode 100644 index 0000000000000..7494c4b37e2d2 --- /dev/null +++ b/tests/baselines/reference/classVarianceResolveCircularity1.symbols @@ -0,0 +1,34 @@ +=== tests/cases/compiler/classVarianceResolveCircularity1.ts === +// Issue #52813 + +class Bar { +>Bar : Symbol(Bar, Decl(classVarianceResolveCircularity1.ts, 0, 0)) +>T : Symbol(T, Decl(classVarianceResolveCircularity1.ts, 2, 10)) + + num!: number; +>num : Symbol(Bar.num, Decl(classVarianceResolveCircularity1.ts, 2, 14)) + + Value = callme(this).num; +>Value : Symbol(Bar.Value, Decl(classVarianceResolveCircularity1.ts, 3, 17)) +>callme(this).num : Symbol(Bar.num, Decl(classVarianceResolveCircularity1.ts, 2, 14)) +>callme : Symbol(callme, Decl(classVarianceResolveCircularity1.ts, 6, 1), Decl(classVarianceResolveCircularity1.ts, 7, 47)) +>this : Symbol(Bar, Decl(classVarianceResolveCircularity1.ts, 0, 0)) +>num : Symbol(Bar.num, Decl(classVarianceResolveCircularity1.ts, 2, 14)) + + Field: number = callme(this).num; +>Field : Symbol(Bar.Field, Decl(classVarianceResolveCircularity1.ts, 4, 29)) +>callme(this).num : Symbol(Bar.num, Decl(classVarianceResolveCircularity1.ts, 2, 14)) +>callme : Symbol(callme, Decl(classVarianceResolveCircularity1.ts, 6, 1), Decl(classVarianceResolveCircularity1.ts, 7, 47)) +>this : Symbol(Bar, Decl(classVarianceResolveCircularity1.ts, 0, 0)) +>num : Symbol(Bar.num, Decl(classVarianceResolveCircularity1.ts, 2, 14)) +} +declare function callme(x: Bar): Bar; +>callme : Symbol(callme, Decl(classVarianceResolveCircularity1.ts, 6, 1), Decl(classVarianceResolveCircularity1.ts, 7, 47)) +>x : Symbol(x, Decl(classVarianceResolveCircularity1.ts, 7, 24)) +>Bar : Symbol(Bar, Decl(classVarianceResolveCircularity1.ts, 0, 0)) +>Bar : Symbol(Bar, Decl(classVarianceResolveCircularity1.ts, 0, 0)) + +declare function callme(x: object): string; +>callme : Symbol(callme, Decl(classVarianceResolveCircularity1.ts, 6, 1), Decl(classVarianceResolveCircularity1.ts, 7, 47)) +>x : Symbol(x, Decl(classVarianceResolveCircularity1.ts, 8, 24)) + diff --git a/tests/baselines/reference/classVarianceResolveCircularity.types b/tests/baselines/reference/classVarianceResolveCircularity1.types similarity index 81% rename from tests/baselines/reference/classVarianceResolveCircularity.types rename to tests/baselines/reference/classVarianceResolveCircularity1.types index d7e48dffe67df..dacd45cedf484 100644 --- a/tests/baselines/reference/classVarianceResolveCircularity.types +++ b/tests/baselines/reference/classVarianceResolveCircularity1.types @@ -1,14 +1,14 @@ -=== tests/cases/compiler/classVarianceResolveCircularity.ts === +=== tests/cases/compiler/classVarianceResolveCircularity1.ts === // Issue #52813 class Bar { >Bar : Bar - num!: number; // Swap to remove error + num!: number; >num : number Value = callme(this).num; ->Value : any +>Value : number >callme(this).num : number >callme(this) : Bar >callme : { (x: Bar): Bar; (x: object): string; } diff --git a/tests/baselines/reference/classVarianceResolveCircularity2.js b/tests/baselines/reference/classVarianceResolveCircularity2.js new file mode 100644 index 0000000000000..f60e843d328dc --- /dev/null +++ b/tests/baselines/reference/classVarianceResolveCircularity2.js @@ -0,0 +1,37 @@ +//// [classVarianceResolveCircularity2.ts] +// Issue #52813 + +export {}; + +class Bar { + num!: number; + Value = callme(new Foo(this)).bar.num; + Field: number = callme(new Foo(this)).bar.num; +} +declare function callme(x: Foo): Foo; +declare function callme(x: object): string; + +class Foo { + bar!: Bar; + constructor(bar: Bar) { + this.bar = bar; + } +} + +//// [classVarianceResolveCircularity2.js] +"use strict"; +// Issue #52813 +Object.defineProperty(exports, "__esModule", { value: true }); +var Bar = /** @class */ (function () { + function Bar() { + this.Value = callme(new Foo(this)).bar.num; + this.Field = callme(new Foo(this)).bar.num; + } + return Bar; +}()); +var Foo = /** @class */ (function () { + function Foo(bar) { + this.bar = bar; + } + return Foo; +}()); diff --git a/tests/baselines/reference/classVarianceResolveCircularity2.symbols b/tests/baselines/reference/classVarianceResolveCircularity2.symbols new file mode 100644 index 0000000000000..305ececb72050 --- /dev/null +++ b/tests/baselines/reference/classVarianceResolveCircularity2.symbols @@ -0,0 +1,63 @@ +=== tests/cases/compiler/classVarianceResolveCircularity2.ts === +// Issue #52813 + +export {}; + +class Bar { +>Bar : Symbol(Bar, Decl(classVarianceResolveCircularity2.ts, 2, 10)) +>T : Symbol(T, Decl(classVarianceResolveCircularity2.ts, 4, 10)) + + num!: number; +>num : Symbol(Bar.num, Decl(classVarianceResolveCircularity2.ts, 4, 14)) + + Value = callme(new Foo(this)).bar.num; +>Value : Symbol(Bar.Value, Decl(classVarianceResolveCircularity2.ts, 5, 17)) +>callme(new Foo(this)).bar.num : Symbol(Bar.num, Decl(classVarianceResolveCircularity2.ts, 4, 14)) +>callme(new Foo(this)).bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14)) +>callme : Symbol(callme, Decl(classVarianceResolveCircularity2.ts, 8, 1), Decl(classVarianceResolveCircularity2.ts, 9, 47)) +>Foo : Symbol(Foo, Decl(classVarianceResolveCircularity2.ts, 10, 43)) +>this : Symbol(Bar, Decl(classVarianceResolveCircularity2.ts, 2, 10)) +>bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14)) +>num : Symbol(Bar.num, Decl(classVarianceResolveCircularity2.ts, 4, 14)) + + Field: number = callme(new Foo(this)).bar.num; +>Field : Symbol(Bar.Field, Decl(classVarianceResolveCircularity2.ts, 6, 42)) +>callme(new Foo(this)).bar.num : Symbol(Bar.num, Decl(classVarianceResolveCircularity2.ts, 4, 14)) +>callme(new Foo(this)).bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14)) +>callme : Symbol(callme, Decl(classVarianceResolveCircularity2.ts, 8, 1), Decl(classVarianceResolveCircularity2.ts, 9, 47)) +>Foo : Symbol(Foo, Decl(classVarianceResolveCircularity2.ts, 10, 43)) +>this : Symbol(Bar, Decl(classVarianceResolveCircularity2.ts, 2, 10)) +>bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14)) +>num : Symbol(Bar.num, Decl(classVarianceResolveCircularity2.ts, 4, 14)) +} +declare function callme(x: Foo): Foo; +>callme : Symbol(callme, Decl(classVarianceResolveCircularity2.ts, 8, 1), Decl(classVarianceResolveCircularity2.ts, 9, 47)) +>x : Symbol(x, Decl(classVarianceResolveCircularity2.ts, 9, 24)) +>Foo : Symbol(Foo, Decl(classVarianceResolveCircularity2.ts, 10, 43)) +>Foo : Symbol(Foo, Decl(classVarianceResolveCircularity2.ts, 10, 43)) + +declare function callme(x: object): string; +>callme : Symbol(callme, Decl(classVarianceResolveCircularity2.ts, 8, 1), Decl(classVarianceResolveCircularity2.ts, 9, 47)) +>x : Symbol(x, Decl(classVarianceResolveCircularity2.ts, 10, 24)) + +class Foo { +>Foo : Symbol(Foo, Decl(classVarianceResolveCircularity2.ts, 10, 43)) +>T : Symbol(T, Decl(classVarianceResolveCircularity2.ts, 12, 10)) + + bar!: Bar; +>bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14)) +>Bar : Symbol(Bar, Decl(classVarianceResolveCircularity2.ts, 2, 10)) +>T : Symbol(T, Decl(classVarianceResolveCircularity2.ts, 12, 10)) + + constructor(bar: Bar) { +>bar : Symbol(bar, Decl(classVarianceResolveCircularity2.ts, 14, 16)) +>Bar : Symbol(Bar, Decl(classVarianceResolveCircularity2.ts, 2, 10)) +>T : Symbol(T, Decl(classVarianceResolveCircularity2.ts, 12, 10)) + + this.bar = bar; +>this.bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14)) +>this : Symbol(Foo, Decl(classVarianceResolveCircularity2.ts, 10, 43)) +>bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14)) +>bar : Symbol(bar, Decl(classVarianceResolveCircularity2.ts, 14, 16)) + } +} diff --git a/tests/baselines/reference/classVarianceResolveCircularity2.types b/tests/baselines/reference/classVarianceResolveCircularity2.types new file mode 100644 index 0000000000000..3096c551f44d3 --- /dev/null +++ b/tests/baselines/reference/classVarianceResolveCircularity2.types @@ -0,0 +1,60 @@ +=== tests/cases/compiler/classVarianceResolveCircularity2.ts === +// Issue #52813 + +export {}; + +class Bar { +>Bar : Bar + + num!: number; +>num : number + + Value = callme(new Foo(this)).bar.num; +>Value : number +>callme(new Foo(this)).bar.num : number +>callme(new Foo(this)).bar : Bar +>callme(new Foo(this)) : Foo +>callme : { (x: Foo): Foo; (x: object): string; } +>new Foo(this) : Foo +>Foo : typeof Foo +>this : this +>bar : Bar +>num : number + + Field: number = callme(new Foo(this)).bar.num; +>Field : number +>callme(new Foo(this)).bar.num : number +>callme(new Foo(this)).bar : Bar +>callme(new Foo(this)) : Foo +>callme : { (x: Foo): Foo; (x: object): string; } +>new Foo(this) : Foo +>Foo : typeof Foo +>this : this +>bar : Bar +>num : number +} +declare function callme(x: Foo): Foo; +>callme : { (x: Foo): Foo; (x: object): string; } +>x : Foo + +declare function callme(x: object): string; +>callme : { (x: Foo): Foo; (x: object): string; } +>x : object + +class Foo { +>Foo : Foo + + bar!: Bar; +>bar : Bar + + constructor(bar: Bar) { +>bar : Bar + + this.bar = bar; +>this.bar = bar : Bar +>this.bar : Bar +>this : this +>bar : Bar +>bar : Bar + } +} diff --git a/tests/cases/compiler/classVarianceResolveCircularity.ts b/tests/cases/compiler/classVarianceResolveCircularity1.ts similarity index 79% rename from tests/cases/compiler/classVarianceResolveCircularity.ts rename to tests/cases/compiler/classVarianceResolveCircularity1.ts index abff110eea799..2432b4743a01c 100644 --- a/tests/cases/compiler/classVarianceResolveCircularity.ts +++ b/tests/cases/compiler/classVarianceResolveCircularity1.ts @@ -3,7 +3,7 @@ // Issue #52813 class Bar { - num!: number; // Swap to remove error + num!: number; Value = callme(this).num; Field: number = callme(this).num; } diff --git a/tests/cases/compiler/classVarianceResolveCircularity2.ts b/tests/cases/compiler/classVarianceResolveCircularity2.ts new file mode 100644 index 0000000000000..9874e13f95ac8 --- /dev/null +++ b/tests/cases/compiler/classVarianceResolveCircularity2.ts @@ -0,0 +1,20 @@ +// @strict: true + +// Issue #52813 + +export {}; + +class Bar { + num!: number; + Value = callme(new Foo(this)).bar.num; + Field: number = callme(new Foo(this)).bar.num; +} +declare function callme(x: Foo): Foo; +declare function callme(x: object): string; + +class Foo { + bar!: Bar; + constructor(bar: Bar) { + this.bar = bar; + } +} \ No newline at end of file