From 535e0980f7e0681393d735e3f6665d6c1f8657d4 Mon Sep 17 00:00:00 2001 From: Maria Solano Date: Fri, 24 Mar 2023 12:41:51 -0700 Subject: [PATCH 01/10] Re-add isTypeAssignableTo check --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f5f82917b877b..09ee2d4107c38 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -35686,7 +35686,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error(errorNode, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); } } - else if (type && strictNullChecks) { + else if (type && strictNullChecks && !isTypeAssignableTo(undefinedType, type)) { error(errorNode, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined); } else if (compilerOptions.noImplicitReturns) { From 7e97af8afbab3dd794d3371403f5d7a791d8f35d Mon Sep 17 00:00:00 2001 From: Maria Solano Date: Fri, 24 Mar 2023 12:42:25 -0700 Subject: [PATCH 02/10] Add tests --- ...ImplicitReturnTypeAssignableToUndefined.js | 47 ++++++++++++++ ...citReturnTypeAssignableToUndefined.symbols | 47 ++++++++++++++ ...licitReturnTypeAssignableToUndefined.types | 62 +++++++++++++++++++ ...peAssignableToUndefinedStrictNullChecks.js | 27 ++++++++ ...ignableToUndefinedStrictNullChecks.symbols | 23 +++++++ ...ssignableToUndefinedStrictNullChecks.types | 27 ++++++++ ...ImplicitReturnTypeAssignableToUndefined.ts | 26 ++++++++ ...peAssignableToUndefinedStrictNullChecks.ts | 16 +++++ 8 files changed, 275 insertions(+) create mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.js create mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.symbols create mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.types create mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.js create mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.symbols create mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.types create mode 100644 tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts create mode 100644 tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.js b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.js new file mode 100644 index 0000000000000..8c899eea127d7 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.js @@ -0,0 +1,47 @@ +//// [functionsWithImplicitReturnTypeAssignableToUndefined.ts] +function f1(): {} { + if (Math.random() < 0.5) return {}; + + // Implicit return, but undefined is assignable to object. +} + +function f2(): Record { + if (Math.random() < 0.5) return { "foo": true }; + + // Implicit return, but undefined is assignable to records (which are just fancy objects). +} + +function f3(): null { + if (Math.random() < 0.5) return null; + + // Implicit return, but undefined is assignable to null. +} + +function f4(): string | null { + if (Math.random() < 0.5) return "string"; + + // Implicit return, but undefined is assignable to null. +} + + +//// [functionsWithImplicitReturnTypeAssignableToUndefined.js] +function f1() { + if (Math.random() < 0.5) + return {}; + // Implicit return, but undefined is assignable to object. +} +function f2() { + if (Math.random() < 0.5) + return { "foo": true }; + // Implicit return, but undefined is assignable to records (which are just fancy objects). +} +function f3() { + if (Math.random() < 0.5) + return null; + // Implicit return, but undefined is assignable to null. +} +function f4() { + if (Math.random() < 0.5) + return "string"; + // Implicit return, but undefined is assignable to null. +} diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.symbols b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.symbols new file mode 100644 index 0000000000000..19ed917025c9e --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.symbols @@ -0,0 +1,47 @@ +=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts === +function f1(): {} { +>f1 : Symbol(f1, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 0, 0)) + + if (Math.random() < 0.5) return {}; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to object. +} + +function f2(): Record { +>f2 : Symbol(f2, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 4, 1)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + + if (Math.random() < 0.5) return { "foo": true }; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>"foo" : Symbol("foo", Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 7, 37)) + + // Implicit return, but undefined is assignable to records (which are just fancy objects). +} + +function f3(): null { +>f3 : Symbol(f3, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 10, 1)) + + if (Math.random() < 0.5) return null; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to null. +} + +function f4(): string | null { +>f4 : Symbol(f4, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 16, 1)) + + if (Math.random() < 0.5) return "string"; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to null. +} + diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.types b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.types new file mode 100644 index 0000000000000..39db5cc036a50 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.types @@ -0,0 +1,62 @@ +=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts === +function f1(): {} { +>f1 : () => {} + + if (Math.random() < 0.5) return {}; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>{} : {} + + // Implicit return, but undefined is assignable to object. +} + +function f2(): Record { +>f2 : () => Record + + if (Math.random() < 0.5) return { "foo": true }; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>{ "foo": true } : { foo: boolean; } +>"foo" : boolean +>true : true + + // Implicit return, but undefined is assignable to records (which are just fancy objects). +} + +function f3(): null { +>f3 : () => null + + if (Math.random() < 0.5) return null; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 + + // Implicit return, but undefined is assignable to null. +} + +function f4(): string | null { +>f4 : () => string | null + + if (Math.random() < 0.5) return "string"; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>"string" : "string" + + // Implicit return, but undefined is assignable to null. +} + diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.js b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.js new file mode 100644 index 0000000000000..1079a3b8d707f --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.js @@ -0,0 +1,27 @@ +//// [functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts] +function f1(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is assignable to unknown. +} + +function f2(): any { + // Implicit return, but undefined is assignable to any. +} + +function f3(): void { + // Implicit return, but undefined is assignable to void. +} + +//// [functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.js] +function f1() { + if (Math.random() < 0.5) + return true; + // Implicit return, but undefined is assignable to unknown. +} +function f2() { + // Implicit return, but undefined is assignable to any. +} +function f3() { + // Implicit return, but undefined is assignable to void. +} diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.symbols b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.symbols new file mode 100644 index 0000000000000..e14333f69d6d6 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.symbols @@ -0,0 +1,23 @@ +=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts === +function f1(): unknown { +>f1 : Symbol(f1, Decl(functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts, 0, 0)) + + if (Math.random() < 0.5) return true; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to unknown. +} + +function f2(): any { +>f2 : Symbol(f2, Decl(functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts, 4, 1)) + + // Implicit return, but undefined is assignable to any. +} + +function f3(): void { +>f3 : Symbol(f3, Decl(functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts, 8, 1)) + + // Implicit return, but undefined is assignable to void. +} diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.types b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.types new file mode 100644 index 0000000000000..5348444807452 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.types @@ -0,0 +1,27 @@ +=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts === +function f1(): unknown { +>f1 : () => unknown + + if (Math.random() < 0.5) return true; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>true : true + + // Implicit return, but undefined is assignable to unknown. +} + +function f2(): any { +>f2 : () => any + + // Implicit return, but undefined is assignable to any. +} + +function f3(): void { +>f3 : () => void + + // Implicit return, but undefined is assignable to void. +} diff --git a/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts b/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts new file mode 100644 index 0000000000000..049a1e49aaabc --- /dev/null +++ b/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts @@ -0,0 +1,26 @@ +// @noImplicitReturns: false +// @strictNullChecks: false + +function f1(): {} { + if (Math.random() < 0.5) return {}; + + // Implicit return, but undefined is assignable to object. +} + +function f2(): Record { + if (Math.random() < 0.5) return { "foo": true }; + + // Implicit return, but undefined is assignable to records (which are just fancy objects). +} + +function f3(): null { + if (Math.random() < 0.5) return null; + + // Implicit return, but undefined is assignable to null. +} + +function f4(): string | null { + if (Math.random() < 0.5) return "string"; + + // Implicit return, but undefined is assignable to null. +} diff --git a/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts b/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts new file mode 100644 index 0000000000000..16d671ab1e7fd --- /dev/null +++ b/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts @@ -0,0 +1,16 @@ +// @noImplicitReturns: false +// @strictNullChecks: true + +function f1(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is assignable to unknown. +} + +function f2(): any { + // Implicit return, but undefined is assignable to any. +} + +function f3(): void { + // Implicit return, but undefined is assignable to void. +} \ No newline at end of file From 1c2c3fae53d3c457311893b4ce84cfefe9e71ef2 Mon Sep 17 00:00:00 2001 From: Maria Solano Date: Fri, 24 Mar 2023 13:06:28 -0700 Subject: [PATCH 03/10] Combine tests in a single file --- ...ableToUndefined(strictnullchecks=false).js | 74 +++++++++++++++ ...oUndefined(strictnullchecks=false).symbols | 71 +++++++++++++++ ...eToUndefined(strictnullchecks=false).types | 90 +++++++++++++++++++ ...ndefined(strictnullchecks=true).errors.txt | 54 +++++++++++ ...nableToUndefined(strictnullchecks=true).js | 74 +++++++++++++++ ...ToUndefined(strictnullchecks=true).symbols | 71 +++++++++++++++ ...leToUndefined(strictnullchecks=true).types | 90 +++++++++++++++++++ ...ImplicitReturnTypeAssignableToUndefined.ts | 35 +++++--- ...peAssignableToUndefinedStrictNullChecks.ts | 16 ---- 9 files changed, 549 insertions(+), 26 deletions(-) create mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).js create mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).symbols create mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).types create mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).errors.txt create mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).js create mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).symbols create mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).types delete mode 100644 tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).js b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).js new file mode 100644 index 0000000000000..e3261d1ece3d0 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).js @@ -0,0 +1,74 @@ +//// [functionsWithImplicitReturnTypeAssignableToUndefined.ts] +function f1(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. +} + +function f2(): any { + // Implicit return, but undefined is always assignable to any. +} + +function f3(): void { + // Implicit return, but undefined is always assignable to void. +} + +function f4(): {} { + if (Math.random() < 0.5) return {}; + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} + +function f5(): Record { + if (Math.random() < 0.5) return { "foo": true }; + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} + +function f6(): null { + if (Math.random() < 0.5) return null; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +function f7(): string | null { + if (Math.random() < 0.5) return "foo"; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + + +//// [functionsWithImplicitReturnTypeAssignableToUndefined.js] +function f1() { + if (Math.random() < 0.5) + return true; + // Implicit return, but undefined is always assignable to unknown. +} +function f2() { + // Implicit return, but undefined is always assignable to any. +} +function f3() { + // Implicit return, but undefined is always assignable to void. +} +function f4() { + if (Math.random() < 0.5) + return {}; + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} +function f5() { + if (Math.random() < 0.5) + return { "foo": true }; + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} +function f6() { + if (Math.random() < 0.5) + return null; + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} +function f7() { + if (Math.random() < 0.5) + return "foo"; + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).symbols b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).symbols new file mode 100644 index 0000000000000..06529c66a396c --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).symbols @@ -0,0 +1,71 @@ +=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts === +function f1(): unknown { +>f1 : Symbol(f1, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 0, 0)) + + if (Math.random() < 0.5) return true; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is always assignable to unknown. +} + +function f2(): any { +>f2 : Symbol(f2, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 4, 1)) + + // Implicit return, but undefined is always assignable to any. +} + +function f3(): void { +>f3 : Symbol(f3, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 8, 1)) + + // Implicit return, but undefined is always assignable to void. +} + +function f4(): {} { +>f4 : Symbol(f4, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 12, 1)) + + if (Math.random() < 0.5) return {}; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} + +function f5(): Record { +>f5 : Symbol(f5, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 18, 1)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + + if (Math.random() < 0.5) return { "foo": true }; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>"foo" : Symbol("foo", Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 21, 37)) + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} + +function f6(): null { +>f6 : Symbol(f6, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 25, 1)) + + if (Math.random() < 0.5) return null; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +function f7(): string | null { +>f7 : Symbol(f7, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 31, 1)) + + if (Math.random() < 0.5) return "foo"; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).types b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).types new file mode 100644 index 0000000000000..ac76e07adf687 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).types @@ -0,0 +1,90 @@ +=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts === +function f1(): unknown { +>f1 : () => unknown + + if (Math.random() < 0.5) return true; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>true : true + + // Implicit return, but undefined is always assignable to unknown. +} + +function f2(): any { +>f2 : () => any + + // Implicit return, but undefined is always assignable to any. +} + +function f3(): void { +>f3 : () => void + + // Implicit return, but undefined is always assignable to void. +} + +function f4(): {} { +>f4 : () => {} + + if (Math.random() < 0.5) return {}; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>{} : {} + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} + +function f5(): Record { +>f5 : () => Record + + if (Math.random() < 0.5) return { "foo": true }; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>{ "foo": true } : { foo: boolean; } +>"foo" : boolean +>true : true + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} + +function f6(): null { +>f6 : () => null + + if (Math.random() < 0.5) return null; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +function f7(): string | null { +>f7 : () => string | null + + if (Math.random() < 0.5) return "foo"; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>"foo" : "foo" + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).errors.txt b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).errors.txt new file mode 100644 index 0000000000000..c5931ba955018 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).errors.txt @@ -0,0 +1,54 @@ +tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(15,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. +tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(21,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. +tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(28,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. +tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(34,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. + + +==== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts (4 errors) ==== + function f1(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. + } + + function f2(): any { + // Implicit return, but undefined is always assignable to any. + } + + function f3(): void { + // Implicit return, but undefined is always assignable to void. + } + + function f4(): {} { + ~~ +!!! error TS2366: Function lacks ending return statement and return type does not include 'undefined'. + if (Math.random() < 0.5) return {}; + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. + } + + function f5(): Record { + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2366: Function lacks ending return statement and return type does not include 'undefined'. + if (Math.random() < 0.5) return { "foo": true }; + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. + } + + function f6(): null { + ~~~~ +!!! error TS2366: Function lacks ending return statement and return type does not include 'undefined'. + if (Math.random() < 0.5) return null; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. + } + + function f7(): string | null { + ~~~~~~~~~~~~~ +!!! error TS2366: Function lacks ending return statement and return type does not include 'undefined'. + if (Math.random() < 0.5) return "foo"; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. + } + \ No newline at end of file diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).js b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).js new file mode 100644 index 0000000000000..e3261d1ece3d0 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).js @@ -0,0 +1,74 @@ +//// [functionsWithImplicitReturnTypeAssignableToUndefined.ts] +function f1(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. +} + +function f2(): any { + // Implicit return, but undefined is always assignable to any. +} + +function f3(): void { + // Implicit return, but undefined is always assignable to void. +} + +function f4(): {} { + if (Math.random() < 0.5) return {}; + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} + +function f5(): Record { + if (Math.random() < 0.5) return { "foo": true }; + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} + +function f6(): null { + if (Math.random() < 0.5) return null; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +function f7(): string | null { + if (Math.random() < 0.5) return "foo"; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + + +//// [functionsWithImplicitReturnTypeAssignableToUndefined.js] +function f1() { + if (Math.random() < 0.5) + return true; + // Implicit return, but undefined is always assignable to unknown. +} +function f2() { + // Implicit return, but undefined is always assignable to any. +} +function f3() { + // Implicit return, but undefined is always assignable to void. +} +function f4() { + if (Math.random() < 0.5) + return {}; + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} +function f5() { + if (Math.random() < 0.5) + return { "foo": true }; + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} +function f6() { + if (Math.random() < 0.5) + return null; + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} +function f7() { + if (Math.random() < 0.5) + return "foo"; + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).symbols b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).symbols new file mode 100644 index 0000000000000..06529c66a396c --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).symbols @@ -0,0 +1,71 @@ +=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts === +function f1(): unknown { +>f1 : Symbol(f1, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 0, 0)) + + if (Math.random() < 0.5) return true; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is always assignable to unknown. +} + +function f2(): any { +>f2 : Symbol(f2, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 4, 1)) + + // Implicit return, but undefined is always assignable to any. +} + +function f3(): void { +>f3 : Symbol(f3, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 8, 1)) + + // Implicit return, but undefined is always assignable to void. +} + +function f4(): {} { +>f4 : Symbol(f4, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 12, 1)) + + if (Math.random() < 0.5) return {}; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} + +function f5(): Record { +>f5 : Symbol(f5, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 18, 1)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + + if (Math.random() < 0.5) return { "foo": true }; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>"foo" : Symbol("foo", Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 21, 37)) + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} + +function f6(): null { +>f6 : Symbol(f6, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 25, 1)) + + if (Math.random() < 0.5) return null; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +function f7(): string | null { +>f7 : Symbol(f7, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 31, 1)) + + if (Math.random() < 0.5) return "foo"; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).types b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).types new file mode 100644 index 0000000000000..ac76e07adf687 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).types @@ -0,0 +1,90 @@ +=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts === +function f1(): unknown { +>f1 : () => unknown + + if (Math.random() < 0.5) return true; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>true : true + + // Implicit return, but undefined is always assignable to unknown. +} + +function f2(): any { +>f2 : () => any + + // Implicit return, but undefined is always assignable to any. +} + +function f3(): void { +>f3 : () => void + + // Implicit return, but undefined is always assignable to void. +} + +function f4(): {} { +>f4 : () => {} + + if (Math.random() < 0.5) return {}; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>{} : {} + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} + +function f5(): Record { +>f5 : () => Record + + if (Math.random() < 0.5) return { "foo": true }; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>{ "foo": true } : { foo: boolean; } +>"foo" : boolean +>true : true + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} + +function f6(): null { +>f6 : () => null + + if (Math.random() < 0.5) return null; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +function f7(): string | null { +>f7 : () => string | null + + if (Math.random() < 0.5) return "foo"; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>"foo" : "foo" + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + diff --git a/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts b/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts index 049a1e49aaabc..e11e23de19871 100644 --- a/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts +++ b/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts @@ -1,26 +1,41 @@ // @noImplicitReturns: false -// @strictNullChecks: false +// @strictNullChecks: true, false -function f1(): {} { +function f1(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. +} + +function f2(): any { + // Implicit return, but undefined is always assignable to any. +} + +function f3(): void { + // Implicit return, but undefined is always assignable to void. +} + +function f4(): {} { if (Math.random() < 0.5) return {}; - // Implicit return, but undefined is assignable to object. + // Implicit return, but undefined is assignable to object when strictNullChecks is off. } -function f2(): Record { +function f5(): Record { if (Math.random() < 0.5) return { "foo": true }; - // Implicit return, but undefined is assignable to records (which are just fancy objects). + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. } -function f3(): null { +function f6(): null { if (Math.random() < 0.5) return null; - // Implicit return, but undefined is assignable to null. + // Implicit return, but undefined is assignable to null when strictNullChecks is off. } -function f4(): string | null { - if (Math.random() < 0.5) return "string"; +function f7(): string | null { + if (Math.random() < 0.5) return "foo"; - // Implicit return, but undefined is assignable to null. + // Implicit return, but undefined is assignable to null when strictNullChecks is off. } diff --git a/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts b/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts deleted file mode 100644 index 16d671ab1e7fd..0000000000000 --- a/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts +++ /dev/null @@ -1,16 +0,0 @@ -// @noImplicitReturns: false -// @strictNullChecks: true - -function f1(): unknown { - if (Math.random() < 0.5) return true; - - // Implicit return, but undefined is assignable to unknown. -} - -function f2(): any { - // Implicit return, but undefined is assignable to any. -} - -function f3(): void { - // Implicit return, but undefined is assignable to void. -} \ No newline at end of file From 250b65c3847da5b3e08a3fef8df286dbb5fe0298 Mon Sep 17 00:00:00 2001 From: Maria Solano Date: Fri, 24 Mar 2023 13:18:09 -0700 Subject: [PATCH 04/10] Remove old baselines --- ...ImplicitReturnTypeAssignableToUndefined.js | 47 -------------- ...citReturnTypeAssignableToUndefined.symbols | 47 -------------- ...licitReturnTypeAssignableToUndefined.types | 62 ------------------- ...peAssignableToUndefinedStrictNullChecks.js | 27 -------- ...ignableToUndefinedStrictNullChecks.symbols | 23 ------- ...ssignableToUndefinedStrictNullChecks.types | 27 -------- 6 files changed, 233 deletions(-) delete mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.js delete mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.symbols delete mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.types delete mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.js delete mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.symbols delete mode 100644 tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.types diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.js b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.js deleted file mode 100644 index 8c899eea127d7..0000000000000 --- a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.js +++ /dev/null @@ -1,47 +0,0 @@ -//// [functionsWithImplicitReturnTypeAssignableToUndefined.ts] -function f1(): {} { - if (Math.random() < 0.5) return {}; - - // Implicit return, but undefined is assignable to object. -} - -function f2(): Record { - if (Math.random() < 0.5) return { "foo": true }; - - // Implicit return, but undefined is assignable to records (which are just fancy objects). -} - -function f3(): null { - if (Math.random() < 0.5) return null; - - // Implicit return, but undefined is assignable to null. -} - -function f4(): string | null { - if (Math.random() < 0.5) return "string"; - - // Implicit return, but undefined is assignable to null. -} - - -//// [functionsWithImplicitReturnTypeAssignableToUndefined.js] -function f1() { - if (Math.random() < 0.5) - return {}; - // Implicit return, but undefined is assignable to object. -} -function f2() { - if (Math.random() < 0.5) - return { "foo": true }; - // Implicit return, but undefined is assignable to records (which are just fancy objects). -} -function f3() { - if (Math.random() < 0.5) - return null; - // Implicit return, but undefined is assignable to null. -} -function f4() { - if (Math.random() < 0.5) - return "string"; - // Implicit return, but undefined is assignable to null. -} diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.symbols b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.symbols deleted file mode 100644 index 19ed917025c9e..0000000000000 --- a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.symbols +++ /dev/null @@ -1,47 +0,0 @@ -=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts === -function f1(): {} { ->f1 : Symbol(f1, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 0, 0)) - - if (Math.random() < 0.5) return {}; ->Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) ->Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) - - // Implicit return, but undefined is assignable to object. -} - -function f2(): Record { ->f2 : Symbol(f2, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 4, 1)) ->Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) - - if (Math.random() < 0.5) return { "foo": true }; ->Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) ->Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) ->"foo" : Symbol("foo", Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 7, 37)) - - // Implicit return, but undefined is assignable to records (which are just fancy objects). -} - -function f3(): null { ->f3 : Symbol(f3, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 10, 1)) - - if (Math.random() < 0.5) return null; ->Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) ->Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) - - // Implicit return, but undefined is assignable to null. -} - -function f4(): string | null { ->f4 : Symbol(f4, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 16, 1)) - - if (Math.random() < 0.5) return "string"; ->Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) ->Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) - - // Implicit return, but undefined is assignable to null. -} - diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.types b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.types deleted file mode 100644 index 39db5cc036a50..0000000000000 --- a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined.types +++ /dev/null @@ -1,62 +0,0 @@ -=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts === -function f1(): {} { ->f1 : () => {} - - if (Math.random() < 0.5) return {}; ->Math.random() < 0.5 : boolean ->Math.random() : number ->Math.random : () => number ->Math : Math ->random : () => number ->0.5 : 0.5 ->{} : {} - - // Implicit return, but undefined is assignable to object. -} - -function f2(): Record { ->f2 : () => Record - - if (Math.random() < 0.5) return { "foo": true }; ->Math.random() < 0.5 : boolean ->Math.random() : number ->Math.random : () => number ->Math : Math ->random : () => number ->0.5 : 0.5 ->{ "foo": true } : { foo: boolean; } ->"foo" : boolean ->true : true - - // Implicit return, but undefined is assignable to records (which are just fancy objects). -} - -function f3(): null { ->f3 : () => null - - if (Math.random() < 0.5) return null; ->Math.random() < 0.5 : boolean ->Math.random() : number ->Math.random : () => number ->Math : Math ->random : () => number ->0.5 : 0.5 - - // Implicit return, but undefined is assignable to null. -} - -function f4(): string | null { ->f4 : () => string | null - - if (Math.random() < 0.5) return "string"; ->Math.random() < 0.5 : boolean ->Math.random() : number ->Math.random : () => number ->Math : Math ->random : () => number ->0.5 : 0.5 ->"string" : "string" - - // Implicit return, but undefined is assignable to null. -} - diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.js b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.js deleted file mode 100644 index 1079a3b8d707f..0000000000000 --- a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.js +++ /dev/null @@ -1,27 +0,0 @@ -//// [functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts] -function f1(): unknown { - if (Math.random() < 0.5) return true; - - // Implicit return, but undefined is assignable to unknown. -} - -function f2(): any { - // Implicit return, but undefined is assignable to any. -} - -function f3(): void { - // Implicit return, but undefined is assignable to void. -} - -//// [functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.js] -function f1() { - if (Math.random() < 0.5) - return true; - // Implicit return, but undefined is assignable to unknown. -} -function f2() { - // Implicit return, but undefined is assignable to any. -} -function f3() { - // Implicit return, but undefined is assignable to void. -} diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.symbols b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.symbols deleted file mode 100644 index e14333f69d6d6..0000000000000 --- a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.symbols +++ /dev/null @@ -1,23 +0,0 @@ -=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts === -function f1(): unknown { ->f1 : Symbol(f1, Decl(functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts, 0, 0)) - - if (Math.random() < 0.5) return true; ->Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) ->Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) - - // Implicit return, but undefined is assignable to unknown. -} - -function f2(): any { ->f2 : Symbol(f2, Decl(functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts, 4, 1)) - - // Implicit return, but undefined is assignable to any. -} - -function f3(): void { ->f3 : Symbol(f3, Decl(functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts, 8, 1)) - - // Implicit return, but undefined is assignable to void. -} diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.types b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.types deleted file mode 100644 index 5348444807452..0000000000000 --- a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.types +++ /dev/null @@ -1,27 +0,0 @@ -=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefinedStrictNullChecks.ts === -function f1(): unknown { ->f1 : () => unknown - - if (Math.random() < 0.5) return true; ->Math.random() < 0.5 : boolean ->Math.random() : number ->Math.random : () => number ->Math : Math ->random : () => number ->0.5 : 0.5 ->true : true - - // Implicit return, but undefined is assignable to unknown. -} - -function f2(): any { ->f2 : () => any - - // Implicit return, but undefined is assignable to any. -} - -function f3(): void { ->f3 : () => void - - // Implicit return, but undefined is assignable to void. -} From df2ab56a5f462a6b6d40d58db58f4452bc83a490 Mon Sep 17 00:00:00 2001 From: Maria Solano Date: Mon, 27 Mar 2023 12:04:09 -0700 Subject: [PATCH 05/10] Add type alias case --- ...ableToUndefined(strictnullchecks=false).js | 37 ++++++++++------ ...oUndefined(strictnullchecks=false).symbols | 41 ++++++++++++------ ...eToUndefined(strictnullchecks=false).types | 43 +++++++++++++------ ...ndefined(strictnullchecks=true).errors.txt | 28 +++++++----- ...nableToUndefined(strictnullchecks=true).js | 37 ++++++++++------ ...ToUndefined(strictnullchecks=true).symbols | 41 ++++++++++++------ ...leToUndefined(strictnullchecks=true).types | 43 +++++++++++++------ ...ImplicitReturnTypeAssignableToUndefined.ts | 21 ++++++--- 8 files changed, 193 insertions(+), 98 deletions(-) diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).js b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).js index e3261d1ece3d0..13870dc02f148 100644 --- a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).js +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).js @@ -5,39 +5,45 @@ function f1(): unknown { // Implicit return, but undefined is always assignable to unknown. } -function f2(): any { +type MyUnknown = unknown; +function f2(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { // Implicit return, but undefined is always assignable to any. } -function f3(): void { +function f4(): void { // Implicit return, but undefined is always assignable to void. } -function f4(): {} { +function f5(): {} { if (Math.random() < 0.5) return {}; // Implicit return, but undefined is assignable to object when strictNullChecks is off. } -function f5(): Record { +function f6(): Record { if (Math.random() < 0.5) return { "foo": true }; // Implicit return, but undefined is assignable to records (which are just fancy objects) // when strictNullChecks is off. } -function f6(): null { +function f7(): null { if (Math.random() < 0.5) return null; // Implicit return, but undefined is assignable to null when strictNullChecks is off. } -function f7(): string | null { +function f8(): string | null { if (Math.random() < 0.5) return "foo"; // Implicit return, but undefined is assignable to null when strictNullChecks is off. -} - +} //// [functionsWithImplicitReturnTypeAssignableToUndefined.js] function f1() { @@ -46,28 +52,33 @@ function f1() { // Implicit return, but undefined is always assignable to unknown. } function f2() { - // Implicit return, but undefined is always assignable to any. + if (Math.random() < 0.5) + return true; + // Implicit return, but undefined is always assignable to unknown. } function f3() { - // Implicit return, but undefined is always assignable to void. + // Implicit return, but undefined is always assignable to any. } function f4() { + // Implicit return, but undefined is always assignable to void. +} +function f5() { if (Math.random() < 0.5) return {}; // Implicit return, but undefined is assignable to object when strictNullChecks is off. } -function f5() { +function f6() { if (Math.random() < 0.5) return { "foo": true }; // Implicit return, but undefined is assignable to records (which are just fancy objects) // when strictNullChecks is off. } -function f6() { +function f7() { if (Math.random() < 0.5) return null; // Implicit return, but undefined is assignable to null when strictNullChecks is off. } -function f7() { +function f8() { if (Math.random() < 0.5) return "foo"; // Implicit return, but undefined is assignable to null when strictNullChecks is off. diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).symbols b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).symbols index 06529c66a396c..776d1aaaa0d53 100644 --- a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).symbols +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).symbols @@ -10,20 +10,34 @@ function f1(): unknown { // Implicit return, but undefined is always assignable to unknown. } -function f2(): any { ->f2 : Symbol(f2, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 4, 1)) +type MyUnknown = unknown; +>MyUnknown : Symbol(MyUnknown, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 4, 1)) + +function f2(): unknown { +>f2 : Symbol(f2, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 6, 25)) + + if (Math.random() < 0.5) return true; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { +>f3 : Symbol(f3, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 11, 1)) // Implicit return, but undefined is always assignable to any. } -function f3(): void { ->f3 : Symbol(f3, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 8, 1)) +function f4(): void { +>f4 : Symbol(f4, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 15, 1)) // Implicit return, but undefined is always assignable to void. } -function f4(): {} { ->f4 : Symbol(f4, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 12, 1)) +function f5(): {} { +>f5 : Symbol(f5, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 19, 1)) if (Math.random() < 0.5) return {}; >Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) @@ -33,22 +47,22 @@ function f4(): {} { // Implicit return, but undefined is assignable to object when strictNullChecks is off. } -function f5(): Record { ->f5 : Symbol(f5, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 18, 1)) +function f6(): Record { +>f6 : Symbol(f6, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 25, 1)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) if (Math.random() < 0.5) return { "foo": true }; >Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) >Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) ->"foo" : Symbol("foo", Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 21, 37)) +>"foo" : Symbol("foo", Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 28, 37)) // Implicit return, but undefined is assignable to records (which are just fancy objects) // when strictNullChecks is off. } -function f6(): null { ->f6 : Symbol(f6, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 25, 1)) +function f7(): null { +>f7 : Symbol(f7, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 32, 1)) if (Math.random() < 0.5) return null; >Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) @@ -58,8 +72,8 @@ function f6(): null { // Implicit return, but undefined is assignable to null when strictNullChecks is off. } -function f7(): string | null { ->f7 : Symbol(f7, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 31, 1)) +function f8(): string | null { +>f8 : Symbol(f8, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 38, 1)) if (Math.random() < 0.5) return "foo"; >Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) @@ -68,4 +82,3 @@ function f7(): string | null { // Implicit return, but undefined is assignable to null when strictNullChecks is off. } - diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).types b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).types index ac76e07adf687..d05f08c2bc427 100644 --- a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).types +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).types @@ -14,20 +14,38 @@ function f1(): unknown { // Implicit return, but undefined is always assignable to unknown. } -function f2(): any { ->f2 : () => any +type MyUnknown = unknown; +>MyUnknown : unknown + +function f2(): unknown { +>f2 : () => unknown + + if (Math.random() < 0.5) return true; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>true : true + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { +>f3 : () => any // Implicit return, but undefined is always assignable to any. } -function f3(): void { ->f3 : () => void +function f4(): void { +>f4 : () => void // Implicit return, but undefined is always assignable to void. } -function f4(): {} { ->f4 : () => {} +function f5(): {} { +>f5 : () => {} if (Math.random() < 0.5) return {}; >Math.random() < 0.5 : boolean @@ -41,8 +59,8 @@ function f4(): {} { // Implicit return, but undefined is assignable to object when strictNullChecks is off. } -function f5(): Record { ->f5 : () => Record +function f6(): Record { +>f6 : () => Record if (Math.random() < 0.5) return { "foo": true }; >Math.random() < 0.5 : boolean @@ -59,8 +77,8 @@ function f5(): Record { // when strictNullChecks is off. } -function f6(): null { ->f6 : () => null +function f7(): null { +>f7 : () => null if (Math.random() < 0.5) return null; >Math.random() < 0.5 : boolean @@ -73,8 +91,8 @@ function f6(): null { // Implicit return, but undefined is assignable to null when strictNullChecks is off. } -function f7(): string | null { ->f7 : () => string | null +function f8(): string | null { +>f8 : () => string | null if (Math.random() < 0.5) return "foo"; >Math.random() < 0.5 : boolean @@ -87,4 +105,3 @@ function f7(): string | null { // Implicit return, but undefined is assignable to null when strictNullChecks is off. } - diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).errors.txt b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).errors.txt index c5931ba955018..844cb5201977f 100644 --- a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).errors.txt +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).errors.txt @@ -1,7 +1,7 @@ -tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(15,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. -tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(21,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. +tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(22,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(28,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. -tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(34,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. +tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(35,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. +tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(41,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. ==== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts (4 errors) ==== @@ -11,15 +11,22 @@ tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(34, // Implicit return, but undefined is always assignable to unknown. } - function f2(): any { + type MyUnknown = unknown; + function f2(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. + } + + function f3(): any { // Implicit return, but undefined is always assignable to any. } - function f3(): void { + function f4(): void { // Implicit return, but undefined is always assignable to void. } - function f4(): {} { + function f5(): {} { ~~ !!! error TS2366: Function lacks ending return statement and return type does not include 'undefined'. if (Math.random() < 0.5) return {}; @@ -27,7 +34,7 @@ tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(34, // Implicit return, but undefined is assignable to object when strictNullChecks is off. } - function f5(): Record { + function f6(): Record { ~~~~~~~~~~~~~~~~~~~ !!! error TS2366: Function lacks ending return statement and return type does not include 'undefined'. if (Math.random() < 0.5) return { "foo": true }; @@ -36,7 +43,7 @@ tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(34, // when strictNullChecks is off. } - function f6(): null { + function f7(): null { ~~~~ !!! error TS2366: Function lacks ending return statement and return type does not include 'undefined'. if (Math.random() < 0.5) return null; @@ -44,11 +51,10 @@ tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(34, // Implicit return, but undefined is assignable to null when strictNullChecks is off. } - function f7(): string | null { + function f8(): string | null { ~~~~~~~~~~~~~ !!! error TS2366: Function lacks ending return statement and return type does not include 'undefined'. if (Math.random() < 0.5) return "foo"; // Implicit return, but undefined is assignable to null when strictNullChecks is off. - } - \ No newline at end of file + } \ No newline at end of file diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).js b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).js index e3261d1ece3d0..13870dc02f148 100644 --- a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).js +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).js @@ -5,39 +5,45 @@ function f1(): unknown { // Implicit return, but undefined is always assignable to unknown. } -function f2(): any { +type MyUnknown = unknown; +function f2(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { // Implicit return, but undefined is always assignable to any. } -function f3(): void { +function f4(): void { // Implicit return, but undefined is always assignable to void. } -function f4(): {} { +function f5(): {} { if (Math.random() < 0.5) return {}; // Implicit return, but undefined is assignable to object when strictNullChecks is off. } -function f5(): Record { +function f6(): Record { if (Math.random() < 0.5) return { "foo": true }; // Implicit return, but undefined is assignable to records (which are just fancy objects) // when strictNullChecks is off. } -function f6(): null { +function f7(): null { if (Math.random() < 0.5) return null; // Implicit return, but undefined is assignable to null when strictNullChecks is off. } -function f7(): string | null { +function f8(): string | null { if (Math.random() < 0.5) return "foo"; // Implicit return, but undefined is assignable to null when strictNullChecks is off. -} - +} //// [functionsWithImplicitReturnTypeAssignableToUndefined.js] function f1() { @@ -46,28 +52,33 @@ function f1() { // Implicit return, but undefined is always assignable to unknown. } function f2() { - // Implicit return, but undefined is always assignable to any. + if (Math.random() < 0.5) + return true; + // Implicit return, but undefined is always assignable to unknown. } function f3() { - // Implicit return, but undefined is always assignable to void. + // Implicit return, but undefined is always assignable to any. } function f4() { + // Implicit return, but undefined is always assignable to void. +} +function f5() { if (Math.random() < 0.5) return {}; // Implicit return, but undefined is assignable to object when strictNullChecks is off. } -function f5() { +function f6() { if (Math.random() < 0.5) return { "foo": true }; // Implicit return, but undefined is assignable to records (which are just fancy objects) // when strictNullChecks is off. } -function f6() { +function f7() { if (Math.random() < 0.5) return null; // Implicit return, but undefined is assignable to null when strictNullChecks is off. } -function f7() { +function f8() { if (Math.random() < 0.5) return "foo"; // Implicit return, but undefined is assignable to null when strictNullChecks is off. diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).symbols b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).symbols index 06529c66a396c..776d1aaaa0d53 100644 --- a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).symbols +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).symbols @@ -10,20 +10,34 @@ function f1(): unknown { // Implicit return, but undefined is always assignable to unknown. } -function f2(): any { ->f2 : Symbol(f2, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 4, 1)) +type MyUnknown = unknown; +>MyUnknown : Symbol(MyUnknown, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 4, 1)) + +function f2(): unknown { +>f2 : Symbol(f2, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 6, 25)) + + if (Math.random() < 0.5) return true; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { +>f3 : Symbol(f3, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 11, 1)) // Implicit return, but undefined is always assignable to any. } -function f3(): void { ->f3 : Symbol(f3, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 8, 1)) +function f4(): void { +>f4 : Symbol(f4, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 15, 1)) // Implicit return, but undefined is always assignable to void. } -function f4(): {} { ->f4 : Symbol(f4, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 12, 1)) +function f5(): {} { +>f5 : Symbol(f5, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 19, 1)) if (Math.random() < 0.5) return {}; >Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) @@ -33,22 +47,22 @@ function f4(): {} { // Implicit return, but undefined is assignable to object when strictNullChecks is off. } -function f5(): Record { ->f5 : Symbol(f5, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 18, 1)) +function f6(): Record { +>f6 : Symbol(f6, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 25, 1)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) if (Math.random() < 0.5) return { "foo": true }; >Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) >Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) ->"foo" : Symbol("foo", Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 21, 37)) +>"foo" : Symbol("foo", Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 28, 37)) // Implicit return, but undefined is assignable to records (which are just fancy objects) // when strictNullChecks is off. } -function f6(): null { ->f6 : Symbol(f6, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 25, 1)) +function f7(): null { +>f7 : Symbol(f7, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 32, 1)) if (Math.random() < 0.5) return null; >Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) @@ -58,8 +72,8 @@ function f6(): null { // Implicit return, but undefined is assignable to null when strictNullChecks is off. } -function f7(): string | null { ->f7 : Symbol(f7, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 31, 1)) +function f8(): string | null { +>f8 : Symbol(f8, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 38, 1)) if (Math.random() < 0.5) return "foo"; >Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) @@ -68,4 +82,3 @@ function f7(): string | null { // Implicit return, but undefined is assignable to null when strictNullChecks is off. } - diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).types b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).types index ac76e07adf687..d05f08c2bc427 100644 --- a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).types +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).types @@ -14,20 +14,38 @@ function f1(): unknown { // Implicit return, but undefined is always assignable to unknown. } -function f2(): any { ->f2 : () => any +type MyUnknown = unknown; +>MyUnknown : unknown + +function f2(): unknown { +>f2 : () => unknown + + if (Math.random() < 0.5) return true; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>true : true + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { +>f3 : () => any // Implicit return, but undefined is always assignable to any. } -function f3(): void { ->f3 : () => void +function f4(): void { +>f4 : () => void // Implicit return, but undefined is always assignable to void. } -function f4(): {} { ->f4 : () => {} +function f5(): {} { +>f5 : () => {} if (Math.random() < 0.5) return {}; >Math.random() < 0.5 : boolean @@ -41,8 +59,8 @@ function f4(): {} { // Implicit return, but undefined is assignable to object when strictNullChecks is off. } -function f5(): Record { ->f5 : () => Record +function f6(): Record { +>f6 : () => Record if (Math.random() < 0.5) return { "foo": true }; >Math.random() < 0.5 : boolean @@ -59,8 +77,8 @@ function f5(): Record { // when strictNullChecks is off. } -function f6(): null { ->f6 : () => null +function f7(): null { +>f7 : () => null if (Math.random() < 0.5) return null; >Math.random() < 0.5 : boolean @@ -73,8 +91,8 @@ function f6(): null { // Implicit return, but undefined is assignable to null when strictNullChecks is off. } -function f7(): string | null { ->f7 : () => string | null +function f8(): string | null { +>f8 : () => string | null if (Math.random() < 0.5) return "foo"; >Math.random() < 0.5 : boolean @@ -87,4 +105,3 @@ function f7(): string | null { // Implicit return, but undefined is assignable to null when strictNullChecks is off. } - diff --git a/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts b/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts index e11e23de19871..767d640015461 100644 --- a/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts +++ b/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts @@ -7,35 +7,42 @@ function f1(): unknown { // Implicit return, but undefined is always assignable to unknown. } -function f2(): any { +type MyUnknown = unknown; +function f2(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { // Implicit return, but undefined is always assignable to any. } -function f3(): void { +function f4(): void { // Implicit return, but undefined is always assignable to void. } -function f4(): {} { +function f5(): {} { if (Math.random() < 0.5) return {}; // Implicit return, but undefined is assignable to object when strictNullChecks is off. } -function f5(): Record { +function f6(): Record { if (Math.random() < 0.5) return { "foo": true }; // Implicit return, but undefined is assignable to records (which are just fancy objects) // when strictNullChecks is off. } -function f6(): null { +function f7(): null { if (Math.random() < 0.5) return null; // Implicit return, but undefined is assignable to null when strictNullChecks is off. } -function f7(): string | null { +function f8(): string | null { if (Math.random() < 0.5) return "foo"; // Implicit return, but undefined is assignable to null when strictNullChecks is off. -} +} \ No newline at end of file From f4974904f5db48f4fc6a00c3e2cd5eef743ea11f Mon Sep 17 00:00:00 2001 From: Maria Solano Date: Mon, 27 Mar 2023 12:15:54 -0700 Subject: [PATCH 06/10] Daniel was right --- src/compiler/checker.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 09ee2d4107c38..435ae83907ba2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -35660,7 +35660,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const type = returnType && unwrapReturnType(returnType, functionFlags); // Functions with an explicitly specified 'undefined, 'void' or 'any' return type don't need any return expressions. - if (type && maybeTypeOfKind(type, TypeFlags.Undefined | TypeFlags.Void | TypeFlags.Any)) { + // 'unknown' is also fine because it is always assignable to 'undefined'. + if (type && maybeTypeOfKind(type, TypeFlags.Undefined | TypeFlags.Void | TypeFlags.Any | TypeFlags.Unknown)) { return; } @@ -35686,7 +35687,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error(errorNode, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); } } - else if (type && strictNullChecks && !isTypeAssignableTo(undefinedType, type)) { + else if (type && strictNullChecks) { error(errorNode, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined); } else if (compilerOptions.noImplicitReturns) { From 2f36455ca94cea1616f0d33c9552db77e7c9348c Mon Sep 17 00:00:00 2001 From: Maria Solano Date: Mon, 27 Mar 2023 12:17:40 -0700 Subject: [PATCH 07/10] Keeping the other check just to be safe --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 435ae83907ba2..4df74e6e124e2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -35687,7 +35687,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error(errorNode, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); } } - else if (type && strictNullChecks) { + else if (type && strictNullChecks && !isTypeAssignableTo(undefinedType, type)) { error(errorNode, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined); } else if (compilerOptions.noImplicitReturns) { From 769251f980c4377279b436f5003bcfe14727d824 Mon Sep 17 00:00:00 2001 From: Maria Solano Date: Mon, 27 Mar 2023 12:20:43 -0700 Subject: [PATCH 08/10] Update comment --- src/compiler/checker.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4df74e6e124e2..a826a9e997ca0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -35659,8 +35659,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const functionFlags = getFunctionFlags(func); const type = returnType && unwrapReturnType(returnType, functionFlags); - // Functions with an explicitly specified 'undefined, 'void' or 'any' return type don't need any return expressions. - // 'unknown' is also fine because it is always assignable to 'undefined'. + // Functions with an explicitly specified 'undefined, 'void', 'any' or 'unknown' return type don't need any return expressions. if (type && maybeTypeOfKind(type, TypeFlags.Undefined | TypeFlags.Void | TypeFlags.Any | TypeFlags.Unknown)) { return; } From b10847a756b83a679ee795a71c764a28c657060f Mon Sep 17 00:00:00 2001 From: Maria Solano Date: Mon, 27 Mar 2023 12:28:55 -0700 Subject: [PATCH 09/10] Revert "Keeping the other check just to be safe" This reverts commit 2f36455ca94cea1616f0d33c9552db77e7c9348c. --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a826a9e997ca0..74ca86a5e040f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -35686,7 +35686,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error(errorNode, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); } } - else if (type && strictNullChecks && !isTypeAssignableTo(undefinedType, type)) { + else if (type && strictNullChecks) { error(errorNode, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined); } else if (compilerOptions.noImplicitReturns) { From 6956159d25a0addb46662920c6f09e4c3d851c0b Mon Sep 17 00:00:00 2001 From: Maria Solano Date: Mon, 27 Mar 2023 13:00:20 -0700 Subject: [PATCH 10/10] Update baseline --- tests/baselines/reference/unknownType1.errors.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/baselines/reference/unknownType1.errors.txt b/tests/baselines/reference/unknownType1.errors.txt index 32034c8e2b9d9..f86564eb5ce8b 100644 --- a/tests/baselines/reference/unknownType1.errors.txt +++ b/tests/baselines/reference/unknownType1.errors.txt @@ -20,7 +20,6 @@ tests/cases/conformance/types/unknown/unknownType1.ts(128,5): error TS2322: Type tests/cases/conformance/types/unknown/unknownType1.ts(129,5): error TS2322: Type 'number' is not assignable to type '{ [x: string]: unknown; }'. tests/cases/conformance/types/unknown/unknownType1.ts(143,29): error TS2698: Spread types may only be created from object types. tests/cases/conformance/types/unknown/unknownType1.ts(144,29): error TS2698: Spread types may only be created from object types. -tests/cases/conformance/types/unknown/unknownType1.ts(150,17): error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/types/unknown/unknownType1.ts(156,14): error TS2700: Rest types may only be created from object types. tests/cases/conformance/types/unknown/unknownType1.ts(162,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor. tests/cases/conformance/types/unknown/unknownType1.ts(170,9): error TS2322: Type 'T' is not assignable to type '{}'. @@ -28,7 +27,7 @@ tests/cases/conformance/types/unknown/unknownType1.ts(171,9): error TS2322: Type tests/cases/conformance/types/unknown/unknownType1.ts(181,5): error TS2322: Type 'T' is not assignable to type '{}'. -==== tests/cases/conformance/types/unknown/unknownType1.ts (27 errors) ==== +==== tests/cases/conformance/types/unknown/unknownType1.ts (26 errors) ==== // In an intersection everything absorbs unknown type T00 = unknown & null; // null @@ -222,8 +221,6 @@ tests/cases/conformance/types/unknown/unknownType1.ts(181,5): error TS2322: Type // Functions with unknown return type don't need return expressions function f27(): unknown { - ~~~~~~~ -!!! error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. } // Rest type cannot be created from unknown