Skip to content

Commit fd4ac10

Browse files
authored
Merge pull request microsoft#20400 from Microsoft/limit-recursive-structured-type-resolution
Limit recursive structured type resolution
2 parents 81fbe12 + 2df7a89 commit fd4ac10

9 files changed

Lines changed: 254 additions & 50 deletions

src/compiler/checker.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5809,6 +5809,7 @@ namespace ts {
58095809
if (source.symbol && members === getMembersOfSymbol(source.symbol)) {
58105810
members = createSymbolTable(source.declaredProperties);
58115811
}
5812+
setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
58125813
const thisArgument = lastOrUndefined(typeArguments);
58135814
for (const baseType of baseTypes) {
58145815
const instantiatedBaseType = thisArgument ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType;
@@ -6071,6 +6072,7 @@ namespace ts {
60716072
if (symbol.exports) {
60726073
members = getExportsOfSymbol(symbol);
60736074
}
6075+
setStructuredTypeMembers(type, members, emptyArray, emptyArray, undefined, undefined);
60746076
if (symbol.flags & SymbolFlags.Class) {
60756077
const classType = getDeclaredTypeOfClassOrInterface(symbol);
60766078
const baseConstructorType = getBaseConstructorTypeOfClass(classType);

tests/baselines/reference/dynamicNames.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -138,17 +138,21 @@ export const o1_s2 = o1[s2];
138138
export const o2: T0 = o1;
139139

140140
// recursive declarations
141-
declare const rI: RI;
142-
interface RI {
143-
x: "a";
141+
// (type parameter indirection courtesy of #20400)
142+
declare const rI: RI<"a">;
143+
rI.x
144+
interface RI<T extends "a" | "b"> {
145+
x: T;
144146
[rI.x]: "b";
145147
}
146148

147-
declare const rC: RC;
148-
declare class RC {
149-
x: "a";
149+
declare const rC: RC<"a">;
150+
rC.x
151+
declare class RC<T extends "a" | "b"> {
152+
x: T;
150153
[rC.x]: "b";
151-
}
154+
}
155+
152156

153157
//// [module.js]
154158
"use strict";
@@ -205,6 +209,8 @@ exports.o1_c4 = exports.o1[exports.c4];
205209
exports.o1_c5 = exports.o1[exports.c5];
206210
exports.o1_s2 = exports.o1[exports.s2];
207211
exports.o2 = exports.o1;
212+
rI.x;
213+
rC.x;
208214

209215

210216
//// [module.d.ts]

tests/baselines/reference/dynamicNames.symbols

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -443,34 +443,50 @@ export const o2: T0 = o1;
443443
>o1 : Symbol(o1, Decl(main.ts, 101, 12))
444444

445445
// recursive declarations
446-
declare const rI: RI;
447-
>rI : Symbol(rI, Decl(main.ts, 115, 13))
448-
>RI : Symbol(RI, Decl(main.ts, 115, 21))
446+
// (type parameter indirection courtesy of #20400)
447+
declare const rI: RI<"a">;
448+
>rI : Symbol(rI, Decl(main.ts, 116, 13))
449+
>RI : Symbol(RI, Decl(main.ts, 117, 4))
449450

450-
interface RI {
451-
>RI : Symbol(RI, Decl(main.ts, 115, 21))
451+
rI.x
452+
>rI.x : Symbol(RI.x, Decl(main.ts, 118, 35))
453+
>rI : Symbol(rI, Decl(main.ts, 116, 13))
454+
>x : Symbol(RI.x, Decl(main.ts, 118, 35))
452455

453-
x: "a";
454-
>x : Symbol(RI.x, Decl(main.ts, 116, 14))
456+
interface RI<T extends "a" | "b"> {
457+
>RI : Symbol(RI, Decl(main.ts, 117, 4))
458+
>T : Symbol(T, Decl(main.ts, 118, 13))
459+
460+
x: T;
461+
>x : Symbol(RI.x, Decl(main.ts, 118, 35))
462+
>T : Symbol(T, Decl(main.ts, 118, 13))
455463

456464
[rI.x]: "b";
457-
>rI.x : Symbol(RI.x, Decl(main.ts, 116, 14))
458-
>rI : Symbol(rI, Decl(main.ts, 115, 13))
459-
>x : Symbol(RI.x, Decl(main.ts, 116, 14))
465+
>rI.x : Symbol(RI.x, Decl(main.ts, 118, 35))
466+
>rI : Symbol(rI, Decl(main.ts, 116, 13))
467+
>x : Symbol(RI.x, Decl(main.ts, 118, 35))
460468
}
461469

462-
declare const rC: RC;
463-
>rC : Symbol(rC, Decl(main.ts, 121, 13))
464-
>RC : Symbol(RC, Decl(main.ts, 121, 21))
470+
declare const rC: RC<"a">;
471+
>rC : Symbol(rC, Decl(main.ts, 123, 13))
472+
>RC : Symbol(RC, Decl(main.ts, 124, 4))
473+
474+
rC.x
475+
>rC.x : Symbol(RC.x, Decl(main.ts, 125, 39))
476+
>rC : Symbol(rC, Decl(main.ts, 123, 13))
477+
>x : Symbol(RC.x, Decl(main.ts, 125, 39))
465478

466-
declare class RC {
467-
>RC : Symbol(RC, Decl(main.ts, 121, 21))
479+
declare class RC<T extends "a" | "b"> {
480+
>RC : Symbol(RC, Decl(main.ts, 124, 4))
481+
>T : Symbol(T, Decl(main.ts, 125, 17))
468482

469-
x: "a";
470-
>x : Symbol(RC.x, Decl(main.ts, 122, 18))
483+
x: T;
484+
>x : Symbol(RC.x, Decl(main.ts, 125, 39))
485+
>T : Symbol(T, Decl(main.ts, 125, 17))
471486

472487
[rC.x]: "b";
473-
>rC.x : Symbol(RC.x, Decl(main.ts, 122, 18))
474-
>rC : Symbol(rC, Decl(main.ts, 121, 13))
475-
>x : Symbol(RC.x, Decl(main.ts, 122, 18))
488+
>rC.x : Symbol(RC.x, Decl(main.ts, 125, 39))
489+
>rC : Symbol(rC, Decl(main.ts, 123, 13))
490+
>x : Symbol(RC.x, Decl(main.ts, 125, 39))
476491
}
492+

tests/baselines/reference/dynamicNames.types

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -519,34 +519,50 @@ export const o2: T0 = o1;
519519
>o1 : { [c4]: number; [c5]: string; [s2]: boolean; }
520520

521521
// recursive declarations
522-
declare const rI: RI;
523-
>rI : RI
524-
>RI : RI
522+
// (type parameter indirection courtesy of #20400)
523+
declare const rI: RI<"a">;
524+
>rI : RI<"a">
525+
>RI : RI<T>
525526

526-
interface RI {
527-
>RI : RI
528-
529-
x: "a";
527+
rI.x
528+
>rI.x : "a"
529+
>rI : RI<"a">
530530
>x : "a"
531531

532+
interface RI<T extends "a" | "b"> {
533+
>RI : RI<T>
534+
>T : T
535+
536+
x: T;
537+
>x : T
538+
>T : T
539+
532540
[rI.x]: "b";
533541
>rI.x : "a"
534-
>rI : RI
542+
>rI : RI<"a">
535543
>x : "a"
536544
}
537545

538-
declare const rC: RC;
539-
>rC : RC
540-
>RC : RC
541-
542-
declare class RC {
543-
>RC : RC
546+
declare const rC: RC<"a">;
547+
>rC : RC<"a">
548+
>RC : RC<T>
544549

545-
x: "a";
550+
rC.x
551+
>rC.x : "a"
552+
>rC : RC<"a">
546553
>x : "a"
547554

555+
declare class RC<T extends "a" | "b"> {
556+
>RC : RC<T>
557+
>T : T
558+
559+
x: T;
560+
>x : T
561+
>T : T
562+
548563
[rC.x]: "b";
549564
>rC.x : "a"
550-
>rC : RC
565+
>rC : RC<"a">
551566
>x : "a"
552567
}
568+
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//// [mutuallyRecursiveInference.ts]
2+
class T<A> {
3+
a: A;
4+
b: any
5+
}
6+
class L<RT extends { a: 'a' | 'b', b: any }> extends T<RT[RT['a']]> {
7+
m() { this.a }
8+
}
9+
class X extends L<X> {
10+
a: 'a' | 'b'
11+
b: number
12+
m2() {
13+
this.a
14+
}
15+
}
16+
17+
18+
//// [mutuallyRecursiveInference.js]
19+
var __extends = (this && this.__extends) || (function () {
20+
var extendStatics = Object.setPrototypeOf ||
21+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
22+
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
23+
return function (d, b) {
24+
extendStatics(d, b);
25+
function __() { this.constructor = d; }
26+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
27+
};
28+
})();
29+
var T = /** @class */ (function () {
30+
function T() {
31+
}
32+
return T;
33+
}());
34+
var L = /** @class */ (function (_super) {
35+
__extends(L, _super);
36+
function L() {
37+
return _super !== null && _super.apply(this, arguments) || this;
38+
}
39+
L.prototype.m = function () { this.a; };
40+
return L;
41+
}(T));
42+
var X = /** @class */ (function (_super) {
43+
__extends(X, _super);
44+
function X() {
45+
return _super !== null && _super.apply(this, arguments) || this;
46+
}
47+
X.prototype.m2 = function () {
48+
this.a;
49+
};
50+
return X;
51+
}(L));
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
=== tests/cases/compiler/mutuallyRecursiveInference.ts ===
2+
class T<A> {
3+
>T : Symbol(T, Decl(mutuallyRecursiveInference.ts, 0, 0))
4+
>A : Symbol(A, Decl(mutuallyRecursiveInference.ts, 0, 8))
5+
6+
a: A;
7+
>a : Symbol(T.a, Decl(mutuallyRecursiveInference.ts, 0, 12))
8+
>A : Symbol(A, Decl(mutuallyRecursiveInference.ts, 0, 8))
9+
10+
b: any
11+
>b : Symbol(T.b, Decl(mutuallyRecursiveInference.ts, 1, 9))
12+
}
13+
class L<RT extends { a: 'a' | 'b', b: any }> extends T<RT[RT['a']]> {
14+
>L : Symbol(L, Decl(mutuallyRecursiveInference.ts, 3, 1))
15+
>RT : Symbol(RT, Decl(mutuallyRecursiveInference.ts, 4, 8))
16+
>a : Symbol(a, Decl(mutuallyRecursiveInference.ts, 4, 20))
17+
>b : Symbol(b, Decl(mutuallyRecursiveInference.ts, 4, 34))
18+
>T : Symbol(T, Decl(mutuallyRecursiveInference.ts, 0, 0))
19+
>RT : Symbol(RT, Decl(mutuallyRecursiveInference.ts, 4, 8))
20+
>RT : Symbol(RT, Decl(mutuallyRecursiveInference.ts, 4, 8))
21+
22+
m() { this.a }
23+
>m : Symbol(L.m, Decl(mutuallyRecursiveInference.ts, 4, 69))
24+
>this.a : Symbol(T.a, Decl(mutuallyRecursiveInference.ts, 0, 12))
25+
>this : Symbol(L, Decl(mutuallyRecursiveInference.ts, 3, 1))
26+
>a : Symbol(T.a, Decl(mutuallyRecursiveInference.ts, 0, 12))
27+
}
28+
class X extends L<X> {
29+
>X : Symbol(X, Decl(mutuallyRecursiveInference.ts, 6, 1))
30+
>L : Symbol(L, Decl(mutuallyRecursiveInference.ts, 3, 1))
31+
>X : Symbol(X, Decl(mutuallyRecursiveInference.ts, 6, 1))
32+
33+
a: 'a' | 'b'
34+
>a : Symbol(X.a, Decl(mutuallyRecursiveInference.ts, 7, 22))
35+
36+
b: number
37+
>b : Symbol(X.b, Decl(mutuallyRecursiveInference.ts, 8, 16))
38+
39+
m2() {
40+
>m2 : Symbol(X.m2, Decl(mutuallyRecursiveInference.ts, 9, 13))
41+
42+
this.a
43+
>this.a : Symbol(X.a, Decl(mutuallyRecursiveInference.ts, 7, 22))
44+
>this : Symbol(X, Decl(mutuallyRecursiveInference.ts, 6, 1))
45+
>a : Symbol(X.a, Decl(mutuallyRecursiveInference.ts, 7, 22))
46+
}
47+
}
48+
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
=== tests/cases/compiler/mutuallyRecursiveInference.ts ===
2+
class T<A> {
3+
>T : T<A>
4+
>A : A
5+
6+
a: A;
7+
>a : A
8+
>A : A
9+
10+
b: any
11+
>b : any
12+
}
13+
class L<RT extends { a: 'a' | 'b', b: any }> extends T<RT[RT['a']]> {
14+
>L : L<RT>
15+
>RT : RT
16+
>a : "a" | "b"
17+
>b : any
18+
>T : T<RT[RT["a"]]>
19+
>RT : RT
20+
>RT : RT
21+
22+
m() { this.a }
23+
>m : () => void
24+
>this.a : RT[RT["a"]]
25+
>this : this
26+
>a : RT[RT["a"]]
27+
}
28+
class X extends L<X> {
29+
>X : X
30+
>L : L<X>
31+
>X : X
32+
33+
a: 'a' | 'b'
34+
>a : "a" | "b"
35+
36+
b: number
37+
>b : number
38+
39+
m2() {
40+
>m2 : () => void
41+
42+
this.a
43+
>this.a : "a" | "b"
44+
>this : this
45+
>a : "a" | "b"
46+
}
47+
}
48+

tests/cases/compiler/dynamicNames.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,17 @@ export const o1_s2 = o1[s2];
140140
export const o2: T0 = o1;
141141

142142
// recursive declarations
143-
declare const rI: RI;
144-
interface RI {
145-
x: "a";
143+
// (type parameter indirection courtesy of #20400)
144+
declare const rI: RI<"a">;
145+
rI.x
146+
interface RI<T extends "a" | "b"> {
147+
x: T;
146148
[rI.x]: "b";
147149
}
148150

149-
declare const rC: RC;
150-
declare class RC {
151-
x: "a";
151+
declare const rC: RC<"a">;
152+
rC.x
153+
declare class RC<T extends "a" | "b"> {
154+
x: T;
152155
[rC.x]: "b";
153-
}
156+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class T<A> {
2+
a: A;
3+
b: any
4+
}
5+
class L<RT extends { a: 'a' | 'b', b: any }> extends T<RT[RT['a']]> {
6+
m() { this.a }
7+
}
8+
class X extends L<X> {
9+
a: 'a' | 'b'
10+
b: number
11+
m2() {
12+
this.a
13+
}
14+
}

0 commit comments

Comments
 (0)