blob: 9bd3eb60c1e480af820ef73e12068d7845b1bd7d [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";
test() {
{
// Promotions from the LHS and RHS are joined using the normal flow analysis
// rules (common promotions are retained), so if the LHS promotes to `num`
// and then to `int`, whereas the RHS promotes to just `num`, then the
// promotion to `num` is retained.
var x = expr<Object>();
if (x case (num() && int()) || num()) {
x.expectStaticType<Exactly<num>>();
}
}
{
// Whereas if the RHS promotes to `num` and then to `int`, whereas the LHS
// promotes to just `num`, then the promotion to `num` is retained.
var x = expr<Object>();
if (x case num() || (num() && int())) {
x.expectStaticType<Exactly<num>>();
}
}
{
// Promotions of the matched value are treated similarly; in this case, the
// LHS promotes to `num` and then to `int`, whereas the RHS promotes to just
// `num`, so the promotion to `num` is retained.
if (expr<Object>() case ((num() && int()) || num()) && var x) {
x.expectStaticType<Exactly<num>>();
}
}
{
// And in this case, the RHS promotes to `num` and then to `int`, whereas
// the LHS promotes to just `num`, so the promotion to `num` is retained.
if (expr<Object>() case (num() || (num() && int())) && var x) {
x.expectStaticType<Exactly<num>>();
}
}
{
// Promotions of explicitly declared match variables are treated similarly;
// in this case, the LHS promotes `x` to `int`, whereas the RHS does not, so
// `x` is not promoted.
if (expr<int?>() case int? x? || int? x) {
x.expectStaticType<Exactly<int?>>();
}
}
{
// And in this case, the RHS promotes `x` to `int`, whereas the LHS does
// not, so `x` is not promoted.
if (expr<int?>() case int? x || int? x?) {
x.expectStaticType<Exactly<int?>>();
}
}
{
// And in this case, both the LHS and RHS promote `x` to `int`, so the
// promotion to `int` is retained.
if (expr<int?>() case int? x? || int? x?) {
x.expectStaticType<Exactly<int>>();
}
}
{
// Similar rules apply inside a record pattern. In this example, both the
// LHS and RHS could both promote the record's field type, and the LHS
// promotes to a subtype of the RHS. But the record's field type is
// unchanged because the join finds no common types.
var x = expr<(Object,)>();
if (x case (int _ || num _,)) {
x.expectStaticType<Exactly<(Object,)>>();
}
}
{
// Similarly, in this case the RHS promotes to a subtype of the LHS. But the
// record's field type is unchanged because the join finds no common types.
var x = expr<(Object,)>();
if (x case (num _ || int _,)) {
x.expectStaticType<Exactly<(Object,)>>();
}
}
{
// In this case the LHS and RHS promote to the same type, so the record's
// field type is promoted to that type.
var x = expr<(Object,)>();
if (x case (num _ || num _,)) {
x.expectStaticType<Exactly<(num,)>>();
}
}
{
// In this case the LHS promotes and the RHS does not, so the join finds no
// common types, and the record's field type is unchanged.
var x = expr<(num,)>();
if (x case (int _ || Object _,)) {
x.expectStaticType<Exactly<(num,)>>();
}
}
{
// In this case the RHS promotes and the LHS does not, so the join finds no
// common types, and the record's field type is unchanged.
var x = expr<(num,)>();
if (x case (Object _ || int _,)) {
x.expectStaticType<Exactly<(num,)>>();
}
}
{
// In this case the required type of the LHS is a subtype of the required
// type of the RHS, but neither type promotes, so the record's field type is
// unchanged.
var x = expr<(int,)>();
if (x case (num _ || Object _,)) {
x.expectStaticType<Exactly<(int,)>>();
}
}
{
// And in this case the required type of the RHS is a subtype of the
// required type of the LHS, but neither type promotes, so the record's
// field type is unchanged.
var x = expr<(int,)>();
if (x case (Object _ || num _,)) {
x.expectStaticType<Exactly<(int,)>>();
}
}
{
// This case demonstrates that even if a least upper bound exists between
// the required types of the LHS and RHS, the record's field type is not
// promoted to that least upper bound.
var x = expr<(Object?,)>();
if (x case (int _ || double _,)) {
x.expectStaticType<Exactly<(Object?,)>>();
}
}
}
T expr<T>() => throw UnimplementedError();
main() {}