Skip to content

Commit

Permalink
Treat exhaustive switch as last statement in function microsoft#18882
Browse files Browse the repository at this point in the history
  • Loading branch information
charlespierce committed Nov 16, 2017
1 parent 8a7b844 commit 1fcb692
Show file tree
Hide file tree
Showing 6 changed files with 326 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17471,8 +17471,8 @@ namespace ts {
if (!(func.flags & NodeFlags.HasImplicitReturn)) {
return false;
}
const lastStatement = lastOrUndefined((<Block>func.body).statements);
if (lastStatement && lastStatement.kind === SyntaxKind.SwitchStatement && isExhaustiveSwitchStatement(<SwitchStatement>lastStatement)) {

if (some((<Block>func.body).statements, statement => statement.kind === SyntaxKind.SwitchStatement && isExhaustiveSwitchStatement(<SwitchStatement>statement))) {
return false;
}
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
tests/cases/compiler/exhaustiveSwitchImplicitReturn.ts(35,32): error TS7030: Not all code paths return a value.


==== tests/cases/compiler/exhaustiveSwitchImplicitReturn.ts (1 errors) ====
function foo1(bar: "a"): number {
switch(bar) {
case "a":
return 1;
}
}

function foo2(bar: "a"): number {
switch(bar) {
case "a":
return 1;
}

let unusedVariable;
}

function foo3(bar: "a"): number {
switch(bar) {
case "a":
return 1;
}

function neverCalled() {}
}

function foo4(bar: "a"): number {
switch(bar) {
case "a":
return 1;
}

foo3(bar);
}

function foo5(bar: "a" | "b"): number {
~~~~~~
!!! error TS7030: Not all code paths return a value.
switch(bar) {
case "a":
return 1;
}
}

77 changes: 77 additions & 0 deletions tests/baselines/reference/exhaustiveSwitchImplicitReturn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//// [exhaustiveSwitchImplicitReturn.ts]
function foo1(bar: "a"): number {
switch(bar) {
case "a":
return 1;
}
}

function foo2(bar: "a"): number {
switch(bar) {
case "a":
return 1;
}

let unusedVariable;
}

function foo3(bar: "a"): number {
switch(bar) {
case "a":
return 1;
}

function neverCalled() {}
}

function foo4(bar: "a"): number {
switch(bar) {
case "a":
return 1;
}

foo3(bar);
}

function foo5(bar: "a" | "b"): number {
switch(bar) {
case "a":
return 1;
}
}


//// [exhaustiveSwitchImplicitReturn.js]
function foo1(bar) {
switch (bar) {
case "a":
return 1;
}
}
function foo2(bar) {
switch (bar) {
case "a":
return 1;
}
var unusedVariable;
}
function foo3(bar) {
switch (bar) {
case "a":
return 1;
}
function neverCalled() { }
}
function foo4(bar) {
switch (bar) {
case "a":
return 1;
}
foo3(bar);
}
function foo5(bar) {
switch (bar) {
case "a":
return 1;
}
}
71 changes: 71 additions & 0 deletions tests/baselines/reference/exhaustiveSwitchImplicitReturn.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
=== tests/cases/compiler/exhaustiveSwitchImplicitReturn.ts ===
function foo1(bar: "a"): number {
>foo1 : Symbol(foo1, Decl(exhaustiveSwitchImplicitReturn.ts, 0, 0))
>bar : Symbol(bar, Decl(exhaustiveSwitchImplicitReturn.ts, 0, 14))

switch(bar) {
>bar : Symbol(bar, Decl(exhaustiveSwitchImplicitReturn.ts, 0, 14))

case "a":
return 1;
}
}

function foo2(bar: "a"): number {
>foo2 : Symbol(foo2, Decl(exhaustiveSwitchImplicitReturn.ts, 5, 1))
>bar : Symbol(bar, Decl(exhaustiveSwitchImplicitReturn.ts, 7, 14))

switch(bar) {
>bar : Symbol(bar, Decl(exhaustiveSwitchImplicitReturn.ts, 7, 14))

case "a":
return 1;
}

let unusedVariable;
>unusedVariable : Symbol(unusedVariable, Decl(exhaustiveSwitchImplicitReturn.ts, 13, 7))
}

function foo3(bar: "a"): number {
>foo3 : Symbol(foo3, Decl(exhaustiveSwitchImplicitReturn.ts, 14, 1))
>bar : Symbol(bar, Decl(exhaustiveSwitchImplicitReturn.ts, 16, 14))

switch(bar) {
>bar : Symbol(bar, Decl(exhaustiveSwitchImplicitReturn.ts, 16, 14))

case "a":
return 1;
}

function neverCalled() {}
>neverCalled : Symbol(neverCalled, Decl(exhaustiveSwitchImplicitReturn.ts, 20, 5))
}

function foo4(bar: "a"): number {
>foo4 : Symbol(foo4, Decl(exhaustiveSwitchImplicitReturn.ts, 23, 1))
>bar : Symbol(bar, Decl(exhaustiveSwitchImplicitReturn.ts, 25, 14))

switch(bar) {
>bar : Symbol(bar, Decl(exhaustiveSwitchImplicitReturn.ts, 25, 14))

case "a":
return 1;
}

foo3(bar);
>foo3 : Symbol(foo3, Decl(exhaustiveSwitchImplicitReturn.ts, 14, 1))
>bar : Symbol(bar, Decl(exhaustiveSwitchImplicitReturn.ts, 25, 14))
}

function foo5(bar: "a" | "b"): number {
>foo5 : Symbol(foo5, Decl(exhaustiveSwitchImplicitReturn.ts, 32, 1))
>bar : Symbol(bar, Decl(exhaustiveSwitchImplicitReturn.ts, 34, 14))

switch(bar) {
>bar : Symbol(bar, Decl(exhaustiveSwitchImplicitReturn.ts, 34, 14))

case "a":
return 1;
}
}

87 changes: 87 additions & 0 deletions tests/baselines/reference/exhaustiveSwitchImplicitReturn.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
=== tests/cases/compiler/exhaustiveSwitchImplicitReturn.ts ===
function foo1(bar: "a"): number {
>foo1 : (bar: "a") => number
>bar : "a"

switch(bar) {
>bar : "a"

case "a":
>"a" : "a"

return 1;
>1 : 1
}
}

function foo2(bar: "a"): number {
>foo2 : (bar: "a") => number
>bar : "a"

switch(bar) {
>bar : "a"

case "a":
>"a" : "a"

return 1;
>1 : 1
}

let unusedVariable;
>unusedVariable : any
}

function foo3(bar: "a"): number {
>foo3 : (bar: "a") => number
>bar : "a"

switch(bar) {
>bar : "a"

case "a":
>"a" : "a"

return 1;
>1 : 1
}

function neverCalled() {}
>neverCalled : () => void
}

function foo4(bar: "a"): number {
>foo4 : (bar: "a") => number
>bar : "a"

switch(bar) {
>bar : "a"

case "a":
>"a" : "a"

return 1;
>1 : 1
}

foo3(bar);
>foo3(bar) : number
>foo3 : (bar: "a") => number
>bar : never
}

function foo5(bar: "a" | "b"): number {
>foo5 : (bar: "a" | "b") => number
>bar : "a" | "b"

switch(bar) {
>bar : "a" | "b"

case "a":
>"a" : "a"

return 1;
>1 : 1
}
}

42 changes: 42 additions & 0 deletions tests/cases/compiler/exhaustiveSwitchImplicitReturn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// @noImplicitReturns: true

function foo1(bar: "a"): number {
switch(bar) {
case "a":
return 1;
}
}

function foo2(bar: "a"): number {
switch(bar) {
case "a":
return 1;
}

let unusedVariable;
}

function foo3(bar: "a"): number {
switch(bar) {
case "a":
return 1;
}

function neverCalled() {}
}

function foo4(bar: "a"): number {
switch(bar) {
case "a":
return 1;
}

foo3(bar);
}

function foo5(bar: "a" | "b"): number {
switch(bar) {
case "a":
return 1;
}
}

0 comments on commit 1fcb692

Please sign in to comment.