|  | // 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"; | 
|  | import "package:expect/variations.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) { | 
|  | !unsoundNullSafety | 
|  | ? 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)); | 
|  | } |