// Copyright (c) 2018, 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:analyzer/dart/element/type.dart';
import 'package:meta/meta.dart';

/// A representation of the operations defined for the type system.
///
/// Clients may not extend, implement or mix-in this class.
abstract class TypeSystem {
  /// Return the result of applying the function "flatten" to the given [type].
  ///
  /// For the Dart 2.0 type system, the function is defined in the Dart Language
  /// Specification, section 16.11 Function Expressions:
  ///
  /// > We define the auxiliary function _flatten(T)_, which is used below and
  /// > in other sections, as follows:
  /// >
  /// > * If _T_ is `FutureOr<`_S_`>` for some _S_ then _flatten(T)_ = _S_.
  /// >
  /// > * Otherwise if _T_ <: `Future` then let _S_ be a type such that _T_ <:
  /// >   `Future<`_S_`>` and for all _R_, if _T_ <: `Future<`_R_`>` then _S_ <:
  /// >   _R_. This ensures that `Future<`_S_`>` is the most specific generic
  /// >   instantiation of `Future` that is a supertype of _T_. Note that _S_ is
  /// >   well-defined because of the requirements on superinterfaces. Then
  /// >   _flatten(T)_ = _S_.
  /// >
  /// > * In any other circumstance, _flatten(T)_ = _T_.
  ///
  /// The subtype relationship (<:) can be tested using [isSubtypeOf].
  ///
  /// Other type systems may define this operation differently.
  DartType flatten(DartType type);

  /// Return `true` if the [leftType] is assignable to the [rightType].
  ///
  /// For the Dart 2.0 type system, the definition of this relationship is given
  /// in the Dart Language Specification, section 19.4 Subtypes:
  ///
  /// > A type _T_ may be assigned to a type _S_ in an environment &Gamma;,
  /// > written &Gamma; &#8866; _T_ &hArr; _S_, iff either &Gamma; &#8866; _S_
  /// > <: _T_ or &Gamma; &#8866; _T_ <: _S_. In this case we say that the types
  /// > _S_ and _T_ are assignable.
  ///
  /// The subtype relationship (<:) can be tested using [isSubtypeOf].
  ///
  /// Other type systems may define this operation differently. In particular,
  /// while the operation is commutative in the Dart 2.0 type system, it will
  /// not be commutative when NNBD is enabled, so the order of the arguments is
  /// important.
  bool isAssignableTo(DartType leftType, DartType rightType);

  /// Return `true` if the [type] is a non-nullable type.
  ///
  /// We say that a type `T` is non-nullable if `T <: Object`. This is
  /// equivalent to the syntactic criterion that `T` is any of:
  /// - `Object`, `int`, `bool`, `Never`, `Function`
  /// - Any function type
  /// - Any class type or generic class type
  /// - `FutureOr<S>` where `S` is non-nullable
  /// - `X extends S` where `S` is non-nullable
  /// - `X & S` where `S` is non-nullable
  ///
  /// The result of this method is undefined when the experiment 'non-nullable'
  /// is not enabled.
  @experimental
  bool isNonNullable(DartType type);

  /// Return `true` if the [type] is a nullable type.
  ///
  /// We say that a type `T` is nullable if `Null <: T`. This is equivalent to
  /// the syntactic criterion that `T` is any of:
  /// - `Null`
  /// - `S?` for some `S`
  /// - `FutureOr<S>` for some `S` where `S` is nullable
  /// - `dynamic`
  /// - `void`
  ///
  /// The result of this method is undefined when the experiment 'non-nullable'
  /// is not enabled.
  @experimental
  bool isNullable(DartType type);

  /// Return `true` if the [type] is a potentially non-nullable type.
  ///
  /// We say that a type `T` is potentially non-nullable if `T` is not nullable.
  /// Note that this is different from saying that `T` is non-nullable. For
  /// example, a type variable `X extends Object?` is a type which is
  /// potentially non-nullable but not non-nullable.
  ///
  /// The result of this method is undefined when the experiment 'non-nullable'
  /// is not enabled.
  @experimental
  bool isPotentiallyNonNullable(DartType type);

  /// Return `true` if the [type] is a potentially nullable type.
  ///
  /// We say that a type `T` is potentially nullable if `T` is not non-nullable.
  /// Note that this is different from saying that `T` is nullable. For example,
  /// a type variable `X extends Object?` is a type which is potentially
  /// nullable but not nullable.
  ///
  /// The result of this method is undefined when the experiment 'non-nullable'
  /// is not enabled.
  @experimental
  bool isPotentiallyNullable(DartType type);

  /// Return `true` if the [leftType] is a subtype of the [rightType].
  ///
  /// For the Dart 2.0 type system, the rules governing the subtype relationship
  /// are given in the Dart Language Specification, section 19.4 Subtypes.
  ///
  /// Other type systems may define this operation differently.
  bool isSubtypeOf(DartType leftType, DartType rightType);

  /// Compute the least upper bound of two types. This operation if commutative,
  /// meaning that `leastUpperBound(t, s) == leastUpperBound(s, t)` for all `t`
  /// and `s`.
  ///
  /// For the Dart 2.0 type system, the definition of the least upper bound is
  /// given in the Dart Language Specification, section 19.9.2 Least Upper
  /// Bounds.
  ///
  /// Other type systems may define this operation differently.
  DartType leastUpperBound(DartType leftType, DartType rightType);

  /// Returns a non-nullable version of [type].  This is equivalent to the
  /// operation `NonNull` defined in the spec.
  DartType promoteToNonNull(DartType type);

  /// Return the result of resolving the bounds of the given [type].
  ///
  /// For the Dart 2.0 type system, the definition of resolving to bounds is
  /// defined by the following. If the given [type] is a [TypeParameterType] and
  /// it has a bound, return the result of resolving its bound (as per this
  /// method). If the [type] is a [TypeParameterType] and it does not have a
  /// bound, return the type `Object`. For any other type, return the given
  /// type.
  ///
  /// Other type systems may define this operation differently.
  DartType resolveToBound(DartType type);
}
