blob: ced63a568f97c301c8bb787453826c824f227ab2 [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.
/// This test verifies that `is` and `==` tests performed on a property get of
/// `this` do not lead to code being considered unreachable. (In principle, we
/// could soundly mark some such code as unreachable, but we have decided not to
/// do so at this time).
///
/// Exception: when the static type of the property access is guaranteed to be
/// Null, and we are performing an `== null` test, then we do mark the non-null
/// branch as unreachable.
import '../../static_type_helper.dart';
class B {
Null get nullProperty => null;
Object? get objectQProperty => null;
}
class C extends B {
void equalitySimple_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (nullProperty == null) {
x = null;
} else {
y = null;
}
// Since the assignment to x was reachable, it should have static type
// `int?` now. But y should still have static type `int`.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int>>();
}
void equalitySimple_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this.nullProperty == null) {
x = null;
} else {
y = null;
}
// Since the assignment to x was reachable, it should have static type
// `int?` now. But y should still have static type `int`.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int>>();
}
void equalityWithBogusPromotion_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (objectQProperty is Null) {
if (objectQProperty == null) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void equalityWithBogusPromotion_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this.objectQProperty is Null) {
if (this.objectQProperty == null) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isSimple_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (nullProperty is Never) {
x = null;
} else {
y = null;
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isSimple_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this.nullProperty is Never) {
x = null;
} else {
y = null;
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isWithBogusPromotion_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (objectQProperty is Null) {
if (objectQProperty is Never) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isWithBogusPromotion_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this.objectQProperty is Null) {
if (this.objectQProperty is Never) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
}
class D extends B {}
extension on D {
void equalitySimple_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (nullProperty == null) {
x = null;
} else {
y = null;
}
// Since the assignment to x was reachable, it should have static type
// `int?` now. But y should still have static type `int`.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int>>();
}
void equalitySimple_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this.nullProperty == null) {
x = null;
} else {
y = null;
}
// Since the assignment to x was reachable, it should have static type
// `int?` now. But y should still have static type `int`.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int>>();
}
void equalityWithBogusPromotion_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (objectQProperty is Null) {
if (objectQProperty == null) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void equalityWithBogusPromotion_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this.objectQProperty is Null) {
if (this.objectQProperty == null) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isSimple_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (nullProperty is Never) {
x = null;
} else {
y = null;
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isSimple_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this.nullProperty is Never) {
x = null;
} else {
y = null;
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isWithBogusPromotion_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (objectQProperty is Null) {
if (objectQProperty is Never) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isWithBogusPromotion_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this.objectQProperty is Null) {
if (this.objectQProperty is Never) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
}
class _B {
final Null _nullField = null;
final Object? _objectQField = null;
}
class _C extends _B {
void equalitySimple_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (_nullField == null) {
x = null;
} else {
y = null;
}
// Since the assignment to x was reachable, it should have static type
// `int?` now. But y should still have static type `int`.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int>>();
}
void equalitySimple_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this._nullField == null) {
x = null;
} else {
y = null;
}
// Since the assignment to x was reachable, it should have static type
// `int?` now. But y should still have static type `int`.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int>>();
}
void equalityWithBogusPromotion_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (_objectQField is Null) {
if (_objectQField == null) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void equalityWithBogusPromotion_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this._objectQField is Null) {
if (this._objectQField == null) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isSimple_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (_nullField is Never) {
x = null;
} else {
y = null;
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isSimple_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this._nullField is Never) {
x = null;
} else {
y = null;
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isWithBogusPromotion_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (_objectQField is Null) {
if (_objectQField is Never) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isWithBogusPromotion_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this._objectQField is Null) {
if (this._objectQField is Never) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
}
class _D extends _B {}
extension on _D {
void equalitySimple_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (_nullField == null) {
x = null;
} else {
y = null;
}
// Since the assignment to x was reachable, it should have static type
// `int?` now. But y should still have static type `int`.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int>>();
}
void equalitySimple_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this._nullField == null) {
x = null;
} else {
y = null;
}
// Since the assignment to x was reachable, it should have static type
// `int?` now. But y should still have static type `int`.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int>>();
}
void equalityWithBogusPromotion_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (_objectQField is Null) {
if (_objectQField == null) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void equalityWithBogusPromotion_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this._objectQField is Null) {
if (this._objectQField == null) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isSimple_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (_nullField is Never) {
x = null;
} else {
y = null;
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isSimple_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this._nullField is Never) {
x = null;
} else {
y = null;
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isWithBogusPromotion_implicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (_objectQField is Null) {
if (_objectQField is Never) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
void isWithBogusPromotion_explicitThis(int? x, int? y) {
if (x == null || y == null) return;
x.expectStaticType<Exactly<int>>();
y.expectStaticType<Exactly<int>>();
if (this._objectQField is Null) {
if (this._objectQField is Never) {
x = null;
} else {
y = null;
}
}
// Since the assignments to x and y were both reachable, they should have
// static type `int?` now.
x.expectStaticType<Exactly<int?>>();
y.expectStaticType<Exactly<int?>>();
}
}
main() {
C().equalitySimple_implicitThis(1, 1);
C().equalitySimple_explicitThis(1, 1);
C().equalityWithBogusPromotion_implicitThis(1, 1);
C().equalityWithBogusPromotion_explicitThis(1, 1);
C().isSimple_implicitThis(1, 1);
C().isSimple_explicitThis(1, 1);
C().isWithBogusPromotion_implicitThis(1, 1);
C().isWithBogusPromotion_explicitThis(1, 1);
D().equalitySimple_implicitThis(1, 1);
D().equalitySimple_explicitThis(1, 1);
D().equalityWithBogusPromotion_implicitThis(1, 1);
D().equalityWithBogusPromotion_explicitThis(1, 1);
D().isSimple_implicitThis(1, 1);
D().isSimple_explicitThis(1, 1);
D().isWithBogusPromotion_implicitThis(1, 1);
D().isWithBogusPromotion_explicitThis(1, 1);
_C().equalitySimple_implicitThis(1, 1);
_C().equalitySimple_explicitThis(1, 1);
_C().equalityWithBogusPromotion_implicitThis(1, 1);
_C().equalityWithBogusPromotion_explicitThis(1, 1);
_C().isSimple_implicitThis(1, 1);
_C().isSimple_explicitThis(1, 1);
_C().isWithBogusPromotion_implicitThis(1, 1);
_C().isWithBogusPromotion_explicitThis(1, 1);
_D().equalitySimple_implicitThis(1, 1);
_D().equalitySimple_explicitThis(1, 1);
_D().equalityWithBogusPromotion_implicitThis(1, 1);
_D().equalityWithBogusPromotion_explicitThis(1, 1);
_D().isSimple_implicitThis(1, 1);
_D().isSimple_explicitThis(1, 1);
_D().isWithBogusPromotion_implicitThis(1, 1);
_D().isWithBogusPromotion_explicitThis(1, 1);
}