Ignore switch statement bypass control flows that produce never (#51703)

* Ignore switch statement bypass control flows that produce 'never'

* Add regression test
This commit is contained in:
Anders Hejlsberg 2022-12-07 16:19:09 -08:00 committed by GitHub
parent d43112a75b
commit b9d0e17298
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 140 additions and 1 deletions

View File

@ -26073,7 +26073,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// If the bypass flow contributes a type we haven't seen yet and the switch statement
// isn't exhaustive, process the bypass flow type. Since exhaustiveness checks increase
// the risk of circularities, we only want to perform them when they make a difference.
if (!contains(antecedentTypes, type) && !isExhaustiveSwitchStatement(bypassFlow.switchStatement)) {
if (!(type.flags & TypeFlags.Never) && !contains(antecedentTypes, type) && !isExhaustiveSwitchStatement(bypassFlow.switchStatement)) {
if (type === declaredType && declaredType === initialType) {
return type;
}

View File

@ -22,4 +22,22 @@ tests/cases/compiler/exhaustiveSwitchCheckCircularity.ts(14,26): error TS2345: A
}
}
}
// Repro from #51688
declare function functionB(key: string): string;
function functionC(): void {
let unionVal: "A" | "B" = "A";
while (true) {
let key: string;
switch (unionVal) {
case "A": {
key = "AA";
break;
}
}
functionB(key);
}
}

View File

@ -17,6 +17,24 @@ function f() {
}
}
}
// Repro from #51688
declare function functionB(key: string): string;
function functionC(): void {
let unionVal: "A" | "B" = "A";
while (true) {
let key: string;
switch (unionVal) {
case "A": {
key = "AA";
break;
}
}
functionB(key);
}
}
//// [exhaustiveSwitchCheckCircularity.js]
@ -36,3 +54,16 @@ function f() {
}
}
}
function functionC() {
var unionVal = "A";
while (true) {
var key = void 0;
switch (unionVal) {
case "A": {
key = "AA";
break;
}
}
functionB(key);
}
}

View File

@ -32,3 +32,35 @@ function f() {
}
}
// Repro from #51688
declare function functionB(key: string): string;
>functionB : Symbol(functionB, Decl(exhaustiveSwitchCheckCircularity.ts, 17, 1))
>key : Symbol(key, Decl(exhaustiveSwitchCheckCircularity.ts, 21, 27))
function functionC(): void {
>functionC : Symbol(functionC, Decl(exhaustiveSwitchCheckCircularity.ts, 21, 48))
let unionVal: "A" | "B" = "A";
>unionVal : Symbol(unionVal, Decl(exhaustiveSwitchCheckCircularity.ts, 24, 7))
while (true) {
let key: string;
>key : Symbol(key, Decl(exhaustiveSwitchCheckCircularity.ts, 26, 11))
switch (unionVal) {
>unionVal : Symbol(unionVal, Decl(exhaustiveSwitchCheckCircularity.ts, 24, 7))
case "A": {
key = "AA";
>key : Symbol(key, Decl(exhaustiveSwitchCheckCircularity.ts, 26, 11))
break;
}
}
functionB(key);
>functionB : Symbol(functionB, Decl(exhaustiveSwitchCheckCircularity.ts, 17, 1))
>key : Symbol(key, Decl(exhaustiveSwitchCheckCircularity.ts, 26, 11))
}
}

View File

@ -41,3 +41,43 @@ function f() {
}
}
// Repro from #51688
declare function functionB(key: string): string;
>functionB : (key: string) => string
>key : string
function functionC(): void {
>functionC : () => void
let unionVal: "A" | "B" = "A";
>unionVal : "A" | "B"
>"A" : "A"
while (true) {
>true : true
let key: string;
>key : string
switch (unionVal) {
>unionVal : "A"
case "A": {
>"A" : "A"
key = "AA";
>key = "AA" : "AA"
>key : string
>"AA" : "AA"
break;
}
}
functionB(key);
>functionB(key) : string
>functionB : (key: string) => string
>key : string
}
}

View File

@ -18,3 +18,21 @@ function f() {
}
}
}
// Repro from #51688
declare function functionB(key: string): string;
function functionC(): void {
let unionVal: "A" | "B" = "A";
while (true) {
let key: string;
switch (unionVal) {
case "A": {
key = "AA";
break;
}
}
functionB(key);
}
}