Files
sdk/pkg/compiler/test/inference/data/switch.dart
T
Nate Biggs 709c4202b5 [dart2js] Global inference should merge breaks after each case statement
The type bounds in each case statement can diverge when a break is hit in a conditional control flow block. Previously the switch statement was just merging the end state after visiting each case block. Instead we need to merge all possible termination states for each case.

This is trivial when the switch only contains breaks. The termination states are just those when we reach each break (or the end of the switch if there's a default).

When there are switch-continue statements we must reconcile the states that flow into each targeted switch before reconciling the types of those targeted switches themselves. We achieve that by making two passes over the cases, the first to gather the continue states and the second to update the switches affected by those states. Similar to before this is done repeatedly until a fixed point is reached.

Fixed: 46770
Change-Id: I5795748a4591e6a1dc283f2a54129e09a20d13d8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/250200
Reviewed-by: Mayank Patke <fishythefish@google.com>
Commit-Queue: Nate Biggs <natebiggs@google.com>
2022-07-07 15:38:51 +00:00

144 lines
3.6 KiB
Dart

// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.7
/*member: main:[null]*/
main() {
switchWithoutDefault();
switchWithDefault();
switchWithDefaultWithoutBreak();
switchWithContinue();
switchWithoutContinue();
}
////////////////////////////////////////////////////////////////////////////////
// Switch statement without default case.
////////////////////////////////////////////////////////////////////////////////
/*member: _switchWithoutDefault:Union(null, [exact=JSString], [exact=JSUInt31])*/
_switchWithoutDefault(/*[exact=JSUInt31]*/ o) {
var local;
switch (o) {
case 0:
local = 0;
break;
case 1:
local = '';
break;
}
return local;
}
/*member: switchWithoutDefault:[null]*/
switchWithoutDefault() {
_switchWithoutDefault(0);
_switchWithoutDefault(1);
}
////////////////////////////////////////////////////////////////////////////////
// Switch statement with default case.
////////////////////////////////////////////////////////////////////////////////
/*member: _switchWithDefault:Union([exact=JSString], [exact=JSUInt31])*/
_switchWithDefault(/*[exact=JSUInt31]*/ o) {
var local;
switch (o) {
case 0:
local = 0;
break;
case 1:
default:
local = '';
break;
}
return local;
}
/*member: switchWithDefault:[null]*/
switchWithDefault() {
_switchWithDefault(0);
_switchWithDefault(1);
}
////////////////////////////////////////////////////////////////////////////////
// Switch statement with default case without break.
////////////////////////////////////////////////////////////////////////////////
/*member: _switchWithDefaultWithoutBreak:Union([exact=JSString], [exact=JSUInt31])*/
_switchWithDefaultWithoutBreak(/*[exact=JSUInt31]*/ o) {
var local;
switch (o) {
case 0:
local = 0;
break;
case 1:
default:
local = '';
}
return local;
}
/*member: switchWithDefaultWithoutBreak:[null]*/
switchWithDefaultWithoutBreak() {
_switchWithDefaultWithoutBreak(0);
_switchWithDefaultWithoutBreak(1);
}
////////////////////////////////////////////////////////////////////////////////
// Switch statement with continue.
////////////////////////////////////////////////////////////////////////////////
/*member: _switchWithContinue:Union([exact=JSBool], [exact=JSString])*/
_switchWithContinue(/*[exact=JSUInt31]*/ o) {
dynamic local;
switch (o) {
case 0:
local = 0;
continue label;
label:
case 1:
local = local. /*Union(null, [exact=JSString], [exact=JSUInt31])*/ isEven;
break;
case 2:
default:
local = '';
}
return local;
}
/*member: switchWithContinue:[null]*/
switchWithContinue() {
_switchWithContinue(0);
_switchWithContinue(1);
}
////////////////////////////////////////////////////////////////////////////////
// Switch statement without continue. Identical to previous test but without
// the continue statement.
////////////////////////////////////////////////////////////////////////////////
/*member: _switchWithoutContinue:Union([exact=JSString], [exact=JSUInt31])*/
_switchWithoutContinue(/*[exact=JSUInt31]*/ o) {
dynamic local;
switch (o) {
case 0:
local = 0;
break;
case 1:
local = local. /*[null]*/ isEven;
break;
case 2:
default:
local = '';
}
return local;
}
/*member: switchWithoutContinue:[null]*/
switchWithoutContinue() {
_switchWithoutContinue(0);
_switchWithoutContinue(1);
}