Create returnOnlySignature only when inferences will possibly be made (#35173)
* Create returnOnlySignature only when inferences will possibly be made * Add regression test * Accept new baselines
This commit is contained in:
parent
0c17476d09
commit
0c2c58c42f
|
@ -26129,15 +26129,19 @@ namespace ts {
|
|||
if (checkMode && checkMode & CheckMode.SkipContextSensitive && isContextSensitive(node)) {
|
||||
// Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage
|
||||
if (!getEffectiveReturnTypeNode(node) && hasContextSensitiveReturnExpression(node)) {
|
||||
const links = getNodeLinks(node);
|
||||
if (links.contextFreeType) {
|
||||
return links.contextFreeType;
|
||||
// Return plain anyFunctionType if there is no possibility we'll make inferences from the return type
|
||||
const contextualSignature = getContextualSignature(node);
|
||||
if (contextualSignature && couldContainTypeVariables(getReturnTypeOfSignature(contextualSignature))) {
|
||||
const links = getNodeLinks(node);
|
||||
if (links.contextFreeType) {
|
||||
return links.contextFreeType;
|
||||
}
|
||||
const returnType = getReturnTypeFromBody(node, checkMode);
|
||||
const returnOnlySignature = createSignature(undefined, undefined, undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
|
||||
const returnOnlyType = createAnonymousType(node.symbol, emptySymbols, [returnOnlySignature], emptyArray, undefined, undefined);
|
||||
returnOnlyType.objectFlags |= ObjectFlags.NonInferrableType;
|
||||
return links.contextFreeType = returnOnlyType;
|
||||
}
|
||||
const returnType = getReturnTypeFromBody(node, checkMode);
|
||||
const returnOnlySignature = createSignature(undefined, undefined, undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
|
||||
const returnOnlyType = createAnonymousType(node.symbol, emptySymbols, [returnOnlySignature], emptyArray, undefined, undefined);
|
||||
returnOnlyType.objectFlags |= ObjectFlags.NonInferrableType;
|
||||
return links.contextFreeType = returnOnlyType;
|
||||
}
|
||||
return anyFunctionType;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
//// [contextSensitiveReturnTypeInference.ts]
|
||||
// Repro from #34849
|
||||
|
||||
interface IData {
|
||||
bar: boolean
|
||||
}
|
||||
|
||||
declare function test<TDependencies>(
|
||||
getter: (deps: TDependencies, data: IData) => any,
|
||||
deps: TDependencies,
|
||||
): any
|
||||
|
||||
const DEPS = {
|
||||
foo: 1
|
||||
}
|
||||
|
||||
test(
|
||||
(deps, data) => ({
|
||||
fn1: function() { return deps.foo },
|
||||
fn2: data.bar
|
||||
}),
|
||||
DEPS
|
||||
);
|
||||
|
||||
test(
|
||||
(deps: typeof DEPS, data) => ({
|
||||
fn1: function() { return deps.foo },
|
||||
fn2: data.bar
|
||||
}),
|
||||
DEPS
|
||||
);
|
||||
|
||||
test(
|
||||
(deps, data) => ({
|
||||
fn1: () => deps.foo,
|
||||
fn2: data.bar
|
||||
}),
|
||||
DEPS
|
||||
);
|
||||
|
||||
test(
|
||||
(deps, data) => {
|
||||
return {
|
||||
fn1() { return deps.foo },
|
||||
fn2: data.bar
|
||||
}
|
||||
},
|
||||
DEPS
|
||||
);
|
||||
|
||||
test(
|
||||
(deps) => ({
|
||||
fn1() { return deps.foo },
|
||||
fn2: 1
|
||||
}),
|
||||
DEPS
|
||||
);
|
||||
|
||||
|
||||
//// [contextSensitiveReturnTypeInference.js]
|
||||
"use strict";
|
||||
// Repro from #34849
|
||||
var DEPS = {
|
||||
foo: 1
|
||||
};
|
||||
test(function (deps, data) { return ({
|
||||
fn1: function () { return deps.foo; },
|
||||
fn2: data.bar
|
||||
}); }, DEPS);
|
||||
test(function (deps, data) { return ({
|
||||
fn1: function () { return deps.foo; },
|
||||
fn2: data.bar
|
||||
}); }, DEPS);
|
||||
test(function (deps, data) { return ({
|
||||
fn1: function () { return deps.foo; },
|
||||
fn2: data.bar
|
||||
}); }, DEPS);
|
||||
test(function (deps, data) {
|
||||
return {
|
||||
fn1: function () { return deps.foo; },
|
||||
fn2: data.bar
|
||||
};
|
||||
}, DEPS);
|
||||
test(function (deps) { return ({
|
||||
fn1: function () { return deps.foo; },
|
||||
fn2: 1
|
||||
}); }, DEPS);
|
|
@ -0,0 +1,157 @@
|
|||
=== tests/cases/compiler/contextSensitiveReturnTypeInference.ts ===
|
||||
// Repro from #34849
|
||||
|
||||
interface IData {
|
||||
>IData : Symbol(IData, Decl(contextSensitiveReturnTypeInference.ts, 0, 0))
|
||||
|
||||
bar: boolean
|
||||
>bar : Symbol(IData.bar, Decl(contextSensitiveReturnTypeInference.ts, 2, 17))
|
||||
}
|
||||
|
||||
declare function test<TDependencies>(
|
||||
>test : Symbol(test, Decl(contextSensitiveReturnTypeInference.ts, 4, 1))
|
||||
>TDependencies : Symbol(TDependencies, Decl(contextSensitiveReturnTypeInference.ts, 6, 22))
|
||||
|
||||
getter: (deps: TDependencies, data: IData) => any,
|
||||
>getter : Symbol(getter, Decl(contextSensitiveReturnTypeInference.ts, 6, 37))
|
||||
>deps : Symbol(deps, Decl(contextSensitiveReturnTypeInference.ts, 7, 11))
|
||||
>TDependencies : Symbol(TDependencies, Decl(contextSensitiveReturnTypeInference.ts, 6, 22))
|
||||
>data : Symbol(data, Decl(contextSensitiveReturnTypeInference.ts, 7, 31))
|
||||
>IData : Symbol(IData, Decl(contextSensitiveReturnTypeInference.ts, 0, 0))
|
||||
|
||||
deps: TDependencies,
|
||||
>deps : Symbol(deps, Decl(contextSensitiveReturnTypeInference.ts, 7, 52))
|
||||
>TDependencies : Symbol(TDependencies, Decl(contextSensitiveReturnTypeInference.ts, 6, 22))
|
||||
|
||||
): any
|
||||
|
||||
const DEPS = {
|
||||
>DEPS : Symbol(DEPS, Decl(contextSensitiveReturnTypeInference.ts, 11, 5))
|
||||
|
||||
foo: 1
|
||||
>foo : Symbol(foo, Decl(contextSensitiveReturnTypeInference.ts, 11, 14))
|
||||
}
|
||||
|
||||
test(
|
||||
>test : Symbol(test, Decl(contextSensitiveReturnTypeInference.ts, 4, 1))
|
||||
|
||||
(deps, data) => ({
|
||||
>deps : Symbol(deps, Decl(contextSensitiveReturnTypeInference.ts, 16, 3))
|
||||
>data : Symbol(data, Decl(contextSensitiveReturnTypeInference.ts, 16, 8))
|
||||
|
||||
fn1: function() { return deps.foo },
|
||||
>fn1 : Symbol(fn1, Decl(contextSensitiveReturnTypeInference.ts, 16, 20))
|
||||
>deps.foo : Symbol(foo, Decl(contextSensitiveReturnTypeInference.ts, 11, 14))
|
||||
>deps : Symbol(deps, Decl(contextSensitiveReturnTypeInference.ts, 16, 3))
|
||||
>foo : Symbol(foo, Decl(contextSensitiveReturnTypeInference.ts, 11, 14))
|
||||
|
||||
fn2: data.bar
|
||||
>fn2 : Symbol(fn2, Decl(contextSensitiveReturnTypeInference.ts, 17, 40))
|
||||
>data.bar : Symbol(IData.bar, Decl(contextSensitiveReturnTypeInference.ts, 2, 17))
|
||||
>data : Symbol(data, Decl(contextSensitiveReturnTypeInference.ts, 16, 8))
|
||||
>bar : Symbol(IData.bar, Decl(contextSensitiveReturnTypeInference.ts, 2, 17))
|
||||
|
||||
}),
|
||||
DEPS
|
||||
>DEPS : Symbol(DEPS, Decl(contextSensitiveReturnTypeInference.ts, 11, 5))
|
||||
|
||||
);
|
||||
|
||||
test(
|
||||
>test : Symbol(test, Decl(contextSensitiveReturnTypeInference.ts, 4, 1))
|
||||
|
||||
(deps: typeof DEPS, data) => ({
|
||||
>deps : Symbol(deps, Decl(contextSensitiveReturnTypeInference.ts, 24, 3))
|
||||
>DEPS : Symbol(DEPS, Decl(contextSensitiveReturnTypeInference.ts, 11, 5))
|
||||
>data : Symbol(data, Decl(contextSensitiveReturnTypeInference.ts, 24, 21))
|
||||
|
||||
fn1: function() { return deps.foo },
|
||||
>fn1 : Symbol(fn1, Decl(contextSensitiveReturnTypeInference.ts, 24, 33))
|
||||
>deps.foo : Symbol(foo, Decl(contextSensitiveReturnTypeInference.ts, 11, 14))
|
||||
>deps : Symbol(deps, Decl(contextSensitiveReturnTypeInference.ts, 24, 3))
|
||||
>foo : Symbol(foo, Decl(contextSensitiveReturnTypeInference.ts, 11, 14))
|
||||
|
||||
fn2: data.bar
|
||||
>fn2 : Symbol(fn2, Decl(contextSensitiveReturnTypeInference.ts, 25, 40))
|
||||
>data.bar : Symbol(IData.bar, Decl(contextSensitiveReturnTypeInference.ts, 2, 17))
|
||||
>data : Symbol(data, Decl(contextSensitiveReturnTypeInference.ts, 24, 21))
|
||||
>bar : Symbol(IData.bar, Decl(contextSensitiveReturnTypeInference.ts, 2, 17))
|
||||
|
||||
}),
|
||||
DEPS
|
||||
>DEPS : Symbol(DEPS, Decl(contextSensitiveReturnTypeInference.ts, 11, 5))
|
||||
|
||||
);
|
||||
|
||||
test(
|
||||
>test : Symbol(test, Decl(contextSensitiveReturnTypeInference.ts, 4, 1))
|
||||
|
||||
(deps, data) => ({
|
||||
>deps : Symbol(deps, Decl(contextSensitiveReturnTypeInference.ts, 32, 3))
|
||||
>data : Symbol(data, Decl(contextSensitiveReturnTypeInference.ts, 32, 8))
|
||||
|
||||
fn1: () => deps.foo,
|
||||
>fn1 : Symbol(fn1, Decl(contextSensitiveReturnTypeInference.ts, 32, 20))
|
||||
>deps.foo : Symbol(foo, Decl(contextSensitiveReturnTypeInference.ts, 11, 14))
|
||||
>deps : Symbol(deps, Decl(contextSensitiveReturnTypeInference.ts, 32, 3))
|
||||
>foo : Symbol(foo, Decl(contextSensitiveReturnTypeInference.ts, 11, 14))
|
||||
|
||||
fn2: data.bar
|
||||
>fn2 : Symbol(fn2, Decl(contextSensitiveReturnTypeInference.ts, 33, 24))
|
||||
>data.bar : Symbol(IData.bar, Decl(contextSensitiveReturnTypeInference.ts, 2, 17))
|
||||
>data : Symbol(data, Decl(contextSensitiveReturnTypeInference.ts, 32, 8))
|
||||
>bar : Symbol(IData.bar, Decl(contextSensitiveReturnTypeInference.ts, 2, 17))
|
||||
|
||||
}),
|
||||
DEPS
|
||||
>DEPS : Symbol(DEPS, Decl(contextSensitiveReturnTypeInference.ts, 11, 5))
|
||||
|
||||
);
|
||||
|
||||
test(
|
||||
>test : Symbol(test, Decl(contextSensitiveReturnTypeInference.ts, 4, 1))
|
||||
|
||||
(deps, data) => {
|
||||
>deps : Symbol(deps, Decl(contextSensitiveReturnTypeInference.ts, 40, 3))
|
||||
>data : Symbol(data, Decl(contextSensitiveReturnTypeInference.ts, 40, 8))
|
||||
|
||||
return {
|
||||
fn1() { return deps.foo },
|
||||
>fn1 : Symbol(fn1, Decl(contextSensitiveReturnTypeInference.ts, 41, 12))
|
||||
>deps.foo : Symbol(foo, Decl(contextSensitiveReturnTypeInference.ts, 11, 14))
|
||||
>deps : Symbol(deps, Decl(contextSensitiveReturnTypeInference.ts, 40, 3))
|
||||
>foo : Symbol(foo, Decl(contextSensitiveReturnTypeInference.ts, 11, 14))
|
||||
|
||||
fn2: data.bar
|
||||
>fn2 : Symbol(fn2, Decl(contextSensitiveReturnTypeInference.ts, 42, 32))
|
||||
>data.bar : Symbol(IData.bar, Decl(contextSensitiveReturnTypeInference.ts, 2, 17))
|
||||
>data : Symbol(data, Decl(contextSensitiveReturnTypeInference.ts, 40, 8))
|
||||
>bar : Symbol(IData.bar, Decl(contextSensitiveReturnTypeInference.ts, 2, 17))
|
||||
}
|
||||
},
|
||||
DEPS
|
||||
>DEPS : Symbol(DEPS, Decl(contextSensitiveReturnTypeInference.ts, 11, 5))
|
||||
|
||||
);
|
||||
|
||||
test(
|
||||
>test : Symbol(test, Decl(contextSensitiveReturnTypeInference.ts, 4, 1))
|
||||
|
||||
(deps) => ({
|
||||
>deps : Symbol(deps, Decl(contextSensitiveReturnTypeInference.ts, 50, 3))
|
||||
|
||||
fn1() { return deps.foo },
|
||||
>fn1 : Symbol(fn1, Decl(contextSensitiveReturnTypeInference.ts, 50, 14))
|
||||
>deps.foo : Symbol(foo, Decl(contextSensitiveReturnTypeInference.ts, 11, 14))
|
||||
>deps : Symbol(deps, Decl(contextSensitiveReturnTypeInference.ts, 50, 3))
|
||||
>foo : Symbol(foo, Decl(contextSensitiveReturnTypeInference.ts, 11, 14))
|
||||
|
||||
fn2: 1
|
||||
>fn2 : Symbol(fn2, Decl(contextSensitiveReturnTypeInference.ts, 51, 30))
|
||||
|
||||
}),
|
||||
DEPS
|
||||
>DEPS : Symbol(DEPS, Decl(contextSensitiveReturnTypeInference.ts, 11, 5))
|
||||
|
||||
);
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
=== tests/cases/compiler/contextSensitiveReturnTypeInference.ts ===
|
||||
// Repro from #34849
|
||||
|
||||
interface IData {
|
||||
bar: boolean
|
||||
>bar : boolean
|
||||
}
|
||||
|
||||
declare function test<TDependencies>(
|
||||
>test : <TDependencies>(getter: (deps: TDependencies, data: IData) => any, deps: TDependencies) => any
|
||||
|
||||
getter: (deps: TDependencies, data: IData) => any,
|
||||
>getter : (deps: TDependencies, data: IData) => any
|
||||
>deps : TDependencies
|
||||
>data : IData
|
||||
|
||||
deps: TDependencies,
|
||||
>deps : TDependencies
|
||||
|
||||
): any
|
||||
|
||||
const DEPS = {
|
||||
>DEPS : { foo: number; }
|
||||
>{ foo: 1} : { foo: number; }
|
||||
|
||||
foo: 1
|
||||
>foo : number
|
||||
>1 : 1
|
||||
}
|
||||
|
||||
test(
|
||||
>test( (deps, data) => ({ fn1: function() { return deps.foo }, fn2: data.bar }), DEPS) : any
|
||||
>test : <TDependencies>(getter: (deps: TDependencies, data: IData) => any, deps: TDependencies) => any
|
||||
|
||||
(deps, data) => ({
|
||||
>(deps, data) => ({ fn1: function() { return deps.foo }, fn2: data.bar }) : (deps: { foo: number; }, data: IData) => { fn1: () => number; fn2: boolean; }
|
||||
>deps : { foo: number; }
|
||||
>data : IData
|
||||
>({ fn1: function() { return deps.foo }, fn2: data.bar }) : { fn1: () => number; fn2: boolean; }
|
||||
>{ fn1: function() { return deps.foo }, fn2: data.bar } : { fn1: () => number; fn2: boolean; }
|
||||
|
||||
fn1: function() { return deps.foo },
|
||||
>fn1 : () => number
|
||||
>function() { return deps.foo } : () => number
|
||||
>deps.foo : number
|
||||
>deps : { foo: number; }
|
||||
>foo : number
|
||||
|
||||
fn2: data.bar
|
||||
>fn2 : boolean
|
||||
>data.bar : boolean
|
||||
>data : IData
|
||||
>bar : boolean
|
||||
|
||||
}),
|
||||
DEPS
|
||||
>DEPS : { foo: number; }
|
||||
|
||||
);
|
||||
|
||||
test(
|
||||
>test( (deps: typeof DEPS, data) => ({ fn1: function() { return deps.foo }, fn2: data.bar }), DEPS) : any
|
||||
>test : <TDependencies>(getter: (deps: TDependencies, data: IData) => any, deps: TDependencies) => any
|
||||
|
||||
(deps: typeof DEPS, data) => ({
|
||||
>(deps: typeof DEPS, data) => ({ fn1: function() { return deps.foo }, fn2: data.bar }) : (deps: { foo: number; }, data: IData) => { fn1: () => number; fn2: boolean; }
|
||||
>deps : { foo: number; }
|
||||
>DEPS : { foo: number; }
|
||||
>data : IData
|
||||
>({ fn1: function() { return deps.foo }, fn2: data.bar }) : { fn1: () => number; fn2: boolean; }
|
||||
>{ fn1: function() { return deps.foo }, fn2: data.bar } : { fn1: () => number; fn2: boolean; }
|
||||
|
||||
fn1: function() { return deps.foo },
|
||||
>fn1 : () => number
|
||||
>function() { return deps.foo } : () => number
|
||||
>deps.foo : number
|
||||
>deps : { foo: number; }
|
||||
>foo : number
|
||||
|
||||
fn2: data.bar
|
||||
>fn2 : boolean
|
||||
>data.bar : boolean
|
||||
>data : IData
|
||||
>bar : boolean
|
||||
|
||||
}),
|
||||
DEPS
|
||||
>DEPS : { foo: number; }
|
||||
|
||||
);
|
||||
|
||||
test(
|
||||
>test( (deps, data) => ({ fn1: () => deps.foo, fn2: data.bar }), DEPS) : any
|
||||
>test : <TDependencies>(getter: (deps: TDependencies, data: IData) => any, deps: TDependencies) => any
|
||||
|
||||
(deps, data) => ({
|
||||
>(deps, data) => ({ fn1: () => deps.foo, fn2: data.bar }) : (deps: { foo: number; }, data: IData) => { fn1: () => number; fn2: boolean; }
|
||||
>deps : { foo: number; }
|
||||
>data : IData
|
||||
>({ fn1: () => deps.foo, fn2: data.bar }) : { fn1: () => number; fn2: boolean; }
|
||||
>{ fn1: () => deps.foo, fn2: data.bar } : { fn1: () => number; fn2: boolean; }
|
||||
|
||||
fn1: () => deps.foo,
|
||||
>fn1 : () => number
|
||||
>() => deps.foo : () => number
|
||||
>deps.foo : number
|
||||
>deps : { foo: number; }
|
||||
>foo : number
|
||||
|
||||
fn2: data.bar
|
||||
>fn2 : boolean
|
||||
>data.bar : boolean
|
||||
>data : IData
|
||||
>bar : boolean
|
||||
|
||||
}),
|
||||
DEPS
|
||||
>DEPS : { foo: number; }
|
||||
|
||||
);
|
||||
|
||||
test(
|
||||
>test( (deps, data) => { return { fn1() { return deps.foo }, fn2: data.bar } }, DEPS) : any
|
||||
>test : <TDependencies>(getter: (deps: TDependencies, data: IData) => any, deps: TDependencies) => any
|
||||
|
||||
(deps, data) => {
|
||||
>(deps, data) => { return { fn1() { return deps.foo }, fn2: data.bar } } : (deps: { foo: number; }, data: IData) => { fn1(): number; fn2: boolean; }
|
||||
>deps : { foo: number; }
|
||||
>data : IData
|
||||
|
||||
return {
|
||||
>{ fn1() { return deps.foo }, fn2: data.bar } : { fn1(): number; fn2: boolean; }
|
||||
|
||||
fn1() { return deps.foo },
|
||||
>fn1 : () => number
|
||||
>deps.foo : number
|
||||
>deps : { foo: number; }
|
||||
>foo : number
|
||||
|
||||
fn2: data.bar
|
||||
>fn2 : boolean
|
||||
>data.bar : boolean
|
||||
>data : IData
|
||||
>bar : boolean
|
||||
}
|
||||
},
|
||||
DEPS
|
||||
>DEPS : { foo: number; }
|
||||
|
||||
);
|
||||
|
||||
test(
|
||||
>test( (deps) => ({ fn1() { return deps.foo }, fn2: 1 }), DEPS) : any
|
||||
>test : <TDependencies>(getter: (deps: TDependencies, data: IData) => any, deps: TDependencies) => any
|
||||
|
||||
(deps) => ({
|
||||
>(deps) => ({ fn1() { return deps.foo }, fn2: 1 }) : (deps: { foo: number; }) => { fn1(): number; fn2: number; }
|
||||
>deps : { foo: number; }
|
||||
>({ fn1() { return deps.foo }, fn2: 1 }) : { fn1(): number; fn2: number; }
|
||||
>{ fn1() { return deps.foo }, fn2: 1 } : { fn1(): number; fn2: number; }
|
||||
|
||||
fn1() { return deps.foo },
|
||||
>fn1 : () => number
|
||||
>deps.foo : number
|
||||
>deps : { foo: number; }
|
||||
>foo : number
|
||||
|
||||
fn2: 1
|
||||
>fn2 : number
|
||||
>1 : 1
|
||||
|
||||
}),
|
||||
DEPS
|
||||
>DEPS : { foo: number; }
|
||||
|
||||
);
|
||||
|
58
tests/cases/compiler/contextSensitiveReturnTypeInference.ts
Normal file
58
tests/cases/compiler/contextSensitiveReturnTypeInference.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
// @strict: true
|
||||
|
||||
// Repro from #34849
|
||||
|
||||
interface IData {
|
||||
bar: boolean
|
||||
}
|
||||
|
||||
declare function test<TDependencies>(
|
||||
getter: (deps: TDependencies, data: IData) => any,
|
||||
deps: TDependencies,
|
||||
): any
|
||||
|
||||
const DEPS = {
|
||||
foo: 1
|
||||
}
|
||||
|
||||
test(
|
||||
(deps, data) => ({
|
||||
fn1: function() { return deps.foo },
|
||||
fn2: data.bar
|
||||
}),
|
||||
DEPS
|
||||
);
|
||||
|
||||
test(
|
||||
(deps: typeof DEPS, data) => ({
|
||||
fn1: function() { return deps.foo },
|
||||
fn2: data.bar
|
||||
}),
|
||||
DEPS
|
||||
);
|
||||
|
||||
test(
|
||||
(deps, data) => ({
|
||||
fn1: () => deps.foo,
|
||||
fn2: data.bar
|
||||
}),
|
||||
DEPS
|
||||
);
|
||||
|
||||
test(
|
||||
(deps, data) => {
|
||||
return {
|
||||
fn1() { return deps.foo },
|
||||
fn2: data.bar
|
||||
}
|
||||
},
|
||||
DEPS
|
||||
);
|
||||
|
||||
test(
|
||||
(deps) => ({
|
||||
fn1() { return deps.foo },
|
||||
fn2: 1
|
||||
}),
|
||||
DEPS
|
||||
);
|
Loading…
Reference in a new issue