Skip to content

Commit 303297a

Browse files
authored
Merge pull request #32362 from microsoft/fix32230
Fix type parameter inference cache invalidation logic
2 parents 851156d + 4b9ca33 commit 303297a

File tree

5 files changed

+199
-4
lines changed

5 files changed

+199
-4
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15266,15 +15266,23 @@ namespace ts {
1526615266
const inference = inferences[i];
1526715267
if (t === inference.typeParameter) {
1526815268
if (fix && !inference.isFixed) {
15269+
clearCachedInferences(inferences);
1526915270
inference.isFixed = true;
15270-
inference.inferredType = undefined;
1527115271
}
1527215272
return getInferredType(context, i);
1527315273
}
1527415274
}
1527515275
return t;
1527615276
}
1527715277

15278+
function clearCachedInferences(inferences: InferenceInfo[]) {
15279+
for (const inference of inferences) {
15280+
if (!inference.isFixed) {
15281+
inference.inferredType = undefined;
15282+
}
15283+
}
15284+
}
15285+
1527815286
function createInferenceInfo(typeParameter: TypeParameter): InferenceInfo {
1527915287
return {
1528015288
typeParameter,
@@ -15554,17 +15562,17 @@ namespace ts {
1555415562
if (contravariant && !bivariant) {
1555515563
if (!contains(inference.contraCandidates, candidate)) {
1555615564
inference.contraCandidates = append(inference.contraCandidates, candidate);
15557-
inference.inferredType = undefined;
15565+
clearCachedInferences(inferences);
1555815566
}
1555915567
}
1556015568
else if (!contains(inference.candidates, candidate)) {
1556115569
inference.candidates = append(inference.candidates, candidate);
15562-
inference.inferredType = undefined;
15570+
clearCachedInferences(inferences);
1556315571
}
1556415572
}
1556515573
if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && inference.topLevel && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
1556615574
inference.topLevel = false;
15567-
inference.inferredType = undefined;
15575+
clearCachedInferences(inferences);
1556815576
}
1556915577
}
1557015578
return;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//// [typeInferenceCacheInvalidation.ts]
2+
// Repro from #32230
3+
4+
type Callback<TFoo, TBar> = (foo: TFoo, bar: TBar) => any
5+
6+
declare function example<TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(
7+
foo: TFoo,
8+
callback: TCallback,
9+
bar: TBar,
10+
): TCallback
11+
12+
example(42, (foo, bar) => ({
13+
t: () => {
14+
let s: string = bar;
15+
}
16+
}), '42');
17+
18+
example(42, (foo, bar) => ({
19+
t() {
20+
let s: string = bar;
21+
}
22+
}), '42');
23+
24+
25+
//// [typeInferenceCacheInvalidation.js]
26+
"use strict";
27+
// Repro from #32230
28+
example(42, function (foo, bar) { return ({
29+
t: function () {
30+
var s = bar;
31+
}
32+
}); }, '42');
33+
example(42, function (foo, bar) { return ({
34+
t: function () {
35+
var s = bar;
36+
}
37+
}); }, '42');
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
=== tests/cases/compiler/typeInferenceCacheInvalidation.ts ===
2+
// Repro from #32230
3+
4+
type Callback<TFoo, TBar> = (foo: TFoo, bar: TBar) => any
5+
>Callback : Symbol(Callback, Decl(typeInferenceCacheInvalidation.ts, 0, 0))
6+
>TFoo : Symbol(TFoo, Decl(typeInferenceCacheInvalidation.ts, 2, 14))
7+
>TBar : Symbol(TBar, Decl(typeInferenceCacheInvalidation.ts, 2, 19))
8+
>foo : Symbol(foo, Decl(typeInferenceCacheInvalidation.ts, 2, 29))
9+
>TFoo : Symbol(TFoo, Decl(typeInferenceCacheInvalidation.ts, 2, 14))
10+
>bar : Symbol(bar, Decl(typeInferenceCacheInvalidation.ts, 2, 39))
11+
>TBar : Symbol(TBar, Decl(typeInferenceCacheInvalidation.ts, 2, 19))
12+
13+
declare function example<TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(
14+
>example : Symbol(example, Decl(typeInferenceCacheInvalidation.ts, 2, 57))
15+
>TFoo : Symbol(TFoo, Decl(typeInferenceCacheInvalidation.ts, 4, 25))
16+
>TBar : Symbol(TBar, Decl(typeInferenceCacheInvalidation.ts, 4, 30))
17+
>TCallback : Symbol(TCallback, Decl(typeInferenceCacheInvalidation.ts, 4, 36))
18+
>Callback : Symbol(Callback, Decl(typeInferenceCacheInvalidation.ts, 0, 0))
19+
>TFoo : Symbol(TFoo, Decl(typeInferenceCacheInvalidation.ts, 4, 25))
20+
>TBar : Symbol(TBar, Decl(typeInferenceCacheInvalidation.ts, 4, 30))
21+
22+
foo: TFoo,
23+
>foo : Symbol(foo, Decl(typeInferenceCacheInvalidation.ts, 4, 77))
24+
>TFoo : Symbol(TFoo, Decl(typeInferenceCacheInvalidation.ts, 4, 25))
25+
26+
callback: TCallback,
27+
>callback : Symbol(callback, Decl(typeInferenceCacheInvalidation.ts, 5, 14))
28+
>TCallback : Symbol(TCallback, Decl(typeInferenceCacheInvalidation.ts, 4, 36))
29+
30+
bar: TBar,
31+
>bar : Symbol(bar, Decl(typeInferenceCacheInvalidation.ts, 6, 24))
32+
>TBar : Symbol(TBar, Decl(typeInferenceCacheInvalidation.ts, 4, 30))
33+
34+
): TCallback
35+
>TCallback : Symbol(TCallback, Decl(typeInferenceCacheInvalidation.ts, 4, 36))
36+
37+
example(42, (foo, bar) => ({
38+
>example : Symbol(example, Decl(typeInferenceCacheInvalidation.ts, 2, 57))
39+
>foo : Symbol(foo, Decl(typeInferenceCacheInvalidation.ts, 10, 13))
40+
>bar : Symbol(bar, Decl(typeInferenceCacheInvalidation.ts, 10, 17))
41+
42+
t: () => {
43+
>t : Symbol(t, Decl(typeInferenceCacheInvalidation.ts, 10, 28))
44+
45+
let s: string = bar;
46+
>s : Symbol(s, Decl(typeInferenceCacheInvalidation.ts, 12, 11))
47+
>bar : Symbol(bar, Decl(typeInferenceCacheInvalidation.ts, 10, 17))
48+
}
49+
}), '42');
50+
51+
example(42, (foo, bar) => ({
52+
>example : Symbol(example, Decl(typeInferenceCacheInvalidation.ts, 2, 57))
53+
>foo : Symbol(foo, Decl(typeInferenceCacheInvalidation.ts, 16, 13))
54+
>bar : Symbol(bar, Decl(typeInferenceCacheInvalidation.ts, 16, 17))
55+
56+
t() {
57+
>t : Symbol(t, Decl(typeInferenceCacheInvalidation.ts, 16, 28))
58+
59+
let s: string = bar;
60+
>s : Symbol(s, Decl(typeInferenceCacheInvalidation.ts, 18, 11))
61+
>bar : Symbol(bar, Decl(typeInferenceCacheInvalidation.ts, 16, 17))
62+
}
63+
}), '42');
64+
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
=== tests/cases/compiler/typeInferenceCacheInvalidation.ts ===
2+
// Repro from #32230
3+
4+
type Callback<TFoo, TBar> = (foo: TFoo, bar: TBar) => any
5+
>Callback : Callback<TFoo, TBar>
6+
>foo : TFoo
7+
>bar : TBar
8+
9+
declare function example<TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(
10+
>example : <TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(foo: TFoo, callback: TCallback, bar: TBar) => TCallback
11+
12+
foo: TFoo,
13+
>foo : TFoo
14+
15+
callback: TCallback,
16+
>callback : TCallback
17+
18+
bar: TBar,
19+
>bar : TBar
20+
21+
): TCallback
22+
23+
example(42, (foo, bar) => ({
24+
>example(42, (foo, bar) => ({ t: () => { let s: string = bar; }}), '42') : (foo: number, bar: string) => { t: () => void; }
25+
>example : <TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(foo: TFoo, callback: TCallback, bar: TBar) => TCallback
26+
>42 : 42
27+
>(foo, bar) => ({ t: () => { let s: string = bar; }}) : (foo: number, bar: string) => { t: () => void; }
28+
>foo : number
29+
>bar : string
30+
>({ t: () => { let s: string = bar; }}) : { t: () => void; }
31+
>{ t: () => { let s: string = bar; }} : { t: () => void; }
32+
33+
t: () => {
34+
>t : () => void
35+
>() => { let s: string = bar; } : () => void
36+
37+
let s: string = bar;
38+
>s : string
39+
>bar : string
40+
}
41+
}), '42');
42+
>'42' : "42"
43+
44+
example(42, (foo, bar) => ({
45+
>example(42, (foo, bar) => ({ t() { let s: string = bar; }}), '42') : (foo: number, bar: string) => { t(): void; }
46+
>example : <TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(foo: TFoo, callback: TCallback, bar: TBar) => TCallback
47+
>42 : 42
48+
>(foo, bar) => ({ t() { let s: string = bar; }}) : (foo: number, bar: string) => { t(): void; }
49+
>foo : number
50+
>bar : string
51+
>({ t() { let s: string = bar; }}) : { t(): void; }
52+
>{ t() { let s: string = bar; }} : { t(): void; }
53+
54+
t() {
55+
>t : () => void
56+
57+
let s: string = bar;
58+
>s : string
59+
>bar : string
60+
}
61+
}), '42');
62+
>'42' : "42"
63+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// @strict: true
2+
3+
// Repro from #32230
4+
5+
type Callback<TFoo, TBar> = (foo: TFoo, bar: TBar) => any
6+
7+
declare function example<TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(
8+
foo: TFoo,
9+
callback: TCallback,
10+
bar: TBar,
11+
): TCallback
12+
13+
example(42, (foo, bar) => ({
14+
t: () => {
15+
let s: string = bar;
16+
}
17+
}), '42');
18+
19+
example(42, (foo, bar) => ({
20+
t() {
21+
let s: string = bar;
22+
}
23+
}), '42');

0 commit comments

Comments
 (0)