blob: 79d6147360114826cb549eaed78b4a0112f02e58 [file] [log] [blame] [edit]
// Copyright (c) 2025, 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.
// Exercises flow analysis of equality comparisons (binary expressions using
// `==` or `!=`) when `sound-flow-analysis` is enabled.
import '../static_type_helper.dart';
// `<nonNullable> == <Null>` is known to evaluate to `false`.
testNonNullableEqualsNull({
required int intValue,
required int Function() intFunction,
required Null nullValue,
required Null Function() nullFunction,
}) {
{
// <var> == null
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (intValue == null) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> == <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (intValue == nullValue) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> == <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (intValue == nullFunction()) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> == null
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (intFunction() == null) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> == <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (intFunction() == nullValue) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> == <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (intFunction() == nullFunction()) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
}
// `<Null> == <nonNullable>` is known to evaluate to `false`.
testNullEqualsNonNullable({
required int intValue,
required int Function() intFunction,
required Null nullValue,
required Null Function() nullFunction,
}) {
{
// null == <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (null == intValue) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> == <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullValue == intValue) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> == <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullFunction() == intValue) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// null == <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (null == intFunction()) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> == <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullValue == intFunction()) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> == <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullFunction() == intFunction()) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
}
// `<nonNullable> != <Null>` is known to evaluate to `true`.
testNonNullableNotEqualsNull({
required int intValue,
required int Function() intFunction,
required Null nullValue,
required Null Function() nullFunction,
}) {
{
// <var> != null
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (intValue != null) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> != <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (intValue != nullValue) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> != <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (intValue != nullFunction()) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> != null
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (intFunction() != null) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> != <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (intFunction() != nullValue) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> != <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (intFunction() != nullFunction()) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
}
// `<Null> != <nonNullable>` is known to evaluate to `true`.
testNullNotEqualsNonNullable({
required int intValue,
required int Function() intFunction,
required Null nullValue,
required Null Function() nullFunction,
}) {
{
// null != <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (null != intValue) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> != <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullValue != intValue) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> != <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullFunction() != intValue) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// null != <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (null != intFunction()) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> != <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullValue != intFunction()) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> != <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullFunction() != intFunction()) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
}
// `<Null> == <Null>` is known to evaluate to `true`.
testNullEqualsNull({
required Null nullValue,
required Null Function() nullFunction,
}) {
{
// null == null
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (null == null) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// null == <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (null == nullValue) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// null == <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (null == nullFunction()) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> == null
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullValue == null) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> == <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullValue == nullValue) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> == <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullValue == nullFunction()) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> == null
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullFunction() == null) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> == <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullFunction() == nullValue) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> == <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullFunction() == nullFunction()) {
shouldBePromoted = 0; // Reachable
} else {
shouldNotBeDemoted = null; // Unreachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
}
// `<Null> != <Null>` is known to evaluate to `false`.
testNullNotEqualsNull({
required Null nullValue,
required Null Function() nullFunction,
}) {
{
// null != null
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (null != null) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// null != <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (null != nullValue) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// null != <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (null != nullFunction()) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> != null
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullValue != null) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> != <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullValue != nullValue) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <var> != <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullValue != nullFunction()) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> != null
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullFunction() != null) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> != <var>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullFunction() != nullValue) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
{
// <expr> != <expr>
int? shouldNotBeDemoted = 0;
int? shouldBePromoted;
if (nullFunction() != nullFunction()) {
shouldNotBeDemoted = null; // Unreachable
} else {
shouldBePromoted = 0; // Reachable
}
shouldNotBeDemoted.expectStaticType<Exactly<int>>();
shouldBePromoted.expectStaticType<Exactly<int>>();
}
}
main() {
testNonNullableEqualsNull(
intValue: 0,
intFunction: () => 0,
nullValue: null,
nullFunction: () => null,
);
testNullEqualsNonNullable(
intValue: 0,
intFunction: () => 0,
nullValue: null,
nullFunction: () => null,
);
testNonNullableNotEqualsNull(
intValue: 0,
intFunction: () => 0,
nullValue: null,
nullFunction: () => null,
);
testNullNotEqualsNonNullable(
intValue: 0,
intFunction: () => 0,
nullValue: null,
nullFunction: () => null,
);
testNullEqualsNull(nullValue: null, nullFunction: () => null);
testNullNotEqualsNull(nullValue: null, nullFunction: () => null);
}