Skip to content

Commit 2db688e

Browse files
authored
Reset type resolution stack when starting to compute variance (#53549)
1 parent 23469e9 commit 2db688e

11 files changed

+233
-57
lines changed

src/compiler/checker.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -2157,6 +2157,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
21572157
var resolutionTargets: TypeSystemEntity[] = [];
21582158
var resolutionResults: boolean[] = [];
21592159
var resolutionPropertyNames: TypeSystemPropertyName[] = [];
2160+
var resolutionStart = 0;
2161+
var inVarianceComputation = false;
21602162

21612163
var suggestionCount = 0;
21622164
var maximumSuggestionCount = 10;
@@ -10106,7 +10108,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1010610108
}
1010710109

1010810110
function findResolutionCycleStartIndex(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): number {
10109-
for (let i = resolutionTargets.length - 1; i >= 0; i--) {
10111+
for (let i = resolutionTargets.length - 1; i >= resolutionStart; i--) {
1011010112
if (resolutionTargetHasProperty(resolutionTargets[i], resolutionPropertyNames[i])) {
1011110113
return -1;
1011210114
}
@@ -22689,6 +22691,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2268922691
const links = getSymbolLinks(symbol);
2269022692
if (!links.variances) {
2269122693
tracing?.push(tracing.Phase.CheckTypes, "getVariancesWorker", { arity: typeParameters.length, id: getTypeId(getDeclaredTypeOfSymbol(symbol)) });
22694+
const oldVarianceComputation = inVarianceComputation;
22695+
if (!inVarianceComputation) {
22696+
inVarianceComputation = true;
22697+
resolutionStart = resolutionTargets.length;
22698+
}
2269222699
links.variances = emptyArray;
2269322700
const variances = [];
2269422701
for (const tp of typeParameters) {
@@ -22727,6 +22734,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2272722734
}
2272822735
variances.push(variance);
2272922736
}
22737+
if (!oldVarianceComputation) {
22738+
inVarianceComputation = false;
22739+
resolutionStart = 0;
22740+
}
2273022741
links.variances = variances;
2273122742
tracing?.pop({ variances: variances.map(Debug.formatVariance) });
2273222743
}

tests/baselines/reference/classVarianceResolveCircularity.errors.txt

-15
This file was deleted.

tests/baselines/reference/classVarianceResolveCircularity.symbols

-34
This file was deleted.

tests/baselines/reference/classVarianceResolveCircularity.js renamed to tests/baselines/reference/classVarianceResolveCircularity1.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
//// [classVarianceResolveCircularity.ts]
1+
//// [classVarianceResolveCircularity1.ts]
22
// Issue #52813
33

44
class Bar<T> {
5-
num!: number; // Swap to remove error
5+
num!: number;
66
Value = callme(this).num;
77
Field: number = callme(this).num;
88
}
99
declare function callme(x: Bar<any>): Bar<any>;
1010
declare function callme(x: object): string;
1111

12-
//// [classVarianceResolveCircularity.js]
12+
//// [classVarianceResolveCircularity1.js]
1313
"use strict";
1414
// Issue #52813
1515
var Bar = /** @class */ (function () {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
=== tests/cases/compiler/classVarianceResolveCircularity1.ts ===
2+
// Issue #52813
3+
4+
class Bar<T> {
5+
>Bar : Symbol(Bar, Decl(classVarianceResolveCircularity1.ts, 0, 0))
6+
>T : Symbol(T, Decl(classVarianceResolveCircularity1.ts, 2, 10))
7+
8+
num!: number;
9+
>num : Symbol(Bar.num, Decl(classVarianceResolveCircularity1.ts, 2, 14))
10+
11+
Value = callme(this).num;
12+
>Value : Symbol(Bar.Value, Decl(classVarianceResolveCircularity1.ts, 3, 17))
13+
>callme(this).num : Symbol(Bar.num, Decl(classVarianceResolveCircularity1.ts, 2, 14))
14+
>callme : Symbol(callme, Decl(classVarianceResolveCircularity1.ts, 6, 1), Decl(classVarianceResolveCircularity1.ts, 7, 47))
15+
>this : Symbol(Bar, Decl(classVarianceResolveCircularity1.ts, 0, 0))
16+
>num : Symbol(Bar.num, Decl(classVarianceResolveCircularity1.ts, 2, 14))
17+
18+
Field: number = callme(this).num;
19+
>Field : Symbol(Bar.Field, Decl(classVarianceResolveCircularity1.ts, 4, 29))
20+
>callme(this).num : Symbol(Bar.num, Decl(classVarianceResolveCircularity1.ts, 2, 14))
21+
>callme : Symbol(callme, Decl(classVarianceResolveCircularity1.ts, 6, 1), Decl(classVarianceResolveCircularity1.ts, 7, 47))
22+
>this : Symbol(Bar, Decl(classVarianceResolveCircularity1.ts, 0, 0))
23+
>num : Symbol(Bar.num, Decl(classVarianceResolveCircularity1.ts, 2, 14))
24+
}
25+
declare function callme(x: Bar<any>): Bar<any>;
26+
>callme : Symbol(callme, Decl(classVarianceResolveCircularity1.ts, 6, 1), Decl(classVarianceResolveCircularity1.ts, 7, 47))
27+
>x : Symbol(x, Decl(classVarianceResolveCircularity1.ts, 7, 24))
28+
>Bar : Symbol(Bar, Decl(classVarianceResolveCircularity1.ts, 0, 0))
29+
>Bar : Symbol(Bar, Decl(classVarianceResolveCircularity1.ts, 0, 0))
30+
31+
declare function callme(x: object): string;
32+
>callme : Symbol(callme, Decl(classVarianceResolveCircularity1.ts, 6, 1), Decl(classVarianceResolveCircularity1.ts, 7, 47))
33+
>x : Symbol(x, Decl(classVarianceResolveCircularity1.ts, 8, 24))
34+

tests/baselines/reference/classVarianceResolveCircularity.types renamed to tests/baselines/reference/classVarianceResolveCircularity1.types

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
=== tests/cases/compiler/classVarianceResolveCircularity.ts ===
1+
=== tests/cases/compiler/classVarianceResolveCircularity1.ts ===
22
// Issue #52813
33

44
class Bar<T> {
55
>Bar : Bar<T>
66

7-
num!: number; // Swap to remove error
7+
num!: number;
88
>num : number
99

1010
Value = callme(this).num;
11-
>Value : any
11+
>Value : number
1212
>callme(this).num : number
1313
>callme(this) : Bar<any>
1414
>callme : { (x: Bar<any>): Bar<any>; (x: object): string; }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//// [classVarianceResolveCircularity2.ts]
2+
// Issue #52813
3+
4+
export {};
5+
6+
class Bar<T> {
7+
num!: number;
8+
Value = callme(new Foo(this)).bar.num;
9+
Field: number = callme(new Foo(this)).bar.num;
10+
}
11+
declare function callme(x: Foo<any>): Foo<any>;
12+
declare function callme(x: object): string;
13+
14+
class Foo<T> {
15+
bar!: Bar<T>;
16+
constructor(bar: Bar<T>) {
17+
this.bar = bar;
18+
}
19+
}
20+
21+
//// [classVarianceResolveCircularity2.js]
22+
"use strict";
23+
// Issue #52813
24+
Object.defineProperty(exports, "__esModule", { value: true });
25+
var Bar = /** @class */ (function () {
26+
function Bar() {
27+
this.Value = callme(new Foo(this)).bar.num;
28+
this.Field = callme(new Foo(this)).bar.num;
29+
}
30+
return Bar;
31+
}());
32+
var Foo = /** @class */ (function () {
33+
function Foo(bar) {
34+
this.bar = bar;
35+
}
36+
return Foo;
37+
}());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
=== tests/cases/compiler/classVarianceResolveCircularity2.ts ===
2+
// Issue #52813
3+
4+
export {};
5+
6+
class Bar<T> {
7+
>Bar : Symbol(Bar, Decl(classVarianceResolveCircularity2.ts, 2, 10))
8+
>T : Symbol(T, Decl(classVarianceResolveCircularity2.ts, 4, 10))
9+
10+
num!: number;
11+
>num : Symbol(Bar.num, Decl(classVarianceResolveCircularity2.ts, 4, 14))
12+
13+
Value = callme(new Foo(this)).bar.num;
14+
>Value : Symbol(Bar.Value, Decl(classVarianceResolveCircularity2.ts, 5, 17))
15+
>callme(new Foo(this)).bar.num : Symbol(Bar.num, Decl(classVarianceResolveCircularity2.ts, 4, 14))
16+
>callme(new Foo(this)).bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14))
17+
>callme : Symbol(callme, Decl(classVarianceResolveCircularity2.ts, 8, 1), Decl(classVarianceResolveCircularity2.ts, 9, 47))
18+
>Foo : Symbol(Foo, Decl(classVarianceResolveCircularity2.ts, 10, 43))
19+
>this : Symbol(Bar, Decl(classVarianceResolveCircularity2.ts, 2, 10))
20+
>bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14))
21+
>num : Symbol(Bar.num, Decl(classVarianceResolveCircularity2.ts, 4, 14))
22+
23+
Field: number = callme(new Foo(this)).bar.num;
24+
>Field : Symbol(Bar.Field, Decl(classVarianceResolveCircularity2.ts, 6, 42))
25+
>callme(new Foo(this)).bar.num : Symbol(Bar.num, Decl(classVarianceResolveCircularity2.ts, 4, 14))
26+
>callme(new Foo(this)).bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14))
27+
>callme : Symbol(callme, Decl(classVarianceResolveCircularity2.ts, 8, 1), Decl(classVarianceResolveCircularity2.ts, 9, 47))
28+
>Foo : Symbol(Foo, Decl(classVarianceResolveCircularity2.ts, 10, 43))
29+
>this : Symbol(Bar, Decl(classVarianceResolveCircularity2.ts, 2, 10))
30+
>bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14))
31+
>num : Symbol(Bar.num, Decl(classVarianceResolveCircularity2.ts, 4, 14))
32+
}
33+
declare function callme(x: Foo<any>): Foo<any>;
34+
>callme : Symbol(callme, Decl(classVarianceResolveCircularity2.ts, 8, 1), Decl(classVarianceResolveCircularity2.ts, 9, 47))
35+
>x : Symbol(x, Decl(classVarianceResolveCircularity2.ts, 9, 24))
36+
>Foo : Symbol(Foo, Decl(classVarianceResolveCircularity2.ts, 10, 43))
37+
>Foo : Symbol(Foo, Decl(classVarianceResolveCircularity2.ts, 10, 43))
38+
39+
declare function callme(x: object): string;
40+
>callme : Symbol(callme, Decl(classVarianceResolveCircularity2.ts, 8, 1), Decl(classVarianceResolveCircularity2.ts, 9, 47))
41+
>x : Symbol(x, Decl(classVarianceResolveCircularity2.ts, 10, 24))
42+
43+
class Foo<T> {
44+
>Foo : Symbol(Foo, Decl(classVarianceResolveCircularity2.ts, 10, 43))
45+
>T : Symbol(T, Decl(classVarianceResolveCircularity2.ts, 12, 10))
46+
47+
bar!: Bar<T>;
48+
>bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14))
49+
>Bar : Symbol(Bar, Decl(classVarianceResolveCircularity2.ts, 2, 10))
50+
>T : Symbol(T, Decl(classVarianceResolveCircularity2.ts, 12, 10))
51+
52+
constructor(bar: Bar<T>) {
53+
>bar : Symbol(bar, Decl(classVarianceResolveCircularity2.ts, 14, 16))
54+
>Bar : Symbol(Bar, Decl(classVarianceResolveCircularity2.ts, 2, 10))
55+
>T : Symbol(T, Decl(classVarianceResolveCircularity2.ts, 12, 10))
56+
57+
this.bar = bar;
58+
>this.bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14))
59+
>this : Symbol(Foo, Decl(classVarianceResolveCircularity2.ts, 10, 43))
60+
>bar : Symbol(Foo.bar, Decl(classVarianceResolveCircularity2.ts, 12, 14))
61+
>bar : Symbol(bar, Decl(classVarianceResolveCircularity2.ts, 14, 16))
62+
}
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
=== tests/cases/compiler/classVarianceResolveCircularity2.ts ===
2+
// Issue #52813
3+
4+
export {};
5+
6+
class Bar<T> {
7+
>Bar : Bar<T>
8+
9+
num!: number;
10+
>num : number
11+
12+
Value = callme(new Foo(this)).bar.num;
13+
>Value : number
14+
>callme(new Foo(this)).bar.num : number
15+
>callme(new Foo(this)).bar : Bar<any>
16+
>callme(new Foo(this)) : Foo<any>
17+
>callme : { (x: Foo<any>): Foo<any>; (x: object): string; }
18+
>new Foo(this) : Foo<T>
19+
>Foo : typeof Foo
20+
>this : this
21+
>bar : Bar<any>
22+
>num : number
23+
24+
Field: number = callme(new Foo(this)).bar.num;
25+
>Field : number
26+
>callme(new Foo(this)).bar.num : number
27+
>callme(new Foo(this)).bar : Bar<any>
28+
>callme(new Foo(this)) : Foo<any>
29+
>callme : { (x: Foo<any>): Foo<any>; (x: object): string; }
30+
>new Foo(this) : Foo<T>
31+
>Foo : typeof Foo
32+
>this : this
33+
>bar : Bar<any>
34+
>num : number
35+
}
36+
declare function callme(x: Foo<any>): Foo<any>;
37+
>callme : { (x: Foo<any>): Foo<any>; (x: object): string; }
38+
>x : Foo<any>
39+
40+
declare function callme(x: object): string;
41+
>callme : { (x: Foo<any>): Foo<any>; (x: object): string; }
42+
>x : object
43+
44+
class Foo<T> {
45+
>Foo : Foo<T>
46+
47+
bar!: Bar<T>;
48+
>bar : Bar<T>
49+
50+
constructor(bar: Bar<T>) {
51+
>bar : Bar<T>
52+
53+
this.bar = bar;
54+
>this.bar = bar : Bar<T>
55+
>this.bar : Bar<T>
56+
>this : this
57+
>bar : Bar<T>
58+
>bar : Bar<T>
59+
}
60+
}

tests/cases/compiler/classVarianceResolveCircularity.ts renamed to tests/cases/compiler/classVarianceResolveCircularity1.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Issue #52813
44

55
class Bar<T> {
6-
num!: number; // Swap to remove error
6+
num!: number;
77
Value = callme(this).num;
88
Field: number = callme(this).num;
99
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// @strict: true
2+
3+
// Issue #52813
4+
5+
export {};
6+
7+
class Bar<T> {
8+
num!: number;
9+
Value = callme(new Foo(this)).bar.num;
10+
Field: number = callme(new Foo(this)).bar.num;
11+
}
12+
declare function callme(x: Foo<any>): Foo<any>;
13+
declare function callme(x: object): string;
14+
15+
class Foo<T> {
16+
bar!: Bar<T>;
17+
constructor(bar: Bar<T>) {
18+
this.bar = bar;
19+
}
20+
}

0 commit comments

Comments
 (0)