blob: 78750c49a8b8d3c93950483c160722feaf3ecac1 [file] [edit]
// Copyright (c) 2026, 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.
// SharedOptions=--enable-experiment=promotion-chain-intersection-join
// Tests the behavior of the enhanced promotion chain join algorithm
// (https://github.com/dart-lang/language/issues/4757) when enabled.
import 'package:expect/static_type_helper.dart';
class A {}
class B implements A {}
class C implements A {}
class D implements B, C {
void dMethod() {}
}
void testIfElseAs(bool condition, bool condition2, Object o) {
if (condition) {
o as A;
if (condition2) {
o as B;
o as D;
} else {
o as C;
o as D;
}
// When promotion-chain-intersection-join is enabled, o retains promotion to
// D across the join.
o.expectStaticType<Exactly<D>>();
o.dMethod();
// To verify that `A` is still in the promotion chain, join with a control
// flow path that promotes only to `A`, and verify that the promotion to `A`
// is preserved:
} else {
o as A;
}
o.expectStaticType<Exactly<A>>();
}
void testIfElseIs(bool condition, bool condition2, Object o) {
if (condition) {
o as A;
if (condition2) {
if (o is! B || o is! D) return;
} else {
if (o is! C || o is! D) return;
}
o.expectStaticType<Exactly<D>>();
o.dMethod();
// To verify that `A` is still in the promotion chain, join with a control
// flow path that promotes only to `A`, and verify that the promotion to `A`
// is preserved:
} else {
o as A;
}
o.expectStaticType<Exactly<A>>();
}
void testConditional(bool condition, bool condition2, Object o) {
if (condition) {
o as A;
condition2 ? (o as B, o as D) : (o as C, o as D);
o.expectStaticType<Exactly<D>>();
o.dMethod();
// To verify that `A` is still in the promotion chain, join with a control
// flow path that promotes only to `A`, and verify that the promotion to `A`
// is preserved:
} else {
o as A;
}
o.expectStaticType<Exactly<A>>();
}
void testSwitch(int x, bool condition2, Object o) {
if (condition2) {
o as A;
switch (x) {
case 1:
o as B;
o as D;
default:
o as C;
o as D;
}
o.expectStaticType<Exactly<D>>();
o.dMethod();
// To verify that `A` is still in the promotion chain, join with a control
// flow path that promotes only to `A`, and verify that the promotion to `A`
// is preserved:
} else {
o as A;
}
o.expectStaticType<Exactly<A>>();
}
void main() {
for (var condition in [true, false]) {
for (var condition2 in [true, false]) {
testIfElseAs(condition, condition2, D());
testIfElseIs(condition, condition2, D());
testConditional(condition, condition2, D());
testSwitch(condition ? 1 : 2, condition2, D());
}
}
}