Merge pull request #32362 from microsoft/fix32230
Fix type parameter inference cache invalidation logic
This commit is contained in:
commit
303297aa27
5 changed files with 199 additions and 4 deletions
|
@ -15266,8 +15266,8 @@ namespace ts {
|
||||||
const inference = inferences[i];
|
const inference = inferences[i];
|
||||||
if (t === inference.typeParameter) {
|
if (t === inference.typeParameter) {
|
||||||
if (fix && !inference.isFixed) {
|
if (fix && !inference.isFixed) {
|
||||||
|
clearCachedInferences(inferences);
|
||||||
inference.isFixed = true;
|
inference.isFixed = true;
|
||||||
inference.inferredType = undefined;
|
|
||||||
}
|
}
|
||||||
return getInferredType(context, i);
|
return getInferredType(context, i);
|
||||||
}
|
}
|
||||||
|
@ -15275,6 +15275,14 @@ namespace ts {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearCachedInferences(inferences: InferenceInfo[]) {
|
||||||
|
for (const inference of inferences) {
|
||||||
|
if (!inference.isFixed) {
|
||||||
|
inference.inferredType = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function createInferenceInfo(typeParameter: TypeParameter): InferenceInfo {
|
function createInferenceInfo(typeParameter: TypeParameter): InferenceInfo {
|
||||||
return {
|
return {
|
||||||
typeParameter,
|
typeParameter,
|
||||||
|
@ -15554,17 +15562,17 @@ namespace ts {
|
||||||
if (contravariant && !bivariant) {
|
if (contravariant && !bivariant) {
|
||||||
if (!contains(inference.contraCandidates, candidate)) {
|
if (!contains(inference.contraCandidates, candidate)) {
|
||||||
inference.contraCandidates = append(inference.contraCandidates, candidate);
|
inference.contraCandidates = append(inference.contraCandidates, candidate);
|
||||||
inference.inferredType = undefined;
|
clearCachedInferences(inferences);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!contains(inference.candidates, candidate)) {
|
else if (!contains(inference.candidates, candidate)) {
|
||||||
inference.candidates = append(inference.candidates, candidate);
|
inference.candidates = append(inference.candidates, candidate);
|
||||||
inference.inferredType = undefined;
|
clearCachedInferences(inferences);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && inference.topLevel && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
|
if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && inference.topLevel && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
|
||||||
inference.topLevel = false;
|
inference.topLevel = false;
|
||||||
inference.inferredType = undefined;
|
clearCachedInferences(inferences);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
37
tests/baselines/reference/typeInferenceCacheInvalidation.js
Normal file
37
tests/baselines/reference/typeInferenceCacheInvalidation.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
//// [typeInferenceCacheInvalidation.ts]
|
||||||
|
// Repro from #32230
|
||||||
|
|
||||||
|
type Callback<TFoo, TBar> = (foo: TFoo, bar: TBar) => any
|
||||||
|
|
||||||
|
declare function example<TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(
|
||||||
|
foo: TFoo,
|
||||||
|
callback: TCallback,
|
||||||
|
bar: TBar,
|
||||||
|
): TCallback
|
||||||
|
|
||||||
|
example(42, (foo, bar) => ({
|
||||||
|
t: () => {
|
||||||
|
let s: string = bar;
|
||||||
|
}
|
||||||
|
}), '42');
|
||||||
|
|
||||||
|
example(42, (foo, bar) => ({
|
||||||
|
t() {
|
||||||
|
let s: string = bar;
|
||||||
|
}
|
||||||
|
}), '42');
|
||||||
|
|
||||||
|
|
||||||
|
//// [typeInferenceCacheInvalidation.js]
|
||||||
|
"use strict";
|
||||||
|
// Repro from #32230
|
||||||
|
example(42, function (foo, bar) { return ({
|
||||||
|
t: function () {
|
||||||
|
var s = bar;
|
||||||
|
}
|
||||||
|
}); }, '42');
|
||||||
|
example(42, function (foo, bar) { return ({
|
||||||
|
t: function () {
|
||||||
|
var s = bar;
|
||||||
|
}
|
||||||
|
}); }, '42');
|
|
@ -0,0 +1,64 @@
|
||||||
|
=== tests/cases/compiler/typeInferenceCacheInvalidation.ts ===
|
||||||
|
// Repro from #32230
|
||||||
|
|
||||||
|
type Callback<TFoo, TBar> = (foo: TFoo, bar: TBar) => any
|
||||||
|
>Callback : Symbol(Callback, Decl(typeInferenceCacheInvalidation.ts, 0, 0))
|
||||||
|
>TFoo : Symbol(TFoo, Decl(typeInferenceCacheInvalidation.ts, 2, 14))
|
||||||
|
>TBar : Symbol(TBar, Decl(typeInferenceCacheInvalidation.ts, 2, 19))
|
||||||
|
>foo : Symbol(foo, Decl(typeInferenceCacheInvalidation.ts, 2, 29))
|
||||||
|
>TFoo : Symbol(TFoo, Decl(typeInferenceCacheInvalidation.ts, 2, 14))
|
||||||
|
>bar : Symbol(bar, Decl(typeInferenceCacheInvalidation.ts, 2, 39))
|
||||||
|
>TBar : Symbol(TBar, Decl(typeInferenceCacheInvalidation.ts, 2, 19))
|
||||||
|
|
||||||
|
declare function example<TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(
|
||||||
|
>example : Symbol(example, Decl(typeInferenceCacheInvalidation.ts, 2, 57))
|
||||||
|
>TFoo : Symbol(TFoo, Decl(typeInferenceCacheInvalidation.ts, 4, 25))
|
||||||
|
>TBar : Symbol(TBar, Decl(typeInferenceCacheInvalidation.ts, 4, 30))
|
||||||
|
>TCallback : Symbol(TCallback, Decl(typeInferenceCacheInvalidation.ts, 4, 36))
|
||||||
|
>Callback : Symbol(Callback, Decl(typeInferenceCacheInvalidation.ts, 0, 0))
|
||||||
|
>TFoo : Symbol(TFoo, Decl(typeInferenceCacheInvalidation.ts, 4, 25))
|
||||||
|
>TBar : Symbol(TBar, Decl(typeInferenceCacheInvalidation.ts, 4, 30))
|
||||||
|
|
||||||
|
foo: TFoo,
|
||||||
|
>foo : Symbol(foo, Decl(typeInferenceCacheInvalidation.ts, 4, 77))
|
||||||
|
>TFoo : Symbol(TFoo, Decl(typeInferenceCacheInvalidation.ts, 4, 25))
|
||||||
|
|
||||||
|
callback: TCallback,
|
||||||
|
>callback : Symbol(callback, Decl(typeInferenceCacheInvalidation.ts, 5, 14))
|
||||||
|
>TCallback : Symbol(TCallback, Decl(typeInferenceCacheInvalidation.ts, 4, 36))
|
||||||
|
|
||||||
|
bar: TBar,
|
||||||
|
>bar : Symbol(bar, Decl(typeInferenceCacheInvalidation.ts, 6, 24))
|
||||||
|
>TBar : Symbol(TBar, Decl(typeInferenceCacheInvalidation.ts, 4, 30))
|
||||||
|
|
||||||
|
): TCallback
|
||||||
|
>TCallback : Symbol(TCallback, Decl(typeInferenceCacheInvalidation.ts, 4, 36))
|
||||||
|
|
||||||
|
example(42, (foo, bar) => ({
|
||||||
|
>example : Symbol(example, Decl(typeInferenceCacheInvalidation.ts, 2, 57))
|
||||||
|
>foo : Symbol(foo, Decl(typeInferenceCacheInvalidation.ts, 10, 13))
|
||||||
|
>bar : Symbol(bar, Decl(typeInferenceCacheInvalidation.ts, 10, 17))
|
||||||
|
|
||||||
|
t: () => {
|
||||||
|
>t : Symbol(t, Decl(typeInferenceCacheInvalidation.ts, 10, 28))
|
||||||
|
|
||||||
|
let s: string = bar;
|
||||||
|
>s : Symbol(s, Decl(typeInferenceCacheInvalidation.ts, 12, 11))
|
||||||
|
>bar : Symbol(bar, Decl(typeInferenceCacheInvalidation.ts, 10, 17))
|
||||||
|
}
|
||||||
|
}), '42');
|
||||||
|
|
||||||
|
example(42, (foo, bar) => ({
|
||||||
|
>example : Symbol(example, Decl(typeInferenceCacheInvalidation.ts, 2, 57))
|
||||||
|
>foo : Symbol(foo, Decl(typeInferenceCacheInvalidation.ts, 16, 13))
|
||||||
|
>bar : Symbol(bar, Decl(typeInferenceCacheInvalidation.ts, 16, 17))
|
||||||
|
|
||||||
|
t() {
|
||||||
|
>t : Symbol(t, Decl(typeInferenceCacheInvalidation.ts, 16, 28))
|
||||||
|
|
||||||
|
let s: string = bar;
|
||||||
|
>s : Symbol(s, Decl(typeInferenceCacheInvalidation.ts, 18, 11))
|
||||||
|
>bar : Symbol(bar, Decl(typeInferenceCacheInvalidation.ts, 16, 17))
|
||||||
|
}
|
||||||
|
}), '42');
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
=== tests/cases/compiler/typeInferenceCacheInvalidation.ts ===
|
||||||
|
// Repro from #32230
|
||||||
|
|
||||||
|
type Callback<TFoo, TBar> = (foo: TFoo, bar: TBar) => any
|
||||||
|
>Callback : Callback<TFoo, TBar>
|
||||||
|
>foo : TFoo
|
||||||
|
>bar : TBar
|
||||||
|
|
||||||
|
declare function example<TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(
|
||||||
|
>example : <TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(foo: TFoo, callback: TCallback, bar: TBar) => TCallback
|
||||||
|
|
||||||
|
foo: TFoo,
|
||||||
|
>foo : TFoo
|
||||||
|
|
||||||
|
callback: TCallback,
|
||||||
|
>callback : TCallback
|
||||||
|
|
||||||
|
bar: TBar,
|
||||||
|
>bar : TBar
|
||||||
|
|
||||||
|
): TCallback
|
||||||
|
|
||||||
|
example(42, (foo, bar) => ({
|
||||||
|
>example(42, (foo, bar) => ({ t: () => { let s: string = bar; }}), '42') : (foo: number, bar: string) => { t: () => void; }
|
||||||
|
>example : <TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(foo: TFoo, callback: TCallback, bar: TBar) => TCallback
|
||||||
|
>42 : 42
|
||||||
|
>(foo, bar) => ({ t: () => { let s: string = bar; }}) : (foo: number, bar: string) => { t: () => void; }
|
||||||
|
>foo : number
|
||||||
|
>bar : string
|
||||||
|
>({ t: () => { let s: string = bar; }}) : { t: () => void; }
|
||||||
|
>{ t: () => { let s: string = bar; }} : { t: () => void; }
|
||||||
|
|
||||||
|
t: () => {
|
||||||
|
>t : () => void
|
||||||
|
>() => { let s: string = bar; } : () => void
|
||||||
|
|
||||||
|
let s: string = bar;
|
||||||
|
>s : string
|
||||||
|
>bar : string
|
||||||
|
}
|
||||||
|
}), '42');
|
||||||
|
>'42' : "42"
|
||||||
|
|
||||||
|
example(42, (foo, bar) => ({
|
||||||
|
>example(42, (foo, bar) => ({ t() { let s: string = bar; }}), '42') : (foo: number, bar: string) => { t(): void; }
|
||||||
|
>example : <TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(foo: TFoo, callback: TCallback, bar: TBar) => TCallback
|
||||||
|
>42 : 42
|
||||||
|
>(foo, bar) => ({ t() { let s: string = bar; }}) : (foo: number, bar: string) => { t(): void; }
|
||||||
|
>foo : number
|
||||||
|
>bar : string
|
||||||
|
>({ t() { let s: string = bar; }}) : { t(): void; }
|
||||||
|
>{ t() { let s: string = bar; }} : { t(): void; }
|
||||||
|
|
||||||
|
t() {
|
||||||
|
>t : () => void
|
||||||
|
|
||||||
|
let s: string = bar;
|
||||||
|
>s : string
|
||||||
|
>bar : string
|
||||||
|
}
|
||||||
|
}), '42');
|
||||||
|
>'42' : "42"
|
||||||
|
|
23
tests/cases/compiler/typeInferenceCacheInvalidation.ts
Normal file
23
tests/cases/compiler/typeInferenceCacheInvalidation.ts
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// @strict: true
|
||||||
|
|
||||||
|
// Repro from #32230
|
||||||
|
|
||||||
|
type Callback<TFoo, TBar> = (foo: TFoo, bar: TBar) => any
|
||||||
|
|
||||||
|
declare function example<TFoo, TBar, TCallback extends Callback<TFoo, TBar>>(
|
||||||
|
foo: TFoo,
|
||||||
|
callback: TCallback,
|
||||||
|
bar: TBar,
|
||||||
|
): TCallback
|
||||||
|
|
||||||
|
example(42, (foo, bar) => ({
|
||||||
|
t: () => {
|
||||||
|
let s: string = bar;
|
||||||
|
}
|
||||||
|
}), '42');
|
||||||
|
|
||||||
|
example(42, (foo, bar) => ({
|
||||||
|
t() {
|
||||||
|
let s: string = bar;
|
||||||
|
}
|
||||||
|
}), '42');
|
Loading…
Reference in a new issue