mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:59:47 +00:00
dd2fb672fd
In DDC the types [num], [int], [double], [String], and [bool] used in bounds caused an "optimization" in type tests that was incorrect when passing a subtype as the type argument. Issue: https://github.com/dart-lang/sdk/issues/52243 Change-Id: I0ae8d21c907cd923d62dbae257085545840a8cdf Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/301140 Reviewed-by: Bob Nystrom <rnystrom@google.com>
220 lines
11 KiB
Dart
220 lines
11 KiB
Dart
// 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 "package:expect/expect.dart";
|
|
|
|
/// Regression test for the issue discovered by
|
|
/// https://github.com/dart-lang/sdk/issues/52243.
|
|
///
|
|
/// In DDC the types [num], [int], [double], [String], and [bool] used in bounds
|
|
/// caused an "optimization" in type tests that was incorrect when passing a
|
|
/// subtype as the type argument.
|
|
|
|
bool isWithNumBound<T extends num>(x) => x is T;
|
|
T asWithNumBound<T extends num>(x) => x as T;
|
|
bool isWithNullableNumBound<T extends num?>(x) => x is T;
|
|
T asWithNullableNumBound<T extends num?>(x) => x as T;
|
|
bool isWithIntBound<T extends int>(x) => x is T;
|
|
T asWithIntBound<T extends int>(x) => x as T;
|
|
bool isWithNullableIntBound<T extends int?>(x) => x is T;
|
|
T asWithNullableIntBound<T extends int?>(x) => x as T;
|
|
bool isWithDoubleBound<T extends double>(x) => x is T;
|
|
T asWithDoubleBound<T extends double>(x) => x as T;
|
|
bool isWithNullableDoubleBound<T extends double?>(x) => x is T;
|
|
T asWithNullableDoubleBound<T extends double?>(x) => x as T;
|
|
bool isWithStringBound<T extends String>(x) => x is T;
|
|
T asWithStringBound<T extends String>(x) => x as T;
|
|
bool isWithNullableStringBound<T extends String?>(x) => x is T;
|
|
T asWithNullableStringBound<T extends String?>(x) => x as T;
|
|
bool isWithBoolBound<T extends bool>(x) => x is T;
|
|
T asWithBoolBound<T extends bool>(x) => x as T;
|
|
bool isWithNullableBoolBound<T extends bool?>(x) => x is T;
|
|
T asWithNullableBoolBound<T extends bool?>(x) => x as T;
|
|
|
|
expectTypeErrorWhenSoundOrValue<T>(T Function(T) computation, T value) {
|
|
hasSoundNullSafety
|
|
? Expect.throws<TypeError>(() => computation(value))
|
|
: Expect.equals(value, computation(value));
|
|
}
|
|
|
|
main() {
|
|
// NOTE: JavaScript platforms can't determine that 1 is not a double so any
|
|
// test combination that would exercise that pattern are excluded here.
|
|
Expect.isTrue(isWithNumBound<num>(1));
|
|
Expect.isTrue(isWithNumBound<int>(1));
|
|
Expect.isFalse(isWithNumBound<Never>(1));
|
|
Expect.isTrue(isWithNumBound<num>(1.2));
|
|
Expect.isFalse(isWithNumBound<int>(1.2));
|
|
Expect.isTrue(isWithNumBound<double>(1.2));
|
|
Expect.isFalse(isWithNumBound<Never>(1.2));
|
|
|
|
Expect.equals(1, asWithNumBound<num>(1));
|
|
Expect.equals(1, asWithNumBound<int>(1));
|
|
Expect.throws<TypeError>(() => asWithNumBound<Never>(1));
|
|
Expect.equals(1.2, asWithNumBound<num>(1.2));
|
|
Expect.throws<TypeError>(() => asWithNumBound<int>(1.2));
|
|
Expect.equals(1.2, asWithNumBound<double>(1.2));
|
|
Expect.throws<TypeError>(() => asWithNumBound<Never>(1.2));
|
|
|
|
Expect.isTrue(isWithNullableNumBound<num>(1));
|
|
Expect.isTrue(isWithNullableNumBound<int>(1));
|
|
Expect.isFalse(isWithNullableNumBound<Never>(1));
|
|
Expect.isTrue(isWithNullableNumBound<num?>(1));
|
|
Expect.isTrue(isWithNullableNumBound<int?>(1));
|
|
Expect.isFalse(isWithNullableNumBound<Null>(1));
|
|
Expect.isTrue(isWithNullableNumBound<num>(1.2));
|
|
Expect.isFalse(isWithNullableNumBound<int>(1.2));
|
|
Expect.isTrue(isWithNullableNumBound<double>(1.2));
|
|
Expect.isFalse(isWithNullableNumBound<Never>(1.2));
|
|
Expect.isTrue(isWithNullableNumBound<num?>(1.2));
|
|
Expect.isFalse(isWithNullableNumBound<int?>(1.2));
|
|
Expect.isTrue(isWithNullableNumBound<double?>(1.2));
|
|
Expect.isFalse(isWithNullableNumBound<Null>(1.2));
|
|
Expect.isFalse(isWithNullableNumBound<num>(null));
|
|
Expect.isFalse(isWithNullableNumBound<int>(null));
|
|
Expect.isFalse(isWithNullableNumBound<double>(null));
|
|
Expect.isFalse(isWithNullableNumBound<Never>(null));
|
|
Expect.isTrue(isWithNullableNumBound<num?>(null));
|
|
Expect.isTrue(isWithNullableNumBound<int?>(null));
|
|
Expect.isTrue(isWithNullableNumBound<double?>(null));
|
|
Expect.isTrue(isWithNullableNumBound<Null>(null));
|
|
|
|
Expect.equals(1, asWithNullableNumBound<num>(1));
|
|
Expect.equals(1, asWithNullableNumBound<int>(1));
|
|
Expect.throws<TypeError>(() => asWithNullableNumBound<Never>(1));
|
|
Expect.equals(1, asWithNullableNumBound<num?>(1));
|
|
Expect.equals(1, asWithNullableNumBound<int?>(1));
|
|
Expect.throws<TypeError>(() => asWithNullableNumBound<Null>(1));
|
|
Expect.equals(1.2, asWithNullableNumBound<num>(1.2));
|
|
Expect.throws<TypeError>(() => asWithNullableNumBound<int>(1.2));
|
|
Expect.equals(1.2, asWithNullableNumBound<double>(1.2));
|
|
Expect.throws<TypeError>(() => asWithNullableNumBound<Never>(1.2));
|
|
Expect.equals(1.2, asWithNullableNumBound<num?>(1.2));
|
|
Expect.throws<TypeError>(() => asWithNullableNumBound<int?>(1.2));
|
|
Expect.equals(1.2, asWithNullableNumBound<double?>(1.2));
|
|
Expect.throws<TypeError>(() => asWithNullableNumBound<Null>(1.2));
|
|
expectTypeErrorWhenSoundOrValue(asWithNullableNumBound<num>, null);
|
|
expectTypeErrorWhenSoundOrValue(asWithNullableNumBound<int>, null);
|
|
expectTypeErrorWhenSoundOrValue(asWithNullableNumBound<double>, null);
|
|
expectTypeErrorWhenSoundOrValue(asWithNullableNumBound<Never>, null);
|
|
Expect.equals(null, asWithNullableNumBound<num?>(null));
|
|
Expect.equals(null, asWithNullableNumBound<int?>(null));
|
|
Expect.equals(null, asWithNullableNumBound<double?>(null));
|
|
Expect.equals(null, asWithNullableNumBound<Null>(null));
|
|
|
|
Expect.isTrue(isWithIntBound<int>(1));
|
|
Expect.isFalse(isWithIntBound<Never>(1));
|
|
Expect.isFalse(isWithIntBound<int>(1.2));
|
|
Expect.isFalse(isWithIntBound<Never>(1.2));
|
|
|
|
Expect.equals(1, asWithIntBound<int>(1));
|
|
Expect.throws<TypeError>(() => asWithIntBound<Never>(1));
|
|
Expect.throws<TypeError>(() => asWithIntBound<int>(1.2));
|
|
Expect.throws<TypeError>(() => asWithIntBound<Never>(1.2));
|
|
|
|
Expect.isTrue(isWithNullableIntBound<int>(1));
|
|
Expect.isFalse(isWithNullableIntBound<Never>(1));
|
|
Expect.isTrue(isWithNullableIntBound<int?>(1));
|
|
Expect.isFalse(isWithNullableIntBound<Null>(1));
|
|
Expect.isFalse(isWithNullableIntBound<int>(1.2));
|
|
Expect.isFalse(isWithNullableIntBound<Never>(1.2));
|
|
Expect.isFalse(isWithNullableIntBound<int?>(1.2));
|
|
Expect.isFalse(isWithNullableIntBound<Null>(1.2));
|
|
Expect.isFalse(isWithNullableIntBound<int>(null));
|
|
Expect.isFalse(isWithNullableIntBound<Never>(null));
|
|
Expect.isTrue(isWithNullableIntBound<int?>(null));
|
|
Expect.isTrue(isWithNullableIntBound<Null>(null));
|
|
|
|
Expect.equals(1, asWithNullableIntBound<int>(1));
|
|
Expect.throws<TypeError>(() => asWithNullableIntBound<Never>(1));
|
|
Expect.equals(1, asWithNullableIntBound<int?>(1));
|
|
Expect.throws<TypeError>(() => asWithNullableIntBound<Null>(1));
|
|
Expect.throws<TypeError>(() => asWithNullableIntBound<int>(1.2));
|
|
Expect.throws<TypeError>(() => asWithNullableIntBound<Never>(1.2));
|
|
Expect.throws<TypeError>(() => asWithNullableIntBound<int?>(1.2));
|
|
Expect.throws<TypeError>(() => asWithNullableIntBound<Null>(1.2));
|
|
expectTypeErrorWhenSoundOrValue(asWithNullableIntBound<int>, null);
|
|
expectTypeErrorWhenSoundOrValue(asWithNullableIntBound<Never>, null);
|
|
Expect.equals(null, asWithNullableIntBound<int?>(null));
|
|
Expect.equals(null, asWithNullableIntBound<Null>(null));
|
|
|
|
Expect.isFalse(isWithDoubleBound<Never>(1));
|
|
Expect.isTrue(isWithDoubleBound<double>(1.2));
|
|
Expect.isFalse(isWithDoubleBound<Never>(1.2));
|
|
|
|
Expect.throws<TypeError>(() => asWithDoubleBound<Never>(1));
|
|
Expect.equals(1.2, asWithDoubleBound<double>(1.2));
|
|
Expect.throws<TypeError>(() => asWithDoubleBound<Never>(1.2));
|
|
|
|
Expect.isFalse(isWithNullableDoubleBound<Never>(1));
|
|
Expect.isFalse(isWithNullableDoubleBound<Null>(1));
|
|
Expect.isTrue(isWithNullableDoubleBound<double>(1.2));
|
|
Expect.isFalse(isWithNullableDoubleBound<Never>(1.2));
|
|
Expect.isTrue(isWithNullableDoubleBound<double?>(1.2));
|
|
Expect.isFalse(isWithNullableDoubleBound<Null>(1.2));
|
|
Expect.isFalse(isWithNullableDoubleBound<double>(null));
|
|
Expect.isFalse(isWithNullableDoubleBound<Never>(null));
|
|
Expect.isTrue(isWithNullableDoubleBound<double?>(null));
|
|
Expect.isTrue(isWithNullableDoubleBound<Null>(null));
|
|
|
|
Expect.throws<TypeError>(() => asWithNullableDoubleBound<Never>(1));
|
|
Expect.throws<TypeError>(() => asWithNullableDoubleBound<Null>(1));
|
|
Expect.equals(1.2, asWithNullableDoubleBound<double>(1.2));
|
|
Expect.throws<TypeError>(() => asWithNullableDoubleBound<Never>(1.2));
|
|
Expect.equals(1.2, asWithNullableDoubleBound<double?>(1.2));
|
|
Expect.throws<TypeError>(() => asWithNullableDoubleBound<Null>(1.2));
|
|
expectTypeErrorWhenSoundOrValue(asWithNullableDoubleBound<double>, null);
|
|
expectTypeErrorWhenSoundOrValue(asWithNullableDoubleBound<Never>, null);
|
|
Expect.equals(null, asWithNullableDoubleBound<double?>(null));
|
|
Expect.equals(null, asWithNullableDoubleBound<Null>(null));
|
|
|
|
Expect.isTrue(isWithStringBound<String>('hello'));
|
|
Expect.isFalse(isWithStringBound<Never>('hello'));
|
|
|
|
Expect.equals('hello', asWithStringBound<String>('hello'));
|
|
Expect.throws<TypeError>(() => asWithStringBound<Never>('hello'));
|
|
|
|
Expect.isTrue(isWithNullableStringBound<String>('hello'));
|
|
Expect.isFalse(isWithNullableStringBound<Never>('hello'));
|
|
Expect.isTrue(isWithNullableStringBound<String?>('hello'));
|
|
Expect.isFalse(isWithNullableStringBound<Null>('hello'));
|
|
Expect.isFalse(isWithNullableStringBound<String>(null));
|
|
Expect.isFalse(isWithNullableStringBound<Never>(null));
|
|
Expect.isTrue(isWithNullableStringBound<String?>(null));
|
|
Expect.isTrue(isWithNullableStringBound<Null>(null));
|
|
|
|
Expect.equals('hello', asWithNullableStringBound<String>('hello'));
|
|
Expect.throws<TypeError>(() => asWithNullableStringBound<Never>('hello'));
|
|
Expect.equals('hello', asWithNullableStringBound<String?>('hello'));
|
|
Expect.throws<TypeError>(() => asWithNullableStringBound<Null>('hello'));
|
|
expectTypeErrorWhenSoundOrValue(asWithNullableStringBound<String>, null);
|
|
expectTypeErrorWhenSoundOrValue(asWithNullableStringBound<Never>, null);
|
|
Expect.equals(null, asWithNullableStringBound<String?>(null));
|
|
Expect.equals(null, asWithNullableStringBound<Null>(null));
|
|
|
|
Expect.isTrue(isWithBoolBound<bool>(true));
|
|
Expect.isFalse(isWithBoolBound<Never>(true));
|
|
|
|
Expect.equals(true, asWithBoolBound<bool>(true));
|
|
Expect.throws<TypeError>(() => asWithBoolBound<Never>(true));
|
|
|
|
Expect.isTrue(isWithNullableBoolBound<bool>(true));
|
|
Expect.isFalse(isWithNullableBoolBound<Never>(true));
|
|
Expect.isTrue(isWithNullableBoolBound<bool?>(true));
|
|
Expect.isFalse(isWithNullableBoolBound<Null>(true));
|
|
Expect.isFalse(isWithNullableBoolBound<bool>(null));
|
|
Expect.isFalse(isWithNullableBoolBound<Never>(null));
|
|
Expect.isTrue(isWithNullableBoolBound<bool?>(null));
|
|
Expect.isTrue(isWithNullableBoolBound<Null>(null));
|
|
|
|
Expect.equals(true, asWithNullableBoolBound<bool>(true));
|
|
Expect.throws<TypeError>(() => asWithNullableBoolBound<Never>(true));
|
|
Expect.equals(true, asWithNullableBoolBound<bool?>(true));
|
|
Expect.throws<TypeError>(() => asWithNullableBoolBound<Null>(true));
|
|
expectTypeErrorWhenSoundOrValue(asWithNullableBoolBound<bool>, null);
|
|
expectTypeErrorWhenSoundOrValue(asWithNullableBoolBound<Never>, null);
|
|
Expect.equals(null, asWithNullableBoolBound<bool?>(null));
|
|
Expect.equals(null, asWithNullableBoolBound<Null>(null));
|
|
}
|