diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ce116ffac23ea..f070d71bb16de 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13549,14 +13549,16 @@ namespace ts { const sourceLen = sourceSignatures.length; const targetLen = targetSignatures.length; const len = sourceLen < targetLen ? sourceLen : targetLen; + const skipParameters = !!(source.flags & TypeFlags.ContainsAnyFunctionType); for (let i = 0; i < len; i++) { - inferFromSignature(getBaseSignature(sourceSignatures[sourceLen - len + i]), getBaseSignature(targetSignatures[targetLen - len + i])); + inferFromSignature(getBaseSignature(sourceSignatures[sourceLen - len + i]), getBaseSignature(targetSignatures[targetLen - len + i]), skipParameters); } } - function inferFromSignature(source: Signature, target: Signature) { - forEachMatchingParameterType(source, target, inferFromContravariantTypes); - + function inferFromSignature(source: Signature, target: Signature, skipParameters: boolean) { + if (!skipParameters) { + forEachMatchingParameterType(source, target, inferFromContravariantTypes); + } const sourceTypePredicate = getTypePredicateOfSignature(source); const targetTypePredicate = getTypePredicateOfSignature(target); if (sourceTypePredicate && targetTypePredicate && sourceTypePredicate.kind === targetTypePredicate.kind) { @@ -20576,8 +20578,10 @@ namespace ts { return links.contextFreeType; } const returnType = getReturnTypeFromBody(node, checkMode); - const singleReturnSignature = createSignature(undefined, undefined, undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); - return links.contextFreeType = createAnonymousType(node.symbol, emptySymbols, [singleReturnSignature], emptyArray, undefined, undefined); + const returnOnlySignature = createSignature(undefined, undefined, undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + const returnOnlyType = createAnonymousType(node.symbol, emptySymbols, [returnOnlySignature], emptyArray, undefined, undefined); + returnOnlyType.flags |= TypeFlags.ContainsAnyFunctionType; + return links.contextFreeType = returnOnlyType; } return anyFunctionType; } diff --git a/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.js b/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.js index de98d754bb079..a089d4eb93549 100644 --- a/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.js +++ b/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.js @@ -1,4 +1,6 @@ //// [badInferenceLowerPriorityThanGoodInference.ts] +// Repro from #13118 + interface Foo { a: A; b: (x: A) => void; @@ -11,11 +13,24 @@ const result = canYouInferThis(() => ({ b: x => { } })) -result.BLAH; +result.BLAH; + +// Repro from #26629 + +function goofus (f: (...args: ARGS) => any ) {} + +goofus((a: string) => ({ dog() { return a; } })); +goofus((a: string) => ({ dog: function() { return a; } })); + //// [badInferenceLowerPriorityThanGoodInference.js] +// Repro from #13118 var result = canYouInferThis(function () { return ({ a: { BLAH: 33 }, b: function (x) { } }); }); result.BLAH; +// Repro from #26629 +function goofus(f) { } +goofus(function (a) { return ({ dog: function () { return a; } }); }); +goofus(function (a) { return ({ dog: function () { return a; } }); }); diff --git a/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.symbols b/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.symbols index d03ac3b800a3f..6eb97aef3ba9b 100644 --- a/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.symbols +++ b/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.symbols @@ -1,42 +1,65 @@ === tests/cases/compiler/badInferenceLowerPriorityThanGoodInference.ts === +// Repro from #13118 + interface Foo { >Foo : Symbol(Foo, Decl(badInferenceLowerPriorityThanGoodInference.ts, 0, 0)) ->A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 0, 14)) +>A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 2, 14)) a: A; ->a : Symbol(Foo.a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 0, 18)) ->A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 0, 14)) +>a : Symbol(Foo.a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 2, 18)) +>A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 2, 14)) b: (x: A) => void; ->b : Symbol(Foo.b, Decl(badInferenceLowerPriorityThanGoodInference.ts, 1, 9)) ->x : Symbol(x, Decl(badInferenceLowerPriorityThanGoodInference.ts, 2, 8)) ->A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 0, 14)) +>b : Symbol(Foo.b, Decl(badInferenceLowerPriorityThanGoodInference.ts, 3, 9)) +>x : Symbol(x, Decl(badInferenceLowerPriorityThanGoodInference.ts, 4, 8)) +>A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 2, 14)) } declare function canYouInferThis(fn: () => Foo): A; ->canYouInferThis : Symbol(canYouInferThis, Decl(badInferenceLowerPriorityThanGoodInference.ts, 3, 1)) ->A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 5, 33)) ->fn : Symbol(fn, Decl(badInferenceLowerPriorityThanGoodInference.ts, 5, 36)) +>canYouInferThis : Symbol(canYouInferThis, Decl(badInferenceLowerPriorityThanGoodInference.ts, 5, 1)) +>A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 33)) +>fn : Symbol(fn, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 36)) >Foo : Symbol(Foo, Decl(badInferenceLowerPriorityThanGoodInference.ts, 0, 0)) ->A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 5, 33)) ->A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 5, 33)) +>A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 33)) +>A : Symbol(A, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 33)) const result = canYouInferThis(() => ({ ->result : Symbol(result, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 5)) ->canYouInferThis : Symbol(canYouInferThis, Decl(badInferenceLowerPriorityThanGoodInference.ts, 3, 1)) +>result : Symbol(result, Decl(badInferenceLowerPriorityThanGoodInference.ts, 9, 5)) +>canYouInferThis : Symbol(canYouInferThis, Decl(badInferenceLowerPriorityThanGoodInference.ts, 5, 1)) a: { BLAH: 33 }, ->a : Symbol(a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 39)) ->BLAH : Symbol(BLAH, Decl(badInferenceLowerPriorityThanGoodInference.ts, 8, 8)) +>a : Symbol(a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 9, 39)) +>BLAH : Symbol(BLAH, Decl(badInferenceLowerPriorityThanGoodInference.ts, 10, 8)) b: x => { } ->b : Symbol(b, Decl(badInferenceLowerPriorityThanGoodInference.ts, 8, 20)) ->x : Symbol(x, Decl(badInferenceLowerPriorityThanGoodInference.ts, 9, 6)) +>b : Symbol(b, Decl(badInferenceLowerPriorityThanGoodInference.ts, 10, 20)) +>x : Symbol(x, Decl(badInferenceLowerPriorityThanGoodInference.ts, 11, 6)) })) result.BLAH; ->result.BLAH : Symbol(BLAH, Decl(badInferenceLowerPriorityThanGoodInference.ts, 8, 8)) ->result : Symbol(result, Decl(badInferenceLowerPriorityThanGoodInference.ts, 7, 5)) ->BLAH : Symbol(BLAH, Decl(badInferenceLowerPriorityThanGoodInference.ts, 8, 8)) +>result.BLAH : Symbol(BLAH, Decl(badInferenceLowerPriorityThanGoodInference.ts, 10, 8)) +>result : Symbol(result, Decl(badInferenceLowerPriorityThanGoodInference.ts, 9, 5)) +>BLAH : Symbol(BLAH, Decl(badInferenceLowerPriorityThanGoodInference.ts, 10, 8)) + +// Repro from #26629 + +function goofus (f: (...args: ARGS) => any ) {} +>goofus : Symbol(goofus, Decl(badInferenceLowerPriorityThanGoodInference.ts, 14, 12)) +>ARGS : Symbol(ARGS, Decl(badInferenceLowerPriorityThanGoodInference.ts, 18, 17)) +>f : Symbol(f, Decl(badInferenceLowerPriorityThanGoodInference.ts, 18, 38)) +>args : Symbol(args, Decl(badInferenceLowerPriorityThanGoodInference.ts, 18, 42)) +>ARGS : Symbol(ARGS, Decl(badInferenceLowerPriorityThanGoodInference.ts, 18, 17)) + +goofus((a: string) => ({ dog() { return a; } })); +>goofus : Symbol(goofus, Decl(badInferenceLowerPriorityThanGoodInference.ts, 14, 12)) +>a : Symbol(a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 20, 8)) +>dog : Symbol(dog, Decl(badInferenceLowerPriorityThanGoodInference.ts, 20, 24)) +>a : Symbol(a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 20, 8)) + +goofus((a: string) => ({ dog: function() { return a; } })); +>goofus : Symbol(goofus, Decl(badInferenceLowerPriorityThanGoodInference.ts, 14, 12)) +>a : Symbol(a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 21, 8)) +>dog : Symbol(dog, Decl(badInferenceLowerPriorityThanGoodInference.ts, 21, 24)) +>a : Symbol(a, Decl(badInferenceLowerPriorityThanGoodInference.ts, 21, 8)) diff --git a/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.types b/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.types index 8b0ab548fddf1..0847f9c29d84d 100644 --- a/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.types +++ b/tests/baselines/reference/badInferenceLowerPriorityThanGoodInference.types @@ -1,4 +1,6 @@ === tests/cases/compiler/badInferenceLowerPriorityThanGoodInference.ts === +// Repro from #13118 + interface Foo { a: A; >a : A @@ -38,3 +40,31 @@ result.BLAH; >result : { BLAH: number; } >BLAH : number +// Repro from #26629 + +function goofus (f: (...args: ARGS) => any ) {} +>goofus : (f: (...args: ARGS) => any) => void +>f : (...args: ARGS) => any +>args : ARGS + +goofus((a: string) => ({ dog() { return a; } })); +>goofus((a: string) => ({ dog() { return a; } })) : void +>goofus : (f: (...args: ARGS) => any) => void +>(a: string) => ({ dog() { return a; } }) : (a: string) => { dog(): string; } +>a : string +>({ dog() { return a; } }) : { dog(): string; } +>{ dog() { return a; } } : { dog(): string; } +>dog : () => string +>a : string + +goofus((a: string) => ({ dog: function() { return a; } })); +>goofus((a: string) => ({ dog: function() { return a; } })) : void +>goofus : (f: (...args: ARGS) => any) => void +>(a: string) => ({ dog: function() { return a; } }) : (a: string) => { dog: () => string; } +>a : string +>({ dog: function() { return a; } }) : { dog: () => string; } +>{ dog: function() { return a; } } : { dog: () => string; } +>dog : () => string +>function() { return a; } : () => string +>a : string + diff --git a/tests/cases/compiler/badInferenceLowerPriorityThanGoodInference.ts b/tests/cases/compiler/badInferenceLowerPriorityThanGoodInference.ts index 59dfb3ff4473f..8092e909df6fc 100644 --- a/tests/cases/compiler/badInferenceLowerPriorityThanGoodInference.ts +++ b/tests/cases/compiler/badInferenceLowerPriorityThanGoodInference.ts @@ -1,3 +1,5 @@ +// Repro from #13118 + interface Foo { a: A; b: (x: A) => void; @@ -10,4 +12,11 @@ const result = canYouInferThis(() => ({ b: x => { } })) -result.BLAH; \ No newline at end of file +result.BLAH; + +// Repro from #26629 + +function goofus (f: (...args: ARGS) => any ) {} + +goofus((a: string) => ({ dog() { return a; } })); +goofus((a: string) => ({ dog: function() { return a; } }));