Fixed false positive circular errors for await expressions with simple non-generic calls in CFA loops (#51126)

This commit is contained in:
Mateusz Burzyński 2023-01-09 19:56:52 +01:00 committed by GitHub
parent 00567618bd
commit 2c1fda249f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1036 additions and 17 deletions

View File

@ -427,6 +427,7 @@ import {
isAssignmentTarget,
isAsyncFunction,
isAutoAccessorPropertyDeclaration,
isAwaitExpression,
isBinaryExpression,
isBindableObjectDefinePropertyCall,
isBindableStaticElementAccessExpression,
@ -36482,7 +36483,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return type;
}
function getQuickTypeOfExpression(node: Expression) {
function getQuickTypeOfExpression(node: Expression): Type | undefined {
let expr = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true);
if (isJSDocTypeAssertion(expr)) {
const type = getJSDocTypeAssertionType(expr);
@ -36491,14 +36492,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
expr = skipParentheses(node);
if (isAwaitExpression(expr)) {
const type = getQuickTypeOfExpression(expr.expression);
return type ? getAwaitedType(type) : undefined;
}
// Optimize for the common case of a call to a function with a single non-generic call
// signature where we can just fetch the return type without checking the arguments.
if (isCallExpression(expr) && expr.expression.kind !== SyntaxKind.SuperKeyword && !isRequireCall(expr, /*checkArgumentIsStringLiteralLike*/ true) && !isSymbolOrSymbolForCall(expr)) {
const type = isCallChain(expr) ? getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr) :
return isCallChain(expr) ? getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr) :
getReturnTypeOfSingleNonGenericCallSignature(checkNonNullExpression(expr.expression));
if (type) {
return type;
}
}
else if (isAssertionExpression(expr) && !isConstTypeReference(expr.type)) {
return getTypeFromTypeNode((expr as TypeAssertion).type);

View File

@ -0,0 +1,177 @@
tests/cases/conformance/controlFlow/controlFlowIterationErrorsAsync.ts(11,23): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'string'.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/controlFlow/controlFlowIterationErrorsAsync.ts(22,23): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'string'.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/controlFlow/controlFlowIterationErrorsAsync.ts(34,23): error TS2769: No overload matches this call.
Overload 1 of 2, '(x: string): Promise<number>', gave the following error.
Argument of type 'string | number' is not assignable to parameter of type 'string'.
Type 'number' is not assignable to type 'string'.
Overload 2 of 2, '(x: number): Promise<string>', gave the following error.
Argument of type 'string | number' is not assignable to parameter of type 'number'.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/controlFlow/controlFlowIterationErrorsAsync.ts(45,23): error TS2769: No overload matches this call.
Overload 1 of 2, '(x: string): Promise<number>', gave the following error.
Argument of type 'string | number' is not assignable to parameter of type 'string'.
Type 'number' is not assignable to type 'string'.
Overload 2 of 2, '(x: number): Promise<string>', gave the following error.
Argument of type 'string | number' is not assignable to parameter of type 'number'.
Type 'string' is not assignable to type 'number'.
==== tests/cases/conformance/controlFlow/controlFlowIterationErrorsAsync.ts (4 errors) ====
let cond: boolean;
async function len(s: string) {
return s.length;
}
async function f1() {
let x: string | number | boolean;
x = "";
while (cond) {
x = await len(x);
~
!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'string'.
!!! error TS2345: Type 'number' is not assignable to type 'string'.
x;
}
x;
}
async function f2() {
let x: string | number | boolean;
x = "";
while (cond) {
x;
x = await len(x);
~
!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'string'.
!!! error TS2345: Type 'number' is not assignable to type 'string'.
}
x;
}
declare function foo(x: string): Promise<number>;
declare function foo(x: number): Promise<string>;
async function g1() {
let x: string | number | boolean;
x = "";
while (cond) {
x = await foo(x);
~
!!! error TS2769: No overload matches this call.
!!! error TS2769: Overload 1 of 2, '(x: string): Promise<number>', gave the following error.
!!! error TS2769: Argument of type 'string | number' is not assignable to parameter of type 'string'.
!!! error TS2769: Type 'number' is not assignable to type 'string'.
!!! error TS2769: Overload 2 of 2, '(x: number): Promise<string>', gave the following error.
!!! error TS2769: Argument of type 'string | number' is not assignable to parameter of type 'number'.
!!! error TS2769: Type 'string' is not assignable to type 'number'.
x;
}
x;
}
async function g2() {
let x: string | number | boolean;
x = "";
while (cond) {
x;
x = await foo(x);
~
!!! error TS2769: No overload matches this call.
!!! error TS2769: Overload 1 of 2, '(x: string): Promise<number>', gave the following error.
!!! error TS2769: Argument of type 'string | number' is not assignable to parameter of type 'string'.
!!! error TS2769: Type 'number' is not assignable to type 'string'.
!!! error TS2769: Overload 2 of 2, '(x: number): Promise<string>', gave the following error.
!!! error TS2769: Argument of type 'string | number' is not assignable to parameter of type 'number'.
!!! error TS2769: Type 'string' is not assignable to type 'number'.
}
x;
}
async function asNumber(x: string | number): Promise<number> {
return +x;
}
async function h1() {
let x: string | number | boolean;
x = "0";
while (cond) {
x = +x + 1;
x;
}
}
async function h2() {
let x: string | number | boolean;
x = "0";
while (cond) {
x = await asNumber(x) + 1;
x;
}
}
async function h3() {
let x: string | number | boolean;
x = "0";
while (cond) {
let y = await asNumber(x);
x = y + 1;
x;
}
}
async function h4() {
let x: string | number | boolean;
x = "0";
while (cond) {
x;
let y = await asNumber(x);
x = y + 1;
x;
}
}
// repro #51115
async function get_things(_: number | undefined) {
return [0];
}
async function foobar() {
let before: number | undefined = undefined;
for (let i = 0; i < 2; i++) {
const results = await get_things(before);
before = results[0];
}
}
// repro #43047#issuecomment-821453073
declare function foox(x: string | undefined): Promise<string>
async () => {
let bar: string | undefined = undefined;
do {
const baz = await foox(bar);
bar = baz
} while (bar)
}
// repro #43047#issuecomment-874221939
declare function myQuery(input: { lastId: number | undefined }): Promise<{ entities: number[] }>;
async function myFunc(): Promise<void> {
let lastId: number | undefined = undefined;
while (true) {
const { entities } = await myQuery({
lastId,
});
lastId = entities[entities.length - 1];
}
}

View File

@ -0,0 +1,321 @@
=== tests/cases/conformance/controlFlow/controlFlowIterationErrorsAsync.ts ===
let cond: boolean;
>cond : Symbol(cond, Decl(controlFlowIterationErrorsAsync.ts, 0, 3))
async function len(s: string) {
>len : Symbol(len, Decl(controlFlowIterationErrorsAsync.ts, 0, 18))
>s : Symbol(s, Decl(controlFlowIterationErrorsAsync.ts, 2, 19))
return s.length;
>s.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>s : Symbol(s, Decl(controlFlowIterationErrorsAsync.ts, 2, 19))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
async function f1() {
>f1 : Symbol(f1, Decl(controlFlowIterationErrorsAsync.ts, 4, 1))
let x: string | number | boolean;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 7, 7))
x = "";
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 7, 7))
while (cond) {
>cond : Symbol(cond, Decl(controlFlowIterationErrorsAsync.ts, 0, 3))
x = await len(x);
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 7, 7))
>len : Symbol(len, Decl(controlFlowIterationErrorsAsync.ts, 0, 18))
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 7, 7))
x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 7, 7))
}
x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 7, 7))
}
async function f2() {
>f2 : Symbol(f2, Decl(controlFlowIterationErrorsAsync.ts, 14, 1))
let x: string | number | boolean;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 17, 7))
x = "";
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 17, 7))
while (cond) {
>cond : Symbol(cond, Decl(controlFlowIterationErrorsAsync.ts, 0, 3))
x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 17, 7))
x = await len(x);
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 17, 7))
>len : Symbol(len, Decl(controlFlowIterationErrorsAsync.ts, 0, 18))
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 17, 7))
}
x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 17, 7))
}
declare function foo(x: string): Promise<number>;
>foo : Symbol(foo, Decl(controlFlowIterationErrorsAsync.ts, 24, 1), Decl(controlFlowIterationErrorsAsync.ts, 26, 49))
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 26, 21))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
declare function foo(x: number): Promise<string>;
>foo : Symbol(foo, Decl(controlFlowIterationErrorsAsync.ts, 24, 1), Decl(controlFlowIterationErrorsAsync.ts, 26, 49))
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 27, 21))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
async function g1() {
>g1 : Symbol(g1, Decl(controlFlowIterationErrorsAsync.ts, 27, 49))
let x: string | number | boolean;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 30, 7))
x = "";
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 30, 7))
while (cond) {
>cond : Symbol(cond, Decl(controlFlowIterationErrorsAsync.ts, 0, 3))
x = await foo(x);
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 30, 7))
>foo : Symbol(foo, Decl(controlFlowIterationErrorsAsync.ts, 24, 1), Decl(controlFlowIterationErrorsAsync.ts, 26, 49))
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 30, 7))
x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 30, 7))
}
x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 30, 7))
}
async function g2() {
>g2 : Symbol(g2, Decl(controlFlowIterationErrorsAsync.ts, 37, 1))
let x: string | number | boolean;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 40, 7))
x = "";
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 40, 7))
while (cond) {
>cond : Symbol(cond, Decl(controlFlowIterationErrorsAsync.ts, 0, 3))
x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 40, 7))
x = await foo(x);
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 40, 7))
>foo : Symbol(foo, Decl(controlFlowIterationErrorsAsync.ts, 24, 1), Decl(controlFlowIterationErrorsAsync.ts, 26, 49))
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 40, 7))
}
x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 40, 7))
}
async function asNumber(x: string | number): Promise<number> {
>asNumber : Symbol(asNumber, Decl(controlFlowIterationErrorsAsync.ts, 47, 1))
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 49, 24))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
return +x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 49, 24))
}
async function h1() {
>h1 : Symbol(h1, Decl(controlFlowIterationErrorsAsync.ts, 51, 1))
let x: string | number | boolean;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 54, 7))
x = "0";
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 54, 7))
while (cond) {
>cond : Symbol(cond, Decl(controlFlowIterationErrorsAsync.ts, 0, 3))
x = +x + 1;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 54, 7))
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 54, 7))
x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 54, 7))
}
}
async function h2() {
>h2 : Symbol(h2, Decl(controlFlowIterationErrorsAsync.ts, 60, 1))
let x: string | number | boolean;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 63, 7))
x = "0";
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 63, 7))
while (cond) {
>cond : Symbol(cond, Decl(controlFlowIterationErrorsAsync.ts, 0, 3))
x = await asNumber(x) + 1;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 63, 7))
>asNumber : Symbol(asNumber, Decl(controlFlowIterationErrorsAsync.ts, 47, 1))
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 63, 7))
x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 63, 7))
}
}
async function h3() {
>h3 : Symbol(h3, Decl(controlFlowIterationErrorsAsync.ts, 69, 1))
let x: string | number | boolean;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 72, 7))
x = "0";
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 72, 7))
while (cond) {
>cond : Symbol(cond, Decl(controlFlowIterationErrorsAsync.ts, 0, 3))
let y = await asNumber(x);
>y : Symbol(y, Decl(controlFlowIterationErrorsAsync.ts, 75, 11))
>asNumber : Symbol(asNumber, Decl(controlFlowIterationErrorsAsync.ts, 47, 1))
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 72, 7))
x = y + 1;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 72, 7))
>y : Symbol(y, Decl(controlFlowIterationErrorsAsync.ts, 75, 11))
x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 72, 7))
}
}
async function h4() {
>h4 : Symbol(h4, Decl(controlFlowIterationErrorsAsync.ts, 79, 1))
let x: string | number | boolean;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 82, 7))
x = "0";
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 82, 7))
while (cond) {
>cond : Symbol(cond, Decl(controlFlowIterationErrorsAsync.ts, 0, 3))
x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 82, 7))
let y = await asNumber(x);
>y : Symbol(y, Decl(controlFlowIterationErrorsAsync.ts, 86, 11))
>asNumber : Symbol(asNumber, Decl(controlFlowIterationErrorsAsync.ts, 47, 1))
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 82, 7))
x = y + 1;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 82, 7))
>y : Symbol(y, Decl(controlFlowIterationErrorsAsync.ts, 86, 11))
x;
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 82, 7))
}
}
// repro #51115
async function get_things(_: number | undefined) {
>get_things : Symbol(get_things, Decl(controlFlowIterationErrorsAsync.ts, 90, 1))
>_ : Symbol(_, Decl(controlFlowIterationErrorsAsync.ts, 94, 26))
return [0];
}
async function foobar() {
>foobar : Symbol(foobar, Decl(controlFlowIterationErrorsAsync.ts, 96, 1))
let before: number | undefined = undefined;
>before : Symbol(before, Decl(controlFlowIterationErrorsAsync.ts, 99, 7))
>undefined : Symbol(undefined)
for (let i = 0; i < 2; i++) {
>i : Symbol(i, Decl(controlFlowIterationErrorsAsync.ts, 100, 12))
>i : Symbol(i, Decl(controlFlowIterationErrorsAsync.ts, 100, 12))
>i : Symbol(i, Decl(controlFlowIterationErrorsAsync.ts, 100, 12))
const results = await get_things(before);
>results : Symbol(results, Decl(controlFlowIterationErrorsAsync.ts, 101, 13))
>get_things : Symbol(get_things, Decl(controlFlowIterationErrorsAsync.ts, 90, 1))
>before : Symbol(before, Decl(controlFlowIterationErrorsAsync.ts, 99, 7))
before = results[0];
>before : Symbol(before, Decl(controlFlowIterationErrorsAsync.ts, 99, 7))
>results : Symbol(results, Decl(controlFlowIterationErrorsAsync.ts, 101, 13))
}
}
// repro #43047#issuecomment-821453073
declare function foox(x: string | undefined): Promise<string>
>foox : Symbol(foox, Decl(controlFlowIterationErrorsAsync.ts, 104, 1))
>x : Symbol(x, Decl(controlFlowIterationErrorsAsync.ts, 108, 22))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
async () => {
let bar: string | undefined = undefined;
>bar : Symbol(bar, Decl(controlFlowIterationErrorsAsync.ts, 111, 5))
>undefined : Symbol(undefined)
do {
const baz = await foox(bar);
>baz : Symbol(baz, Decl(controlFlowIterationErrorsAsync.ts, 113, 9))
>foox : Symbol(foox, Decl(controlFlowIterationErrorsAsync.ts, 104, 1))
>bar : Symbol(bar, Decl(controlFlowIterationErrorsAsync.ts, 111, 5))
bar = baz
>bar : Symbol(bar, Decl(controlFlowIterationErrorsAsync.ts, 111, 5))
>baz : Symbol(baz, Decl(controlFlowIterationErrorsAsync.ts, 113, 9))
} while (bar)
>bar : Symbol(bar, Decl(controlFlowIterationErrorsAsync.ts, 111, 5))
}
// repro #43047#issuecomment-874221939
declare function myQuery(input: { lastId: number | undefined }): Promise<{ entities: number[] }>;
>myQuery : Symbol(myQuery, Decl(controlFlowIterationErrorsAsync.ts, 116, 1))
>input : Symbol(input, Decl(controlFlowIterationErrorsAsync.ts, 120, 25))
>lastId : Symbol(lastId, Decl(controlFlowIterationErrorsAsync.ts, 120, 33))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>entities : Symbol(entities, Decl(controlFlowIterationErrorsAsync.ts, 120, 74))
async function myFunc(): Promise<void> {
>myFunc : Symbol(myFunc, Decl(controlFlowIterationErrorsAsync.ts, 120, 97))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
let lastId: number | undefined = undefined;
>lastId : Symbol(lastId, Decl(controlFlowIterationErrorsAsync.ts, 123, 5))
>undefined : Symbol(undefined)
while (true) {
const { entities } = await myQuery({
>entities : Symbol(entities, Decl(controlFlowIterationErrorsAsync.ts, 126, 11))
>myQuery : Symbol(myQuery, Decl(controlFlowIterationErrorsAsync.ts, 116, 1))
lastId,
>lastId : Symbol(lastId, Decl(controlFlowIterationErrorsAsync.ts, 126, 40))
});
lastId = entities[entities.length - 1];
>lastId : Symbol(lastId, Decl(controlFlowIterationErrorsAsync.ts, 123, 5))
>entities : Symbol(entities, Decl(controlFlowIterationErrorsAsync.ts, 126, 11))
>entities.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>entities : Symbol(entities, Decl(controlFlowIterationErrorsAsync.ts, 126, 11))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
}
}

View File

@ -0,0 +1,388 @@
=== tests/cases/conformance/controlFlow/controlFlowIterationErrorsAsync.ts ===
let cond: boolean;
>cond : boolean
async function len(s: string) {
>len : (s: string) => Promise<number>
>s : string
return s.length;
>s.length : number
>s : string
>length : number
}
async function f1() {
>f1 : () => Promise<void>
let x: string | number | boolean;
>x : string | number | boolean
x = "";
>x = "" : ""
>x : string | number | boolean
>"" : ""
while (cond) {
>cond : boolean
x = await len(x);
>x = await len(x) : number
>x : string | number | boolean
>await len(x) : number
>len(x) : Promise<number>
>len : (s: string) => Promise<number>
>x : string | number
x;
>x : number
}
x;
>x : string | number
}
async function f2() {
>f2 : () => Promise<void>
let x: string | number | boolean;
>x : string | number | boolean
x = "";
>x = "" : ""
>x : string | number | boolean
>"" : ""
while (cond) {
>cond : boolean
x;
>x : string | number
x = await len(x);
>x = await len(x) : number
>x : string | number | boolean
>await len(x) : number
>len(x) : Promise<number>
>len : (s: string) => Promise<number>
>x : string | number
}
x;
>x : string | number
}
declare function foo(x: string): Promise<number>;
>foo : { (x: string): Promise<number>; (x: number): Promise<string>; }
>x : string
declare function foo(x: number): Promise<string>;
>foo : { (x: string): Promise<number>; (x: number): Promise<string>; }
>x : number
async function g1() {
>g1 : () => Promise<void>
let x: string | number | boolean;
>x : string | number | boolean
x = "";
>x = "" : ""
>x : string | number | boolean
>"" : ""
while (cond) {
>cond : boolean
x = await foo(x);
>x = await foo(x) : never
>x : string | number | boolean
>await foo(x) : never
>foo(x) : Promise<number> & Promise<string>
>foo : { (x: string): Promise<number>; (x: number): Promise<string>; }
>x : string | number
x;
>x : never
}
x;
>x : string | number
}
async function g2() {
>g2 : () => Promise<void>
let x: string | number | boolean;
>x : string | number | boolean
x = "";
>x = "" : ""
>x : string | number | boolean
>"" : ""
while (cond) {
>cond : boolean
x;
>x : string | number
x = await foo(x);
>x = await foo(x) : never
>x : string | number | boolean
>await foo(x) : never
>foo(x) : Promise<number> & Promise<string>
>foo : { (x: string): Promise<number>; (x: number): Promise<string>; }
>x : string | number
}
x;
>x : string | number
}
async function asNumber(x: string | number): Promise<number> {
>asNumber : (x: string | number) => Promise<number>
>x : string | number
return +x;
>+x : number
>x : string | number
}
async function h1() {
>h1 : () => Promise<void>
let x: string | number | boolean;
>x : string | number | boolean
x = "0";
>x = "0" : "0"
>x : string | number | boolean
>"0" : "0"
while (cond) {
>cond : boolean
x = +x + 1;
>x = +x + 1 : number
>x : string | number | boolean
>+x + 1 : number
>+x : number
>x : string | number
>1 : 1
x;
>x : number
}
}
async function h2() {
>h2 : () => Promise<void>
let x: string | number | boolean;
>x : string | number | boolean
x = "0";
>x = "0" : "0"
>x : string | number | boolean
>"0" : "0"
while (cond) {
>cond : boolean
x = await asNumber(x) + 1;
>x = await asNumber(x) + 1 : number
>x : string | number | boolean
>await asNumber(x) + 1 : number
>await asNumber(x) : number
>asNumber(x) : Promise<number>
>asNumber : (x: string | number) => Promise<number>
>x : string | number
>1 : 1
x;
>x : number
}
}
async function h3() {
>h3 : () => Promise<void>
let x: string | number | boolean;
>x : string | number | boolean
x = "0";
>x = "0" : "0"
>x : string | number | boolean
>"0" : "0"
while (cond) {
>cond : boolean
let y = await asNumber(x);
>y : number
>await asNumber(x) : number
>asNumber(x) : Promise<number>
>asNumber : (x: string | number) => Promise<number>
>x : string | number
x = y + 1;
>x = y + 1 : number
>x : string | number | boolean
>y + 1 : number
>y : number
>1 : 1
x;
>x : number
}
}
async function h4() {
>h4 : () => Promise<void>
let x: string | number | boolean;
>x : string | number | boolean
x = "0";
>x = "0" : "0"
>x : string | number | boolean
>"0" : "0"
while (cond) {
>cond : boolean
x;
>x : string | number
let y = await asNumber(x);
>y : number
>await asNumber(x) : number
>asNumber(x) : Promise<number>
>asNumber : (x: string | number) => Promise<number>
>x : string | number
x = y + 1;
>x = y + 1 : number
>x : string | number | boolean
>y + 1 : number
>y : number
>1 : 1
x;
>x : number
}
}
// repro #51115
async function get_things(_: number | undefined) {
>get_things : (_: number | undefined) => Promise<number[]>
>_ : number | undefined
return [0];
>[0] : number[]
>0 : 0
}
async function foobar() {
>foobar : () => Promise<void>
let before: number | undefined = undefined;
>before : number | undefined
>undefined : undefined
for (let i = 0; i < 2; i++) {
>i : number
>0 : 0
>i < 2 : boolean
>i : number
>2 : 2
>i++ : number
>i : number
const results = await get_things(before);
>results : number[]
>await get_things(before) : number[]
>get_things(before) : Promise<number[]>
>get_things : (_: number | undefined) => Promise<number[]>
>before : number | undefined
before = results[0];
>before = results[0] : number
>before : number | undefined
>results[0] : number
>results : number[]
>0 : 0
}
}
// repro #43047#issuecomment-821453073
declare function foox(x: string | undefined): Promise<string>
>foox : (x: string | undefined) => Promise<string>
>x : string | undefined
async () => {
>async () => { let bar: string | undefined = undefined; do { const baz = await foox(bar); bar = baz } while (bar)} : () => Promise<void>
let bar: string | undefined = undefined;
>bar : string | undefined
>undefined : undefined
do {
const baz = await foox(bar);
>baz : string
>await foox(bar) : string
>foox(bar) : Promise<string>
>foox : (x: string | undefined) => Promise<string>
>bar : string | undefined
bar = baz
>bar = baz : string
>bar : string | undefined
>baz : string
} while (bar)
>bar : string
}
// repro #43047#issuecomment-874221939
declare function myQuery(input: { lastId: number | undefined }): Promise<{ entities: number[] }>;
>myQuery : (input: { lastId: number | undefined;}) => Promise<{ entities: number[];}>
>input : { lastId: number | undefined; }
>lastId : number | undefined
>entities : number[]
async function myFunc(): Promise<void> {
>myFunc : () => Promise<void>
let lastId: number | undefined = undefined;
>lastId : number | undefined
>undefined : undefined
while (true) {
>true : true
const { entities } = await myQuery({
>entities : number[]
>await myQuery({ lastId, }) : { entities: number[]; }
>myQuery({ lastId, }) : Promise<{ entities: number[]; }>
>myQuery : (input: { lastId: number | undefined; }) => Promise<{ entities: number[]; }>
>{ lastId, } : { lastId: number | undefined; }
lastId,
>lastId : number | undefined
});
lastId = entities[entities.length - 1];
>lastId = entities[entities.length - 1] : number
>lastId : number | undefined
>entities[entities.length - 1] : number
>entities : number[]
>entities.length - 1 : number
>entities.length : number
>entities : number[]
>length : number
>1 : 1
}
}

View File

@ -7,7 +7,7 @@ tests/cases/compiler/implicitAnyFromCircularInference.ts(17,5): error TS7023: 'f
tests/cases/compiler/implicitAnyFromCircularInference.ts(22,5): error TS7023: 'f2' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
tests/cases/compiler/implicitAnyFromCircularInference.ts(25,10): error TS7023: 'h' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
tests/cases/compiler/implicitAnyFromCircularInference.ts(27,14): error TS7023: 'foo' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
tests/cases/compiler/implicitAnyFromCircularInference.ts(45,9): error TS7023: 'x' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
tests/cases/compiler/implicitAnyFromCircularInference.ts(44,9): error TS7023: 'x' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
==== tests/cases/compiler/implicitAnyFromCircularInference.ts (10 errors) ====
@ -67,7 +67,6 @@ tests/cases/compiler/implicitAnyFromCircularInference.ts(45,9): error TS7023: 'x
function foo(x: A): string { return "abc"; }
class C {
// Error expected
s = foo(this);
}

View File

@ -37,7 +37,6 @@ interface A {
function foo(x: A): string { return "abc"; }
class C {
// Error expected
s = foo(this);
}
@ -76,7 +75,6 @@ function h() {
function foo(x) { return "abc"; }
var C = /** @class */ (function () {
function C() {
// Error expected
this.s = foo(this);
}
return C;

View File

@ -72,7 +72,6 @@ function foo(x: A): string { return "abc"; }
class C {
>C : Symbol(C, Decl(implicitAnyFromCircularInference.ts, 35, 44))
// Error expected
s = foo(this);
>s : Symbol(C.s, Decl(implicitAnyFromCircularInference.ts, 37, 9))
>foo : Symbol(foo, Decl(implicitAnyFromCircularInference.ts, 33, 1))
@ -80,16 +79,16 @@ class C {
}
class D {
>D : Symbol(D, Decl(implicitAnyFromCircularInference.ts, 40, 1))
>D : Symbol(D, Decl(implicitAnyFromCircularInference.ts, 39, 1))
// Error expected
get x() {
>x : Symbol(D.x, Decl(implicitAnyFromCircularInference.ts, 42, 9))
>x : Symbol(D.x, Decl(implicitAnyFromCircularInference.ts, 41, 9))
return this.x;
>this.x : Symbol(D.x, Decl(implicitAnyFromCircularInference.ts, 42, 9))
>this : Symbol(D, Decl(implicitAnyFromCircularInference.ts, 40, 1))
>x : Symbol(D.x, Decl(implicitAnyFromCircularInference.ts, 42, 9))
>this.x : Symbol(D.x, Decl(implicitAnyFromCircularInference.ts, 41, 9))
>this : Symbol(D, Decl(implicitAnyFromCircularInference.ts, 39, 1))
>x : Symbol(D.x, Decl(implicitAnyFromCircularInference.ts, 41, 9))
}
}

View File

@ -78,7 +78,6 @@ function foo(x: A): string { return "abc"; }
class C {
>C : C
// Error expected
s = foo(this);
>s : string
>foo(this) : string

View File

@ -39,7 +39,6 @@ interface A {
function foo(x: A): string { return "abc"; }
class C {
// Error expected
s = foo(this);
}

View File

@ -0,0 +1,137 @@
// @strict: true
// @noEmit: true
// @lib: esnext
let cond: boolean;
async function len(s: string) {
return s.length;
}
async function f1() {
let x: string | number | boolean;
x = "";
while (cond) {
x = await len(x);
x;
}
x;
}
async function f2() {
let x: string | number | boolean;
x = "";
while (cond) {
x;
x = await len(x);
}
x;
}
declare function foo(x: string): Promise<number>;
declare function foo(x: number): Promise<string>;
async function g1() {
let x: string | number | boolean;
x = "";
while (cond) {
x = await foo(x);
x;
}
x;
}
async function g2() {
let x: string | number | boolean;
x = "";
while (cond) {
x;
x = await foo(x);
}
x;
}
async function asNumber(x: string | number): Promise<number> {
return +x;
}
async function h1() {
let x: string | number | boolean;
x = "0";
while (cond) {
x = +x + 1;
x;
}
}
async function h2() {
let x: string | number | boolean;
x = "0";
while (cond) {
x = await asNumber(x) + 1;
x;
}
}
async function h3() {
let x: string | number | boolean;
x = "0";
while (cond) {
let y = await asNumber(x);
x = y + 1;
x;
}
}
async function h4() {
let x: string | number | boolean;
x = "0";
while (cond) {
x;
let y = await asNumber(x);
x = y + 1;
x;
}
}
// repro #51115
async function get_things(_: number | undefined) {
return [0];
}
async function foobar() {
let before: number | undefined = undefined;
for (let i = 0; i < 2; i++) {
const results = await get_things(before);
before = results[0];
}
}
// repro #43047#issuecomment-821453073
declare function foox(x: string | undefined): Promise<string>
async () => {
let bar: string | undefined = undefined;
do {
const baz = await foox(bar);
bar = baz
} while (bar)
}
// repro #43047#issuecomment-874221939
declare function myQuery(input: { lastId: number | undefined }): Promise<{ entities: number[] }>;
async function myFunc(): Promise<void> {
let lastId: number | undefined = undefined;
while (true) {
const { entities } = await myQuery({
lastId,
});
lastId = entities[entities.length - 1];
}
}