blob: f71e30655f0c52c43cb5ae86dabdf3bdd984d364 [file] [log] [blame]
// Copyright (c) 2023, 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.
import "../../static_type_helper.dart";
import "dart:async";
test() {
{
// This test verifies that when a pattern match occurs inside a guard, flow
// analysis doesn't mix up the "unmatched" states between the inner and
// outer pattern matches.
int? reachability0 = 0;
int? reachability1 = 0;
var x = expr<FutureOr<int>>();
var y = expr<FutureOr<String>>();
if (expr<bool>()) {
if (x case int _
when pickSecond(() {
if (y case String _) {
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<String>>();
} else {
x.expectStaticType<Exactly<int>>();
// Note that even though flow analysis doesn't run the
// exhaustiveness checker, it understands that `y` has type
// `Future<String>` here, because this is understood by the
// "factor" algorithm (see
// https://github.com/dart-lang/language/blob/main/resources/type-system/flow-analysis.md#promotion)
y.expectStaticType<Exactly<Future<String>>>();
}
}, throw expr<Object>())) {
// Unreachable because the guard clause throws
reachability0 = null;
} else {
reachability1 = null;
// `x` is known to have type `Future<int>` because if it had type `int`,
// the guard clause would have executed (and an exception would have
// been thrown).
x.expectStaticType<Exactly<Future<int>>>();
}
}
reachability0.expectStaticType<Exactly<int>>();
reachability1.expectStaticType<Exactly<int?>>();
}
}
T expr<T>() => throw UnimplementedError();
T pickSecond<T>(dynamic x, T y) => y;
main() {}