Skip to content

Commit 1ae5bef

Browse files
authored
Merge pull request #14874 from Microsoft/fixIndexedAccessRelation
Fix stack overflow in indexed access relation
2 parents 31701b6 + 0b8a9fc commit 1ae5bef

File tree

6 files changed

+294
-32
lines changed

6 files changed

+294
-32
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8525,16 +8525,9 @@ namespace ts {
85258525
}
85268526
}
85278527
else if (target.flags & TypeFlags.IndexedAccess) {
8528-
// if we have indexed access types with identical index types, see if relationship holds for
8529-
// the two object types.
8530-
if (source.flags & TypeFlags.IndexedAccess && (<IndexedAccessType>source).indexType === (<IndexedAccessType>target).indexType) {
8531-
if (result = isRelatedTo((<IndexedAccessType>source).objectType, (<IndexedAccessType>target).objectType, reportErrors)) {
8532-
return result;
8533-
}
8534-
}
85358528
// A type S is related to a type T[K] if S is related to A[K], where K is string-like and
85368529
// A is the apparent type of S.
8537-
const constraint = getBaseConstraintOfType(target);
8530+
const constraint = getConstraintOfType(<IndexedAccessType>target);
85388531
if (constraint) {
85398532
if (result = isRelatedTo(source, constraint, reportErrors)) {
85408533
errorInfo = saveErrorInfo;
@@ -8581,6 +8574,13 @@ namespace ts {
85818574
return result;
85828575
}
85838576
}
8577+
else if (target.flags & TypeFlags.IndexedAccess && (<IndexedAccessType>source).indexType === (<IndexedAccessType>target).indexType) {
8578+
// if we have indexed access types with identical index types, see if relationship holds for
8579+
// the two object types.
8580+
if (result = isRelatedTo((<IndexedAccessType>source).objectType, (<IndexedAccessType>target).objectType, reportErrors)) {
8581+
return result;
8582+
}
8583+
}
85848584
}
85858585
else {
85868586
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//// [indexedAccessRelation.ts]
2+
// Repro from #14723
3+
4+
class Component<S> {
5+
setState<K extends keyof S>(state: Pick<S, K>) {}
6+
}
7+
8+
export interface State<T> {
9+
a?: T;
10+
}
11+
12+
class Foo {}
13+
14+
class Comp<T extends Foo, S> extends Component<S & State<T>>
15+
{
16+
foo(a: T) {
17+
this.setState({ a: a });
18+
}
19+
}
20+
21+
22+
//// [indexedAccessRelation.js]
23+
// Repro from #14723
24+
"use strict";
25+
var __extends = (this && this.__extends) || (function () {
26+
var extendStatics = Object.setPrototypeOf ||
27+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
28+
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
29+
return function (d, b) {
30+
extendStatics(d, b);
31+
function __() { this.constructor = d; }
32+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
33+
};
34+
})();
35+
exports.__esModule = true;
36+
var Component = (function () {
37+
function Component() {
38+
}
39+
Component.prototype.setState = function (state) { };
40+
return Component;
41+
}());
42+
var Foo = (function () {
43+
function Foo() {
44+
}
45+
return Foo;
46+
}());
47+
var Comp = (function (_super) {
48+
__extends(Comp, _super);
49+
function Comp() {
50+
return _super !== null && _super.apply(this, arguments) || this;
51+
}
52+
Comp.prototype.foo = function (a) {
53+
this.setState({ a: a });
54+
};
55+
return Comp;
56+
}(Component));
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
=== tests/cases/compiler/indexedAccessRelation.ts ===
2+
// Repro from #14723
3+
4+
class Component<S> {
5+
>Component : Symbol(Component, Decl(indexedAccessRelation.ts, 0, 0))
6+
>S : Symbol(S, Decl(indexedAccessRelation.ts, 2, 16))
7+
8+
setState<K extends keyof S>(state: Pick<S, K>) {}
9+
>setState : Symbol(Component.setState, Decl(indexedAccessRelation.ts, 2, 20))
10+
>K : Symbol(K, Decl(indexedAccessRelation.ts, 3, 13))
11+
>S : Symbol(S, Decl(indexedAccessRelation.ts, 2, 16))
12+
>state : Symbol(state, Decl(indexedAccessRelation.ts, 3, 32))
13+
>Pick : Symbol(Pick, Decl(lib.d.ts, --, --))
14+
>S : Symbol(S, Decl(indexedAccessRelation.ts, 2, 16))
15+
>K : Symbol(K, Decl(indexedAccessRelation.ts, 3, 13))
16+
}
17+
18+
export interface State<T> {
19+
>State : Symbol(State, Decl(indexedAccessRelation.ts, 4, 1))
20+
>T : Symbol(T, Decl(indexedAccessRelation.ts, 6, 23))
21+
22+
a?: T;
23+
>a : Symbol(State.a, Decl(indexedAccessRelation.ts, 6, 27))
24+
>T : Symbol(T, Decl(indexedAccessRelation.ts, 6, 23))
25+
}
26+
27+
class Foo {}
28+
>Foo : Symbol(Foo, Decl(indexedAccessRelation.ts, 8, 1))
29+
30+
class Comp<T extends Foo, S> extends Component<S & State<T>>
31+
>Comp : Symbol(Comp, Decl(indexedAccessRelation.ts, 10, 12))
32+
>T : Symbol(T, Decl(indexedAccessRelation.ts, 12, 11))
33+
>Foo : Symbol(Foo, Decl(indexedAccessRelation.ts, 8, 1))
34+
>S : Symbol(S, Decl(indexedAccessRelation.ts, 12, 25))
35+
>Component : Symbol(Component, Decl(indexedAccessRelation.ts, 0, 0))
36+
>S : Symbol(S, Decl(indexedAccessRelation.ts, 12, 25))
37+
>State : Symbol(State, Decl(indexedAccessRelation.ts, 4, 1))
38+
>T : Symbol(T, Decl(indexedAccessRelation.ts, 12, 11))
39+
{
40+
foo(a: T) {
41+
>foo : Symbol(Comp.foo, Decl(indexedAccessRelation.ts, 13, 1))
42+
>a : Symbol(a, Decl(indexedAccessRelation.ts, 14, 8))
43+
>T : Symbol(T, Decl(indexedAccessRelation.ts, 12, 11))
44+
45+
this.setState({ a: a });
46+
>this.setState : Symbol(Component.setState, Decl(indexedAccessRelation.ts, 2, 20))
47+
>this : Symbol(Comp, Decl(indexedAccessRelation.ts, 10, 12))
48+
>setState : Symbol(Component.setState, Decl(indexedAccessRelation.ts, 2, 20))
49+
>a : Symbol(a, Decl(indexedAccessRelation.ts, 15, 23))
50+
>a : Symbol(a, Decl(indexedAccessRelation.ts, 14, 8))
51+
}
52+
}
53+
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
=== tests/cases/compiler/indexedAccessRelation.ts ===
2+
// Repro from #14723
3+
4+
class Component<S> {
5+
>Component : Component<S>
6+
>S : S
7+
8+
setState<K extends keyof S>(state: Pick<S, K>) {}
9+
>setState : <K extends keyof S>(state: Pick<S, K>) => void
10+
>K : K
11+
>S : S
12+
>state : Pick<S, K>
13+
>Pick : Pick<T, K>
14+
>S : S
15+
>K : K
16+
}
17+
18+
export interface State<T> {
19+
>State : State<T>
20+
>T : T
21+
22+
a?: T;
23+
>a : T
24+
>T : T
25+
}
26+
27+
class Foo {}
28+
>Foo : Foo
29+
30+
class Comp<T extends Foo, S> extends Component<S & State<T>>
31+
>Comp : Comp<T, S>
32+
>T : T
33+
>Foo : Foo
34+
>S : S
35+
>Component : Component<S & State<T>>
36+
>S : S
37+
>State : State<T>
38+
>T : T
39+
{
40+
foo(a: T) {
41+
>foo : (a: T) => void
42+
>a : T
43+
>T : T
44+
45+
this.setState({ a: a });
46+
>this.setState({ a: a }) : void
47+
>this.setState : <K extends keyof (S & State<T>)>(state: Pick<S & State<T>, K>) => void
48+
>this : this
49+
>setState : <K extends keyof (S & State<T>)>(state: Pick<S & State<T>, K>) => void
50+
>{ a: a } : { a: T; }
51+
>a : T
52+
>a : T
53+
}
54+
}
55+

0 commit comments

Comments
 (0)