Skip to content

Commit

Permalink
switch typeof any could be checked for unreachable
Browse files Browse the repository at this point in the history
  • Loading branch information
ShuiRuTian committed Jul 2, 2020
1 parent 9ac7412 commit f3e4ba4
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 6 deletions.
17 changes: 11 additions & 6 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ namespace ts {
UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy,
NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy,
EmptyObjectStrictFacts = All & ~(EQUndefined | EQNull | EQUndefinedOrNull),
AllTypeofNE = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | NEUndefined,
EmptyObjectFacts = All,
}

Expand Down Expand Up @@ -28565,6 +28566,10 @@ namespace ts {
// notEqualFacts states that the type of the switched value is not equal to every type in the switch.
const notEqualFacts = getFactsFromTypeofSwitch(0, 0, witnesses, /*hasDefault*/ true);
const type = getBaseConstraintOfType(operandType) || operandType;
// Take any as a specail condition. Maybe we could change type to a union containing all primitive types.
if (type.flags = TypeFlags.Any) {
return (TypeFacts.AllTypeofNE & notEqualFacts) === TypeFacts.AllTypeofNE;
}
return !!(filterType(type, t => (getTypeFacts(t) & notEqualFacts) === notEqualFacts).flags & TypeFlags.Never);
}
const type = getTypeOfExpression(node.expression);
Expand Down Expand Up @@ -30345,12 +30350,12 @@ namespace ts {
}
// If a type has been cached for the node, return it.
// Note: this is not only cache, without this, some test case would always runs, such as binaryArithmeticControlFlowGraphNotTooLarge.
if (node.flags & NodeFlags.TypeCached && flowTypeCache) {
const cachedType = flowTypeCache[getNodeId(node)];
if (cachedType) {
return cachedType;
}
}
// if (node.flags & NodeFlags.TypeCached && flowTypeCache) {
// const cachedType = flowTypeCache[getNodeId(node)];
// if (cachedType) {
// return cachedType;
// }
// }
const startInvocationCount = flowInvocationCount;
const type = checkExpression(node);
// If control flow analysis was required to determine the type, it is worth caching.
Expand Down
19 changes: 19 additions & 0 deletions tests/baselines/reference/unreachableSwitchTypeofAny.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
tests/cases/compiler/unreachable.ts(12,5): error TS7027: Unreachable code detected.


==== tests/cases/compiler/unreachable.ts (1 errors) ====
const unreachable = (x: any): number => {
switch (typeof x) {
case 'string': return 0
case 'number': return 0
case 'bigint': return 0
case 'boolean': return 0
case 'symbol': return 0
case 'undefined': return 0
case 'object': return 0
case 'function': return 0
}
x;
~~
!!! error TS7027: Unreachable code detected.
}
29 changes: 29 additions & 0 deletions tests/baselines/reference/unreachableSwitchTypeofAny.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//// [unreachable.ts]
const unreachable = (x: any): number => {
switch (typeof x) {
case 'string': return 0
case 'number': return 0
case 'bigint': return 0
case 'boolean': return 0
case 'symbol': return 0
case 'undefined': return 0
case 'object': return 0
case 'function': return 0
}
x;
}

//// [unreachable.js]
var unreachable = function (x) {
switch (typeof x) {
case 'string': return 0;
case 'number': return 0;
case 'bigint': return 0;
case 'boolean': return 0;
case 'symbol': return 0;
case 'undefined': return 0;
case 'object': return 0;
case 'function': return 0;
}
x;
};
20 changes: 20 additions & 0 deletions tests/baselines/reference/unreachableSwitchTypeofAny.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
=== tests/cases/compiler/unreachable.ts ===
const unreachable = (x: any): number => {
>unreachable : Symbol(unreachable, Decl(unreachable.ts, 0, 5))
>x : Symbol(x, Decl(unreachable.ts, 0, 21))

switch (typeof x) {
>x : Symbol(x, Decl(unreachable.ts, 0, 21))

case 'string': return 0
case 'number': return 0
case 'bigint': return 0
case 'boolean': return 0
case 'symbol': return 0
case 'undefined': return 0
case 'object': return 0
case 'function': return 0
}
x;
>x : Symbol(x, Decl(unreachable.ts, 0, 21))
}
45 changes: 45 additions & 0 deletions tests/baselines/reference/unreachableSwitchTypeofAny.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
=== tests/cases/compiler/unreachable.ts ===
const unreachable = (x: any): number => {
>unreachable : (x: any) => number
>(x: any): number => { switch (typeof x) { case 'string': return 0 case 'number': return 0 case 'bigint': return 0 case 'boolean': return 0 case 'symbol': return 0 case 'undefined': return 0 case 'object': return 0 case 'function': return 0 } x;} : (x: any) => number
>x : any

switch (typeof x) {
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : any

case 'string': return 0
>'string' : "string"
>0 : 0

case 'number': return 0
>'number' : "number"
>0 : 0

case 'bigint': return 0
>'bigint' : "bigint"
>0 : 0

case 'boolean': return 0
>'boolean' : "boolean"
>0 : 0

case 'symbol': return 0
>'symbol' : "symbol"
>0 : 0

case 'undefined': return 0
>'undefined' : "undefined"
>0 : 0

case 'object': return 0
>'object' : "object"
>0 : 0

case 'function': return 0
>'function' : "function"
>0 : 0
}
x;
>x : any
}
16 changes: 16 additions & 0 deletions tests/cases/compiler/unreachableSwitchTypeofAny.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// @Filename: unreachable.ts
// @outDir: out
// @allowUnreachableCode: false
const unreachable = (x: any): number => {
switch (typeof x) {
case 'string': return 0
case 'number': return 0
case 'bigint': return 0
case 'boolean': return 0
case 'symbol': return 0
case 'undefined': return 0
case 'object': return 0
case 'function': return 0
}
x;
}

0 comments on commit f3e4ba4

Please sign in to comment.