blob: 14acd637f2b320f92047c3585f62cd2cdf271114 [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.
/// Helper to create [Type] values.
Type typeOf<T>() => T;
/// Ensures a context type of [T] for the operand.
Object? context<T>(T x) => x;
/// Captures the context type of the call and returns the same type.
///
/// Can be used to check the context type as:
/// ```dart
/// int x = contextType(1 /* valid value */)..expectStaticType<Exactly<int>>;
/// ```
T contextType<T>(Object result) => result as T;
extension StaticType<T> on T {
/// Check the static type.
///
/// Use as follows (assuming `e` has static type `num`):
/// ```dart
/// e.expectStaticType<Exactly<num>>() // No context type.
/// e.expectStaticType<SubtypeOf<Object>>() // No context type.
/// e.expectStaticType<SupertypeOf<int>>() // No context type.
/// ```
/// or
/// ```dart
/// e..expectStaticType<Exactly<num>>() // Preserve context type.
/// e..expectStaticType<SubtypeOf<Object>>() // Preserve context type.
/// e..expectStaticType<SupertypeOf<int>>() // Preserve context type.
/// ```
/// This will be a *compile-time error* if the static type is not
/// as required by the constraints type (the one passed to [Exactly],
/// [SubtypeOf] or [SupertypeOf].)
T expectStaticType<R extends Exactly<T>>() {
return this;
}
/// Invokes [callback] with the static type of `this`.
///
/// Allows any operation on the type.
T captureStaticType(void Function<X>() callback) {
callback<T>();
return this;
}
}
/// Invokes [callback] with the static type of [value].
///
/// Similar to [StaticType.captureStaticType], but works
/// for types like `void` and `dynamic` which do not allow
/// extension methods.
void captureStaticType<T>(T value, void Function<X>(X value) callback) {
callback<T>(value);
}
/// Use with [StaticType.expectStaticType] to expect precisely the type [T].
///
/// Example use:
/// ```dart
/// "abc".expectStaticType<Exactly<String>>();
/// ```
typedef Exactly<T> = T Function(T);
/// Use with [StaticType.expectStaticType] to expect a subtype of [T].
///
/// Example use:
/// ```dart
/// num x = 1;
/// x.expectStaticType<SubtypeOf<Object>>();
/// ```
typedef SubtypeOf<T> = Never Function(T);
/// Use with [StaticType.expectStaticType] to expect a supertype of [T].
///
/// Example use:
/// ```dart
/// num x = 1;
/// x.expectStaticType<SupertypeOf<int>>();
/// ```
typedef SupertypeOf<T> = T Function(Object?);
/// Checks that an expression is assignable to [T1], [T2] and [Object].
///
/// This ensures that the static type of the expression is either dynamic,
/// Never, or a type assignable to both [T1] and [T2], and if those are
/// unrelated, it must be an intersection type.
void checkIntersectionType<T1, T2>(T1 v1, T2 v2, Object v3) {}