blob: 82f5e61718afccb1aca9d43c69df83f0f81235e6 [file] [log] [blame]
// Copyright (c) 2024, 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.
// This test verifies that extension type erasure is used when computing whether
// a pattern fully covers the matched value type. This is necessary to avoid a
// "catch-22" situation in which flow analysis and the exhaustiveness checker
// disagree about the exhaustiveness of a switch statement. For details see
// https://github.com/dart-lang/language/issues/3534#issuecomment-1885839268.
import '../static_type_helper.dart';
extension type E(int i) {}
// Helper method used to verify that a local variable has been definitely
// assigned.
void checkAssigned(Object? o) {}
testIfCase(E e, int i) {
int? j = 0; // promotes `j` to `int`
j.expectStaticType<Exactly<int>>();
if (e case int _) {
// reachable
} else {
// unreachable
j = null; // demotes `j`
j.expectStaticType<Exactly<int?>>();
}
// `j` is still promoted because the demotion is in an unreachable code path.
j.expectStaticType<Exactly<int>>();
if (i case E _) {
// reachable
} else {
// unreachable
j = null; // demotes `j`
j.expectStaticType<Exactly<int?>>();
}
// `j` is still promoted because the demotion is in an unreachable code path.
j.expectStaticType<Exactly<int>>();
}
testSwitchStatement(E e, int i) {
{
int j;
switch (e) {
case int _:
j = 0;
}
// `int` fully covers `E`, so `j` has been definitely assigned now.
checkAssigned(j);
}
{
int j;
switch (i) {
case E _:
j = 0;
}
// `int` fully covers `E`, so `j` has been definitely assigned now.
checkAssigned(j);
}
}
main() {
testIfCase(E(0), 0);
testSwitchStatement(E(0), 0);
}