Skip to content

Commit 366d3f4

Browse files
committed
Check target equivalence in isMatchingReference before computing property key equivalence
Fixes microsoft#61606. Need PR results to see if this is worth it or not.
1 parent b263cc4 commit 366d3f4

File tree

5 files changed

+194
-3
lines changed

5 files changed

+194
-3
lines changed

src/compiler/checker.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27184,9 +27184,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2718427184
case SyntaxKind.ElementAccessExpression:
2718527185
const sourcePropertyName = getAccessedPropertyName(source as AccessExpression);
2718627186
if (sourcePropertyName !== undefined) {
27187-
const targetPropertyName = isAccessExpression(target) ? getAccessedPropertyName(target) : undefined;
27188-
if (targetPropertyName !== undefined) {
27189-
return targetPropertyName === sourcePropertyName && isMatchingReference((source as AccessExpression).expression, (target as AccessExpression).expression);
27187+
if (isAccessExpression(target) && isMatchingReference((source as AccessExpression).expression, target.expression)) {
27188+
const targetPropertyName = isAccessExpression(target) ? getAccessedPropertyName(target) : undefined;
27189+
if (targetPropertyName !== undefined) {
27190+
return targetPropertyName === sourcePropertyName;
27191+
}
2719027192
}
2719127193
}
2719227194
if (isElementAccessExpression(source) && isElementAccessExpression(target) && isIdentifier(source.argumentExpression) && isIdentifier(target.argumentExpression)) {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//// [tests/cases/compiler/circularRefFromClassMember.ts] ////
2+
3+
//// [circularRefFromClassMember.ts]
4+
// Test for #61606
5+
6+
const result: boolean[] = [];
7+
class Test {
8+
n: 42 | "" = 42 as any;
9+
foo(): void {
10+
if (this.n === "") {
11+
return;
12+
}
13+
for (let i = 0; i < 1; i++) {
14+
const localN = this.n;
15+
const localN_alias = localN;
16+
result[localN_alias] = true;
17+
}
18+
}
19+
}
20+
21+
22+
//// [circularRefFromClassMember.js]
23+
// Test for #61606
24+
var result = [];
25+
var Test = /** @class */ (function () {
26+
function Test() {
27+
this.n = 42;
28+
}
29+
Test.prototype.foo = function () {
30+
if (this.n === "") {
31+
return;
32+
}
33+
for (var i = 0; i < 1; i++) {
34+
var localN = this.n;
35+
var localN_alias = localN;
36+
result[localN_alias] = true;
37+
}
38+
};
39+
return Test;
40+
}());
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//// [tests/cases/compiler/circularRefFromClassMember.ts] ////
2+
3+
=== circularRefFromClassMember.ts ===
4+
// Test for #61606
5+
6+
const result: boolean[] = [];
7+
>result : Symbol(result, Decl(circularRefFromClassMember.ts, 2, 5))
8+
9+
class Test {
10+
>Test : Symbol(Test, Decl(circularRefFromClassMember.ts, 2, 29))
11+
12+
n: 42 | "" = 42 as any;
13+
>n : Symbol(Test.n, Decl(circularRefFromClassMember.ts, 3, 12))
14+
15+
foo(): void {
16+
>foo : Symbol(Test.foo, Decl(circularRefFromClassMember.ts, 4, 27))
17+
18+
if (this.n === "") {
19+
>this.n : Symbol(Test.n, Decl(circularRefFromClassMember.ts, 3, 12))
20+
>this : Symbol(Test, Decl(circularRefFromClassMember.ts, 2, 29))
21+
>n : Symbol(Test.n, Decl(circularRefFromClassMember.ts, 3, 12))
22+
23+
return;
24+
}
25+
for (let i = 0; i < 1; i++) {
26+
>i : Symbol(i, Decl(circularRefFromClassMember.ts, 9, 16))
27+
>i : Symbol(i, Decl(circularRefFromClassMember.ts, 9, 16))
28+
>i : Symbol(i, Decl(circularRefFromClassMember.ts, 9, 16))
29+
30+
const localN = this.n;
31+
>localN : Symbol(localN, Decl(circularRefFromClassMember.ts, 10, 17))
32+
>this.n : Symbol(Test.n, Decl(circularRefFromClassMember.ts, 3, 12))
33+
>this : Symbol(Test, Decl(circularRefFromClassMember.ts, 2, 29))
34+
>n : Symbol(Test.n, Decl(circularRefFromClassMember.ts, 3, 12))
35+
36+
const localN_alias = localN;
37+
>localN_alias : Symbol(localN_alias, Decl(circularRefFromClassMember.ts, 11, 17))
38+
>localN : Symbol(localN, Decl(circularRefFromClassMember.ts, 10, 17))
39+
40+
result[localN_alias] = true;
41+
>result : Symbol(result, Decl(circularRefFromClassMember.ts, 2, 5))
42+
>localN_alias : Symbol(localN_alias, Decl(circularRefFromClassMember.ts, 11, 17))
43+
}
44+
}
45+
}
46+
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//// [tests/cases/compiler/circularRefFromClassMember.ts] ////
2+
3+
=== circularRefFromClassMember.ts ===
4+
// Test for #61606
5+
6+
const result: boolean[] = [];
7+
>result : boolean[]
8+
> : ^^^^^^^^^
9+
>[] : undefined[]
10+
> : ^^^^^^^^^^^
11+
12+
class Test {
13+
>Test : Test
14+
> : ^^^^
15+
16+
n: 42 | "" = 42 as any;
17+
>n : "" | 42
18+
> : ^^^^^^^
19+
>42 as any : any
20+
>42 : 42
21+
> : ^^
22+
23+
foo(): void {
24+
>foo : () => void
25+
> : ^^^^^^
26+
27+
if (this.n === "") {
28+
>this.n === "" : boolean
29+
> : ^^^^^^^
30+
>this.n : "" | 42
31+
> : ^^^^^^^
32+
>this : this
33+
> : ^^^^
34+
>n : "" | 42
35+
> : ^^^^^^^
36+
>"" : ""
37+
> : ^^
38+
39+
return;
40+
}
41+
for (let i = 0; i < 1; i++) {
42+
>i : number
43+
> : ^^^^^^
44+
>0 : 0
45+
> : ^
46+
>i < 1 : boolean
47+
> : ^^^^^^^
48+
>i : number
49+
> : ^^^^^^
50+
>1 : 1
51+
> : ^
52+
>i++ : number
53+
> : ^^^^^^
54+
>i : number
55+
> : ^^^^^^
56+
57+
const localN = this.n;
58+
>localN : 42
59+
> : ^^
60+
>this.n : 42
61+
> : ^^
62+
>this : this
63+
> : ^^^^
64+
>n : 42
65+
> : ^^
66+
67+
const localN_alias = localN;
68+
>localN_alias : 42
69+
> : ^^
70+
>localN : 42
71+
> : ^^
72+
73+
result[localN_alias] = true;
74+
>result[localN_alias] = true : true
75+
> : ^^^^
76+
>result[localN_alias] : boolean
77+
> : ^^^^^^^
78+
>result : boolean[]
79+
> : ^^^^^^^^^
80+
>localN_alias : 42
81+
> : ^^
82+
>true : true
83+
> : ^^^^
84+
}
85+
}
86+
}
87+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Test for #61606
2+
3+
const result: boolean[] = [];
4+
class Test {
5+
n: 42 | "" = 42 as any;
6+
foo(): void {
7+
if (this.n === "") {
8+
return;
9+
}
10+
for (let i = 0; i < 1; i++) {
11+
const localN = this.n;
12+
const localN_alias = localN;
13+
result[localN_alias] = true;
14+
}
15+
}
16+
}

0 commit comments

Comments
 (0)