blob: b76b06672e6d105e467846293909ed8daa0a95b5 [file] [log] [blame]
// Copyright (c) 2020, 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';
// This test checks that local boolean variables cannot be used to perform type
// promotion in the presence of compound assignments.
//
// We test the following kinds of compound assignments:
// - Ordinary (e.g. `+=`)
// - Prefix increment/decrement (e.g. `++<variable>`)
// - Postfix increment/decrement (e.g. `<variable>++`)
// - Null-aware (`??=`)
//
// We test both the side effect of the assignment and the evaluated value of the
// assignment expression.
testSideEffect(int? x) {
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
b /= x != null;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
b ~/= x != null;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
b %= x != null;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
b += x != null;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
b -= x != null;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
b <<= x != null;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
b >>= x != null;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
b &= x != null;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
b ^= x != null;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
b |= x != null;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
b ??= x != null;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
++b;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
--b;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
b++;
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
b--;
if (b) x.expectStaticType<Exactly<int?>>();
}
}
testValue(int? x) {
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (b /= x != null) {
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (b ~/= x != null) {
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (b %= x != null) {
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (b += x != null) {
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (b -= x != null) {
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (b <<= x != null) {
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (b >>= x != null) {
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (b &= x != null) {
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (b ^= x != null) {
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (b |= x != null) {
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (b ??= x != null) {
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (++b) {
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (--b) {
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (b++) {
// Note: arguably we could promote here (since the value of `b++` is the
// same as the value that `b` had before the "increment") but given that
// incrementing booleans doesn't work at runtime anyhow, it doesn't seem
// worth it.
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
{
dynamic b = x != null;
if (b) x.expectStaticType<Exactly<int>>();
if (b--) {
// Note: arguably we could promote here (since the value of `b--` is the
// same as the value that `b` had before the "decrement") but given that
// decrementing booleans doesn't work at runtime anyhow, it doesn't seem
// worth it.
x.expectStaticType<Exactly<int?>>();
}
if (b) x.expectStaticType<Exactly<int?>>();
}
}
bool _alwaysFalse() => false;
main() {
// Because of the use of dynamic in these tests, they're not expected to
// succeed at runtime; we just want to check the compile-time behavior. So we
// reference the test functions but don't call them.
if (_alwaysFalse()) testSideEffect(0);
if (_alwaysFalse()) testValue(0);
}