blob: d54e1a002b91e71491aa949f2346bb2dfd73fd60 [file] [log] [blame]
// 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.
/// @assertion Two objects T1 and T2 which are instances of Type (that is,
/// runtime type objects) are considered equal if and only if the runtime type
/// objects T1 and T2 corresponds to the types S1 and S2 respectively, and the
/// normal forms NORM(S1) and NORM(S2) are syntactically equal up to equivalence
/// of bound variables and ignoring * modifiers on types.
/// ...
/// Two constant type literals T1 and T2 compare as identical if they are equal
/// using the definition of runtime type equality specified above.
///
/// @description Checks that two constant type literals `T1` and `T2` are
/// identical if they are equal according to the runtime type equality.
/// @author sgrekhov22@gmail.com
import "dart:async";
import "../../Utils/expect.dart";
typedef NullableInt = int?;
typedef DoubleNullableInt = NullableInt?;
typedef NullableNever = Never?;
typedef NullableNull = Null?;
typedef NullableDynamic = dynamic?;
typedef Void = void;
typedef NullableVoid = Void?;
typedef NullableObject = Object?;
typedef DoubleNullableObject = NullableObject?;
typedef NullableFutureNull = Future<Null>?;
typedef NullableFutureOrNullableInt = FutureOr<int?>?;
typedef F1 = Never? Function<X extends FutureOr<Object?>>(DoubleNullableInt);
typedef F1_NORM = Null Function<X extends Object?>(int?);
typedef F2 = Null? Function<X extends FutureOr<Null>>([NullableDynamic]);
typedef F2_NORM = Null Function<X extends NullableFutureNull>([dynamic]);
typedef F3 = NullableVoid Function<X extends FutureOr<Object>>(
{FutureOr<Never> v});
typedef F3_NORM = void Function<X extends Object>({Future<Never> v});
typedef RecordPositionalVoid = (void,);
typedef RecordPositionalNullableVoid = (NullableVoid,);
typedef RecordNamedNullableInt = ({NullableInt n});
typedef RecordNamedDoubleNullableInt = ({DoubleNullableInt n});
typedef RecordDynamicNull = (dynamic, {Null n});
typedef RecordNullableDynamicNullableNever = (
NullableDynamic, {
NullableNever n
});
main() {
// NORM(FutureOr<T>) == S, if NORM(T) == S and S is a top type
Expect.identical(Void, FutureOr<void>);
// NORM(FutureOr<T>) == S, if NORM(T) == S and S is a top type
Expect.identical(dynamic, FutureOr<dynamic>);
// NORM(FutureOr<T>) == S, if NORM(T) == S and S is a top type
Expect.identical(NullableObject, FutureOr<Object?>);
// NORM(FutureOr<T>) == Object, if NORM(T) == Object
Expect.identical(Object, FutureOr<Object>);
// NORM(FutureOr<T>) == Future<Never>, if NORM(T) == Never
Expect.identical(Future<Never>, FutureOr<Never>);
// NORM(FutureOr<T>) == Future<Null>?, if NORM(T) == Null
Expect.identical(NullableFutureNull, FutureOr<Null>);
// NORM(FutureOr<T>) == FutureOr<S>, where NORM(T) == S (all other cases)
Expect.identical(FutureOr<int?>, FutureOr<DoubleNullableInt>);
// NORM(T?) == S, if NORM(T) == S and S is a top type
Expect.identical(dynamic, NullableDynamic);
// NORM(T?) == S, if NORM(T) == S and S is a top type
Expect.identical(Void, NullableVoid);
// NORM(T?) == S, if NORM(T) == S and S is a top type
Expect.identical(NullableObject, DoubleNullableObject);
// NORM(T?) == Null, if NORM(T) == Never
Expect.identical(Null, NullableNever);
// NORM(T?) == Null, if NORM(T) == Null
Expect.identical(Null, NullableNull);
// NORM(T?) == FutureOr<R>, if NORM(T) == FutureOr<R> and R is nullable
Expect.identical(FutureOr<int?>, NullableFutureOrNullableInt);
// NORM(T?) == R?, if NORM(T) == R?
Expect.identical(NullableInt, DoubleNullableInt);
// NORM(T?) == S?, if NORM(T) == S (all other cases)
Expect.identical(NullableInt, NullableInt);
// NORM(C<T0, ..., Tn>) = C<R0, ..., Rn> where Ri is NORM(Ti)
Expect.identical(Map<void, dynamic>, Map<FutureOr<void>, FutureOr<dynamic>>);
Expect.identical(
Map<Object?, Object>, Map<FutureOr<Object?>, FutureOr<Object>>);
Expect.identical(
Map<Future<Never>, Future<Null>?>, Map<FutureOr<Never>, FutureOr<Null>>);
Expect.identical(Map<FutureOr<int?>, dynamic>,
Map<FutureOr<DoubleNullableInt>, NullableDynamic>);
Expect.identical(Map<void, Object?>, Map<NullableVoid, DoubleNullableObject>);
Expect.identical(Map<Null, Null>, Map<NullableNever, NullableNull>);
Expect.identical(
Map<FutureOr<int?>, int?>, Map<FutureOr<int?>?, DoubleNullableInt>);
Expect.identical(Map<F1_NORM, F2_NORM>, Map<F1, F2>);
Expect.identical(Map<F3_NORM, RecordPositionalVoid>,
Map<F3, RecordPositionalNullableVoid>);
Expect.identical(Map<RecordNamedNullableInt, RecordDynamicNull>,
Map<RecordNamedDoubleNullableInt, RecordNullableDynamicNullableNever>);
// NORM(R Function<X extends B>(S)) = R1 Function<X extends B1>(S1)
// where R1 = NORM(R)
// and B1 = NORM(B)
// and S1 = NORM(S)
Expect.identical(F1_NORM, F1);
Expect.identical(F2_NORM, F2);
Expect.identical(F3_NORM, F3);
// NORM((S0, ..., Sn, {T0 d0, ..., Tm dm})) =
// (S0', ..., Sn', {T0' d0, ..., Tm' dm})
// where Si' = NORM(Si)
// and Ti' = NORM(Ti)
Expect.identical(RecordPositionalVoid, RecordPositionalNullableVoid);
Expect.identical(RecordNamedNullableInt, RecordNamedDoubleNullableInt);
Expect.identical(RecordDynamicNull, RecordNullableDynamicNullableNever);
}