//===--- Types.h - Swift Language Type ASTs ---------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the TypeBase class and subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_TYPES_H
#define SWIFT_TYPES_H

// SWIFT_ENABLE_TENSORFLOW
#include "swift/AST/AutoDiff.h"
#include "swift/AST/Attr.h"
#include "swift/AST/DeclContext.h"
#include "swift/AST/GenericParamKey.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/Ownership.h"
#include "swift/AST/ProtocolConformanceRef.h"
#include "swift/AST/Requirement.h"
#include "swift/AST/SILLayout.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/AST/Type.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/Basic/ArrayRefView.h"
#include "swift/Basic/InlineBitfield.h"
#include "swift/Basic/UUID.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerEmbeddedInt.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TrailingObjects.h"

namespace llvm {
struct fltSemantics;
} // namespace llvm

namespace swift {

enum class AllocationArena;
class ArchetypeType;
class AssociatedTypeDecl;
class ASTContext;
class ClassDecl;
class DependentMemberType;
class GenericTypeParamDecl;
class GenericTypeParamType;
class GenericParamList;
class GenericSignature;
class GenericSignatureBuilder;
class Identifier;
class InOutType;
class OpaqueTypeDecl;
class OpenedArchetypeType;
enum class ReferenceCounting : uint8_t;
enum class ResilienceExpansion : unsigned;
class SILModule;
class SILType;
class TypeAliasDecl;
class TypeDecl;
class NominalTypeDecl;
class GenericTypeDecl;
class EnumDecl;
class EnumElementDecl;
class StructDecl;
class ProtocolDecl;
class TypeVariableType;
class ValueDecl;
class ModuleDecl;
class ModuleType;
class ProtocolConformance;
enum PointerTypeKind : unsigned;
struct ValueOwnershipKind;
// SWIFT_ENABLE_TENSORFLOW
struct SILAutoDiffConfig;

namespace Lowering {
class TypeConverter;
} // namespace Lowering
// SWIFT_ENABLE_TENSORFLOW END

enum class TypeKind : uint8_t {
#define TYPE(id, parent) id,
#define LAST_TYPE(id) Last_Type = id,
#define TYPE_RANGE(Id, FirstId, LastId) \
  First_##Id##Type = FirstId, Last_##Id##Type = LastId,
#include "swift/AST/TypeNodes.def"
};

enum : unsigned {
  NumTypeKindBits = countBitsUsed(static_cast<unsigned>(TypeKind::Last_Type))
};

enum class BuiltinTypeKind : std::underlying_type<TypeKind>::type;

/// Various properties of types that are primarily defined recursively
/// on structural types.
class RecursiveTypeProperties {
public:
  /// A single property.
  ///
  /// Note that the property polarities should be chosen so that 0 is
  /// the correct default value and bitwise-or correctly merges things.
  enum Property : unsigned {
    /// This type expression contains a TypeVariableType.
    HasTypeVariable      = 0x01,

    /// This type expression contains a context-dependent archetype, either a
    /// PrimaryArchetypeType or OpenedArchetypeType.
    HasArchetype         = 0x02,

    /// This type expression contains a GenericTypeParamType.
    HasTypeParameter     = 0x04,

    /// This type expression contains an UnresolvedType.
    HasUnresolvedType    = 0x08,
    
    /// Whether this type expression contains an unbound generic type.
    HasUnboundGeneric    = 0x10,

    /// This type expression contains an LValueType other than as a
    /// function input, and can be loaded to convert to an rvalue.
    IsLValue             = 0x20,

    /// This type expression contains an opened existential ArchetypeType.
    HasOpenedExistential = 0x40,

    /// This type expression contains a DynamicSelf type.
    HasDynamicSelf       = 0x80,

    /// This type contains an Error type.
    HasError             = 0x100,

    /// This type contains a DependentMemberType.
    HasDependentMember   = 0x200,
    
    /// This type contains an OpaqueTypeArchetype.
    HasOpaqueArchetype   = 0x400,

    Last_Property = HasOpaqueArchetype
  };
  enum { BitWidth = countBitsUsed(Property::Last_Property) };

private:
  unsigned Bits;

public:
  RecursiveTypeProperties() : Bits(0) {}
  RecursiveTypeProperties(Property prop) : Bits(prop) {}
  explicit RecursiveTypeProperties(unsigned bits) : Bits(bits) {}

  /// Return these properties as a bitfield.
  unsigned getBits() const { return Bits; }

  /// Does a type with these properties structurally contain a type
  /// variable?
  bool hasTypeVariable() const { return Bits & HasTypeVariable; }

  /// Does a type with these properties structurally contain a
  /// context-dependent archetype (that is, a Primary- or OpenedArchetype)?
  bool hasArchetype() const { return Bits & HasArchetype; }

  /// Does a type with these properties structurally contain an
  /// archetype from an opaque type declaration?
  bool hasOpaqueArchetype() const { return Bits & HasOpaqueArchetype; }
  
  /// Does a type with these properties have a type parameter somewhere in it?
  bool hasTypeParameter() const { return Bits & HasTypeParameter; }

  /// Does a type with these properties have an unresolved type somewhere in it?
  bool hasUnresolvedType() const { return Bits & HasUnresolvedType; }
  
  /// Is a type with these properties an lvalue?
  bool isLValue() const { return Bits & IsLValue; }

  /// Does this type contain an error?
  bool hasError() const { return Bits & HasError; }

  /// Does this type contain a dependent member type, possibly with a
  /// non-type parameter base, such as a type variable or concrete type?
  bool hasDependentMember() const { return Bits & HasDependentMember; }

  /// Does a type with these properties structurally contain an
  /// archetype?
  bool hasOpenedExistential() const { return Bits & HasOpenedExistential; }

  /// Does a type with these properties structurally contain a
  /// reference to DynamicSelf?
  bool hasDynamicSelf() const { return Bits & HasDynamicSelf; }

  /// Does a type with these properties structurally contain an unbound
  /// generic type?
  bool hasUnboundGeneric() const { return Bits & HasUnboundGeneric; }

  /// Returns the set of properties present in either set.
  friend RecursiveTypeProperties operator|(Property lhs, Property rhs) {
    return RecursiveTypeProperties(unsigned(lhs) | unsigned(rhs));
  }
  friend RecursiveTypeProperties operator|(RecursiveTypeProperties lhs,
                                           RecursiveTypeProperties rhs) {
    return RecursiveTypeProperties(lhs.Bits | rhs.Bits);
  }

  /// Add any properties in the right-hand set to this set.
  RecursiveTypeProperties &operator|=(RecursiveTypeProperties other) {
    Bits |= other.Bits;
    return *this;
  }
  /// Restrict this to only the properties in the right-hand set.
  RecursiveTypeProperties &operator&=(RecursiveTypeProperties other) {
    Bits &= other.Bits;
    return *this;
  }

  /// Remove the HasTypeParameter property from this set.
  void removeHasTypeParameter() {
    Bits &= ~HasTypeParameter;
  }

  /// Remove the HasDependentMember property from this set.
  void removeHasDependentMember() {
    Bits &= ~HasDependentMember;
  }

  /// Test for a particular property in this set.
  bool operator&(Property prop) const {
    return Bits & prop;
  }
};

inline RecursiveTypeProperties operator~(RecursiveTypeProperties::Property P) {
  return RecursiveTypeProperties(~unsigned(P));
}
  
/// The result of a type trait check.
enum class TypeTraitResult {
  /// The type cannot have the trait.
  IsNot,
  /// The generic type can be bound to a type that has the trait.
  CanBe,
  /// The type has the trait irrespective of generic substitutions.
  Is,
};

/// Specifies which normally-unsafe type mismatches should be accepted when
/// checking overrides.
enum class TypeMatchFlags {
  /// Allow properly-covariant overrides.
  AllowOverride = 1 << 0,
  /// Allow a parameter with IUO type to be overridden by a parameter with non-
  /// optional type.
  AllowNonOptionalForIUOParam = 1 << 1,
  /// Allow any mismatches of Optional or ImplicitlyUnwrappedOptional at the
  /// top level of a type.
  ///
  /// This includes function parameters and result types as well as tuple
  /// elements, but excludes generic parameters.
  AllowTopLevelOptionalMismatch = 1 << 2,
  /// Allow any ABI-compatible types to be considered matching.
  AllowABICompatible = 1 << 3,
  /// Allow escaping function parameters to override optional non-escaping ones.
  ///
  /// This is necessary because Objective-C allows optional function paramaters
  /// to be non-escaping, but Swift currently does not.
  IgnoreNonEscapingForOptionalFunctionParam = 1 << 4,
  /// Allow compatible opaque archetypes.
  AllowCompatibleOpaqueTypeArchetypes = 1 << 5
};
using TypeMatchOptions = OptionSet<TypeMatchFlags>;

/// TypeBase - Base class for all types in Swift.
class alignas(1 << TypeAlignInBits) TypeBase {
  
  friend class ASTContext;
  TypeBase(const TypeBase&) = delete;
  void operator=(const TypeBase&) = delete;
  
  /// This union contains the ASTContext for canonical types, and is
  /// otherwise lazily populated by ASTContext when the canonical form of a
  /// non-canonical type is requested. The disposition of the union is stored
  /// outside of the union for performance. See Bits.TypeBase.IsCanonical.
  union {
    CanType CanonicalType;
    const ASTContext *Context;
  };

  /// Returns true if the given type is a sugared type.
  ///
  /// Only intended for use in compile-time assertions.
  // Specializations of this are at the end of the file.
  template <typename T>
  static constexpr bool isSugaredType() {
    return false;
  }

protected:
  // SWIFT_ENABLE_TENSORFLOW
  enum { NumAFTExtInfoBits = 8 };
  enum { NumSILExtInfoBits = 8 };
  union { uint64_t OpaqueBits;

  SWIFT_INLINE_BITFIELD_BASE(TypeBase, bitmax(NumTypeKindBits,8) +
                             RecursiveTypeProperties::BitWidth + 1,
    /// Kind - The discriminator that indicates what subclass of type this is.
    Kind : bitmax(NumTypeKindBits,8),

    Properties : RecursiveTypeProperties::BitWidth,

    /// Whether this type is canonical or not.
    IsCanonical : 1
  );

  SWIFT_INLINE_BITFIELD(ErrorType, TypeBase, 1,
    /// Whether there is an original type.
    HasOriginalType : 1
  );

  SWIFT_INLINE_BITFIELD(SugarType, TypeBase, 1,
    HasCachedType : 1
  );

  enum { NumFlagBits = 8 };
  SWIFT_INLINE_BITFIELD(ParenType, SugarType, NumFlagBits,
    /// Whether there is an original type.
    Flags : NumFlagBits
  );

  SWIFT_INLINE_BITFIELD_FULL(AnyFunctionType, TypeBase, NumAFTExtInfoBits+16,
    /// Extra information which affects how the function is called, like
    /// regparm and the calling convention.
    ExtInfo : NumAFTExtInfoBits,

    : NumPadBits,
    NumParams : 16
  );

  SWIFT_INLINE_BITFIELD_FULL(ArchetypeType, TypeBase, 1+1+1+16,
    ExpandedNestedTypes : 1,
    HasSuperclass : 1,
    HasLayoutConstraint : 1,
    : NumPadBits,
    NumProtocols : 16
  );

  SWIFT_INLINE_BITFIELD_FULL(TypeVariableType, TypeBase, 4+32,
    : NumPadBits,

    /// Type variable options.
    Options : 4,

    /// The unique number assigned to this type variable.
    ID : 32
  );

  SWIFT_INLINE_BITFIELD(SILFunctionType, TypeBase, NumSILExtInfoBits+3+1+2,
    ExtInfo : NumSILExtInfoBits,
    CalleeConvention : 3,
    HasErrorResult : 1,
    CoroutineKind : 2
  );

  SWIFT_INLINE_BITFIELD(AnyMetatypeType, TypeBase, 2,
    /// The representation of the metatype.
    ///
    /// Zero indicates that no representation has been set; otherwise,
    /// the value is the representation + 1
    Representation : 2
  );

  SWIFT_INLINE_BITFIELD_FULL(ProtocolCompositionType, TypeBase, 1+32,
    /// Whether we have an explicitly-stated class constraint not
    /// implied by any of our members.
    HasExplicitAnyObject : 1,

    : NumPadBits,

    /// The number of protocols being composed.
    Count : 32
  );

  SWIFT_INLINE_BITFIELD_FULL(TupleType, TypeBase, 1+32,
    /// Whether an element of the tuple is inout, __shared or __owned.
    /// Values cannot have such tuple types in the language.
    HasElementWithOwnership : 1,

    : NumPadBits,

    /// The number of elements of the tuple.
    Count : 32
  );

  SWIFT_INLINE_BITFIELD_FULL(BoundGenericType, TypeBase, 32,
    : NumPadBits,

    /// The number of generic arguments.
    GenericArgCount : 32
  );

  SWIFT_INLINE_BITFIELD_FULL(TypeAliasType, SugarType, 1+1,
    : NumPadBits,

    /// Whether we have a parent type.
    HasParent : 1,

    /// Whether we have a substitution map.
    HasSubstitutionMap : 1
  );

  } Bits;

protected:
  TypeBase(TypeKind kind, const ASTContext *CanTypeCtx,
           RecursiveTypeProperties properties)
    : Context(nullptr) {
    Bits.OpaqueBits = 0;
    Bits.TypeBase.Kind = static_cast<unsigned>(kind);
    Bits.TypeBase.IsCanonical = false;
    // If this type is canonical, switch the CanonicalType union to ASTContext.
    if (CanTypeCtx) {
      Bits.TypeBase.IsCanonical = true;
      Context = CanTypeCtx;
    }
    setRecursiveProperties(properties);
  }

  void setRecursiveProperties(RecursiveTypeProperties properties) {
    Bits.TypeBase.Properties = properties.getBits();
    assert(Bits.TypeBase.Properties == properties.getBits() && "Bits dropped!");
  }

public:
  /// getKind - Return what kind of type this is.
  TypeKind getKind() const { return static_cast<TypeKind>(Bits.TypeBase.Kind); }

  /// isCanonical - Return true if this is a canonical type.
  bool isCanonical() const { return Bits.TypeBase.IsCanonical; }
  
  /// hasCanonicalTypeComputed - Return true if we've already computed a
  /// canonical version of this type.
  bool hasCanonicalTypeComputed() const { return !CanonicalType.isNull(); }

private:
  CanType computeCanonicalType();

public:
  /// getCanonicalType - Return the canonical version of this type, which has
  /// sugar from all levels stripped off.
  CanType getCanonicalType() const {
    if (isCanonical())
      return CanType(const_cast<TypeBase*>(this));
    if (hasCanonicalTypeComputed())
      return CanonicalType;
    return const_cast<TypeBase*>(this)->computeCanonicalType();
  }

  /// getCanonicalType - Stronger canonicalization which folds away equivalent
  /// associated types, or type parameters that have been made concrete.
  CanType getCanonicalType(GenericSignature sig);

  /// Reconstitute type sugar, e.g., for array types, dictionary
  /// types, optionals, etc.
  TypeBase *reconstituteSugar(bool Recursive);

  // If this type is a syntax sugar type, desugar it. Also desugar any nested
  // syntax sugar types.
  TypeBase *getWithoutSyntaxSugar();

  /// getASTContext - Return the ASTContext that this type belongs to.
  ASTContext &getASTContext() {
    // If this type is canonical, it has the ASTContext in it.
    if (isCanonical())
      return *const_cast<ASTContext*>(Context);
    // If not, canonicalize it to get the Context.
    return *const_cast<ASTContext*>(getCanonicalType()->Context);
  }
  
  /// isEqual - Return true if these two types are equal, ignoring sugar.
  ///
  /// To compare sugar, check for pointer equality of the underlying TypeBase *
  /// values, obtained by calling getPointer().
  bool isEqual(Type Other);
  
  /// getDesugaredType - If this type is a sugared type, remove all levels of
  /// sugar until we get down to a non-sugar type.
  TypeBase *getDesugaredType();
  
  /// If this type is a (potentially sugared) type of the specified kind, remove
  /// the minimal amount of sugar required to get a pointer to the type.
  template <typename T>
  T *getAs() {
    static_assert(!isSugaredType<T>(), "getAs desugars types");
    auto Ty = getDesugaredType();
    SWIFT_ASSUME(Ty != nullptr);
    return dyn_cast<T>(Ty);
  }

  template <typename T>
  bool is() {
    static_assert(!isSugaredType<T>(), "isa desugars types");
    return isa<T>(getDesugaredType());
  }
  
  template <typename T>
  T *castTo() {
    static_assert(!isSugaredType<T>(), "castTo desugars types");
    return cast<T>(getDesugaredType());
  }

  /// getRecursiveProperties - Returns the properties defined on the
  /// structure of this type.
  RecursiveTypeProperties getRecursiveProperties() const {
    return RecursiveTypeProperties(Bits.TypeBase.Properties);
  }

  /// hasReferenceSemantics() - Do objects of this type have reference
  /// semantics?
  bool hasReferenceSemantics();

  /// Is this a nominally uninhabited type, such as 'Never'?
  bool isUninhabited();

  /// Is this an uninhabited type, such as 'Never' or '(Never, Int)'?
  bool isStructurallyUninhabited();
  
  /// Is this the 'Any' type?
  bool isAny();

  /// Does the type have outer parenthesis?
  bool hasParenSugar() const { return getKind() == TypeKind::Paren; }

  /// Are values of this type essentially just class references,
  /// possibly with some sort of additional information?
  ///
  ///   - any of the builtin reference types
  ///   - a class type
  ///   - a bound generic class type
  ///   - a class-bounded archetype type
  ///   - a class-bounded existential type
  ///   - a dynamic Self type
  bool isAnyClassReferenceType();
  
  /// allowsOwnership() - Are variables of this type permitted to have
  /// ownership attributes?
  bool allowsOwnership(GenericSignatureImpl *sig = nullptr);

  /// Determine whether this type involves a type variable.
  bool hasTypeVariable() const {
    return getRecursiveProperties().hasTypeVariable();
  }

  /// Determine where this type is a type variable or a dependent
  /// member root in a type variable.
  bool isTypeVariableOrMember();

  /// Determine whether this type involves a UnresolvedType.
  bool hasUnresolvedType() const {
    return getRecursiveProperties().hasUnresolvedType();
  }
  
  /// Determine whether the type involves a context-dependent archetype.
  bool hasArchetype() const {
    return getRecursiveProperties().hasArchetype();
  }
  
  /// Determine whether the type involves an opened existential archetype.
  bool hasOpenedExistential() const {
    return getRecursiveProperties().hasOpenedExistential();
  }

  /// Determine whether the type involves the given opened existential
  /// archetype.
  bool hasOpenedExistential(OpenedArchetypeType *opened);

  /// Determine whether the type involves an opaque type.
  bool hasOpaqueArchetype() const {
    return getRecursiveProperties().hasOpaqueArchetype();
  }
  
  /// Determine whether the type is an opened existential type.
  ///
  /// To determine whether there is an opened existential type
  /// anywhere in the type, use \c hasOpenedExistential.
  bool isOpenedExistential() const;

  /// Determine whether the type is an opened existential type with Error inside
  bool isOpenedExistentialWithError();

  /// Retrieve the set of opened existential archetypes that occur
  /// within this type.
  void getOpenedExistentials(SmallVectorImpl<OpenedArchetypeType *> &opened);

  /// Erase the given opened existential type by replacing it with its
  /// existential type throughout the given type.
  Type eraseOpenedExistential(OpenedArchetypeType *opened);

  /// Given a declaration context, returns a function type with the 'self'
  /// type curried as the input if the declaration context describes a type.
  /// Otherwise, returns the type itself.
  Type addCurriedSelfType(const DeclContext *dc);

  /// Map a contextual type to an interface type.
  Type mapTypeOutOfContext();

  /// Compute and return the set of type variables that occur within this
  /// type.
  ///
  /// \param typeVariables This vector is populated with the set of
  /// type variables referenced by this type.
  void getTypeVariables(SmallVectorImpl<TypeVariableType *> &typeVariables);

  /// Determine whether this type is a type parameter, which is either a
  /// GenericTypeParamType or a DependentMemberType.
  ///
  /// Note that this routine will return \c false for types that include type
  /// parameters in nested positions, e.g, \c T is a type parameter but
  /// \c X<T> is not a type parameter. Use \c hasTypeParameter to determine
  /// whether a type parameter exists at any position.
  bool isTypeParameter();

  /// Determine whether this type can dynamically be an optional type.
  ///
  /// \param includeExistential Whether an existential type should be considered
  /// such a type.
  bool canDynamicallyBeOptionalType(bool includeExistential);

  /// Determine whether this type contains a type parameter somewhere in it.
  bool hasTypeParameter() {
    return getRecursiveProperties().hasTypeParameter();
  }

  /// Find any unresolved dependent member type within this type.
  ///
  /// "Unresolved" dependent member types have no known associated type,
  /// and are only used transiently in the type checker.
  const DependentMemberType *findUnresolvedDependentMemberType();

  /// Return the root generic parameter of this type parameter type.
  GenericTypeParamType *getRootGenericParam();

  /// Determines whether this type is an lvalue. This includes both straight
  /// lvalue types as well as tuples or optionals of lvalues.
  bool hasLValueType() {
    return getRecursiveProperties().isLValue();
  }
  
  /// Is this a first-class value type, meaning it is not an InOutType or a
  /// tuple type containing an InOutType?
  bool isMaterializable();

  /// Is this a non-escaping type, that is, a non-escaping function type or a
  /// tuple type containing a non-escaping type?
  bool isNoEscape() const;

  /// Determine whether the type is dependent on DynamicSelf.
  bool hasDynamicSelfType() const {
    return getRecursiveProperties().hasDynamicSelf();
  }

  /// Determine whether the type contains an unbound generic type.
  bool hasUnboundGenericType() const {
    return getRecursiveProperties().hasUnboundGeneric();
  }

  /// Determine whether this type contains an error type.
  bool hasError() const {
    return getRecursiveProperties().hasError();
  }

  /// Does this type contain a dependent member type, possibly with a
  /// non-type parameter base, such as a type variable or concrete type?
  bool hasDependentMember() const {
    return getRecursiveProperties().hasDependentMember();
  }

  /// isExistentialType - Determines whether this type is an existential type,
  /// whose real (runtime) type is unknown but which is known to conform to
  /// some set of protocols. Protocol and protocol-conformance types are
  /// existential types.
  bool isExistentialType();

  /// isAnyExistentialType - Determines whether this type is any kind of
  /// existential type: a protocol type, a protocol composition type, or
  /// an existential metatype.
  bool isAnyExistentialType();

  /// isObjCExistentialType - Determines whether this type is an
  /// class-bounded existential type whose required conformances are
  /// all @objc.  Such types are compatible with ObjC.
  bool isObjCExistentialType();
  
  /// Determines whether this type is an existential type with a class protocol
  /// bound.
  bool isClassExistentialType();

  /// Opens an existential instance or meta-type and returns the opened type.
  Type openAnyExistentialType(OpenedArchetypeType *&opened);

  /// Break an existential down into a set of constraints.
  ExistentialLayout getExistentialLayout();

  /// Determines the element type of a known
  /// [Autoreleasing]Unsafe[Mutable][Raw]Pointer variant, or returns null if the
  /// type is not a pointer.
  Type getAnyPointerElementType(PointerTypeKind &PTK);
  Type getAnyPointerElementType() {
    PointerTypeKind Ignore;
    return getAnyPointerElementType(Ignore);
  }

  /// Returns a type representing a pointer to \c this.
  ///
  /// \p kind must not be a raw pointer kind, since that would discard the
  /// current type.
  Type wrapInPointer(PointerTypeKind kind);
  
  /// Determine whether the given type is "specialized", meaning that
  /// it involves generic types for which generic arguments have been provided.
  /// For example, the types Vector<Int> and Vector<Int>.Element are both
  /// specialized, but the type Vector is not.
  bool isSpecialized();

  /// Determine whether this type is a legal, lowered SIL type.
  ///
  /// A type is SIL-illegal if it is:
  ///   - an l-value type,
  ///   - a metatype without a representation,
  ///   - an AST function type (i.e. subclasses of AnyFunctionType),
  ///   - an optional whose object type is SIL-illegal, or
  ///   - a tuple type with a SIL-illegal element type.
  bool isLegalSILType();

  /// Determine whether this type is a legal formal type.
  ///
  /// A type is illegal as a formal type if it is:
  ///   - an l-value type,
  ///   - a reference storage type,
  ///   - a metatype with a representation,
  ///   - a lowered function type (i.e. SILFunctionType),
  ///   - an optional whose object type is not a formal type, or
  ///   - a tuple type with an element that is not a formal type.
  ///
  /// These are the types of the Swift type system.
  bool isLegalFormalType();

  /// Check if this type is equal to the empty tuple type.
  bool isVoid();

  /// Check if this type is equal to Swift.Bool.
  bool isBool();

  /// Check if this type is equal to Builtin.IntN.
  bool isBuiltinIntegerType(unsigned bitWidth);

  /// If this is a class type or a bound generic class type, returns the
  /// (possibly generic) class.
  ClassDecl *getClassOrBoundGenericClass();
  
  /// If this is a struct type or a bound generic struct type, returns
  /// the (possibly generic) class.
  StructDecl *getStructOrBoundGenericStruct();
  
  /// If this is an enum or a bound generic enum type, returns the
  /// (possibly generic) enum.
  EnumDecl *getEnumOrBoundGenericEnum();
  
  /// Determine whether this type may have a superclass, which holds for
  /// classes, bound generic classes, and archetypes that are only instantiable
  /// with a class type.
  bool mayHaveSuperclass();

  /// Determine whether this type satisfies a class layout constraint, written
  /// `T: AnyObject` in the source.
  ///
  /// A class layout constraint is satisfied when we have a single retainable
  /// pointer as the representation, which includes:
  /// - @objc existentials
  /// - class constrained archetypes
  /// - classes
  bool satisfiesClassConstraint();

  /// Determine whether this type can be used as a base type for AST
  /// name lookup, which is the case for nominal types, protocol compositions
  /// and archetypes.
  ///
  /// Generally, the static vs instance and mutating vs nonmutating distinction
  /// is handled elsewhere, so metatypes, lvalue types and inout types are not
  /// allowed here.
  ///
  /// Similarly, tuples formally have members, but this does not go through
  /// name lookup.
  bool mayHaveMembers() {
    return (is<ArchetypeType>() ||
            is<ModuleType>() ||
            isExistentialType() ||
            getAnyNominal());
  }

  /// Retrieve the superclass of this type.
  ///
  /// \param useArchetypes Whether to use context archetypes for outer generic
  /// parameters if the class is nested inside a generic function.
  ///
  /// \returns The superclass of this type, or a null type if it has no
  ///          superclass.
  Type getSuperclass(bool useArchetypes = true);
  
  /// True if this type is the exact superclass of another type.
  ///
  /// \param ty       The potential subclass.
  ///
  /// \returns True if this type is \c ty or a superclass of \c ty.
  ///
  /// If this type is a bound generic class \c Foo<T>, the method only
  /// returns true if the generic parameters of \c ty exactly match the
  /// superclass of \c ty. For instance, if \c ty is a
  /// class DerivedClass: Base<Int>, then \c Base<T> (where T is an archetype)
  /// will return false. `isBindableToSuperclassOf` should be used
  /// for queries that care whether a generic class type can be substituted into
  /// a type's subclass.
  bool isExactSuperclassOf(Type ty);

  /// Get the substituted base class type, starting from a base class
  /// declaration and a substituted derived class type.
  ///
  /// For example, given the following declarations:
  ///
  /// class A<T, U> {}
  /// class B<V> : A<Int, V> {}
  /// class C<X, Y> : B<Y> {}
  ///
  /// Calling `C<String, NSObject>`->getSuperclassForDecl(`A`) will return
  /// `A<Int, NSObject>`.
  ///
  /// \param useArchetypes Whether to use context archetypes for outer generic
  /// parameters if the class is nested inside a generic function.
  Type getSuperclassForDecl(const ClassDecl *classDecl,
                            bool useArchetypes = true);

  /// True if this type is the superclass of another type, or a generic
  /// type that could be bound to the superclass.
  ///
  /// \param ty       The potential subclass.
  ///
  /// \returns True if this type is \c ty, a superclass of \c ty, or an
  ///          archetype-parameterized type that can be bound to a superclass
  ///          of \c ty.
  bool isBindableToSuperclassOf(Type ty);

  /// True if this type contains archetypes that could be substituted with
  /// concrete types to form the argument type.
  bool isBindableTo(Type ty);

  /// Determines whether this type is similar to \p other as defined by
  /// \p matchOptions.
  bool matches(Type other, TypeMatchOptions matchOptions);

  bool matchesParameter(Type other, TypeMatchOptions matchMode);

  /// Determines whether this function type is similar to \p
  /// other as defined by \p matchOptions and the callback \p
  /// paramsAndResultMatch which determines in a client-specific way
  /// whether the parameters and result of the types match.
  bool matchesFunctionType(Type other, TypeMatchOptions matchOptions,
                           llvm::function_ref<bool()> paramsAndResultMatch);

  /// Determines whether this type has a retainable pointer
  /// representation, i.e. whether it is representable as a single,
  /// possibly nil pointer that can be unknown-retained and
  /// unknown-released.
  bool hasRetainablePointerRepresentation();

  /// Given that this type is a reference type, which kind of reference
  /// counting does it use?
  ReferenceCounting getReferenceCounting();

  /// Determines whether this type has a bridgeable object
  /// representation, i.e., whether it is always represented as a single
  /// (non-nil) pointer that can be unknown-retained and
  /// unknown-released.
  ///
  /// This predicate covers all types that can be placed into an
  /// AnyObject without ever requiring a representation change. Note that this
  /// excludes ObjC class metatypes, which may need to be wrapped or unwrapped
  /// when converting from native representation to AnyObject representation.
  bool isBridgeableObjectType();

  /// Determine whether this type is a potentially-bridged value type.
  ///
  /// This predicate doesn't guarantee that the type is bridged, but rather is
  /// a quick way to check whether the type is a value type that could
  /// conceivably be bridged to an Objective-C class type.
  bool isPotentiallyBridgedValueType();

  /// If this is a nominal type or a bound generic nominal type,
  /// returns the (possibly generic) nominal type declaration.
  NominalTypeDecl *getNominalOrBoundGenericNominal();

  /// If this is a nominal type, bound generic nominal type, or
  /// unbound generic nominal type, return the (possibly generic) nominal type
  /// declaration.
  NominalTypeDecl *getAnyNominal();

  /// Determine whether the given type is representable in the given
  /// foreign language.
  std::pair<ForeignRepresentableKind, ProtocolConformance *>
  getForeignRepresentableIn(ForeignLanguage language, const DeclContext *dc);

  /// Determines whether the given Swift type is representable within
  /// the given foreign language.
  ///
  /// A given Swift type is representable in the given foreign
  /// language if the Swift type can be used from source code written
  /// in that language.
  bool isRepresentableIn(ForeignLanguage language, const DeclContext *dc);

  /// Determines whether the type is trivially representable within
  /// the foreign language, meaning that it is both representable in
  /// that language and that the runtime representations are
  /// equivalent.
  bool isTriviallyRepresentableIn(ForeignLanguage language,
                                  const DeclContext *dc);

  /// Given that this is a nominal type or bound generic nominal
  /// type, return its parent type; this will be a null type if the type
  /// is not a nested type.
  Type getNominalParent();

  /// If this is a GenericType, bound generic nominal type, or
  /// unbound generic nominal type, return the (possibly generic) nominal type
  /// declaration.
  GenericTypeDecl *getAnyGeneric();

  /// removeArgumentLabels -  Retrieve a version of this type with all
  /// argument labels removed.
  Type removeArgumentLabels(unsigned numArgumentLabels);

  /// Retrieve the type without any parentheses around it.
  Type getWithoutParens();

  /// Replace the base type of the result type of the given function
  /// type with a new result type, as per a DynamicSelf or other
  /// covariant return transformation.  The optionality of the
  /// existing result will be preserved.
  ///
  /// \param newResultType The new result type.
  ///
  /// \param uncurryLevel The number of uncurry levels to apply before
  /// replacing the type. With uncurry level == 0, this simply
  /// replaces the current type with the new result type.
  Type replaceCovariantResultType(Type newResultType,
                                  unsigned uncurryLevel);

  /// Returns a new function type exactly like this one but with the self
  /// parameter replaced. Only makes sense for function members of types.
  Type replaceSelfParameterType(Type newSelf);

  /// getRValueType - For an @lvalue type, retrieves the underlying object type.
  /// Otherwise, returns the type itself.
  Type getRValueType();

  /// getInOutObjectType - For an inout type, retrieves the underlying object
  /// type.  Otherwise, returns the type itself.
  Type getInOutObjectType();

  /// getWithoutSpecifierType - For a non-materializable type
  /// e.g. @lvalue or inout, retrieves the underlying object type.
  /// Otherwise, returns the type itself.
  Type getWithoutSpecifierType();

  /// getMetatypeInstanceType - Looks through metatypes.
  Type getMetatypeInstanceType();

  /// For a ReferenceStorageType like @unowned, this returns the referent.
  /// Otherwise, it returns the type itself.
  Type getReferenceStorageReferent();

  /// Determine the set of substitutions that should be applied to a
  /// type spelled within the given DeclContext to treat it as a
  /// member of this type.
  ///
  /// For example, given:
  /// \code
  /// struct X<T, U> { }
  /// extension X {
  ///   typealias SomeArray = [T]
  /// }
  /// \endcode
  ///
  /// Asking for the member substitutions of \c X<Int,String> within
  /// the context of the extension above will produce substitutions T
  /// -> Int and U -> String suitable for mapping the type of
  /// \c SomeArray.
  ///
  /// \param genericEnv If non-null and the type is nested inside of a
  /// generic function, generic parameters of the outer context are
  /// mapped to context archetypes of this generic environment.
  SubstitutionMap getContextSubstitutionMap(ModuleDecl *module,
                                            const DeclContext *dc,
                                            GenericEnvironment *genericEnv=nullptr);

  /// Deprecated version of the above.
  TypeSubstitutionMap getContextSubstitutions(const DeclContext *dc,
                                              GenericEnvironment *genericEnv=nullptr);

  /// Get the substitutions to apply to the type of the given member as seen
  /// from this base type.
  ///
  /// \param genericEnv If non-null, generic parameters of the member are
  /// mapped to context archetypes of this generic environment.
  SubstitutionMap getMemberSubstitutionMap(ModuleDecl *module,
                                           const ValueDecl *member,
                                           GenericEnvironment *genericEnv=nullptr);

  /// Deprecated version of the above.
  TypeSubstitutionMap getMemberSubstitutions(const ValueDecl *member,
                                             GenericEnvironment *genericEnv=nullptr);

  /// Retrieve the type of the given member as seen through the given base
  /// type, substituting generic arguments where necessary.
  ///
  /// This routine allows one to take a concrete type (the "this" type) and
  /// and a member of that type (or one of its superclasses), then determine
  /// what type an access to that member through the base type will have.
  /// For example, given:
  ///
  /// \code
  /// class Vector<T> {
  ///   func add(value : T) { }
  /// }
  /// \endcode
  ///
  /// Given the type \c Vector<Int> and the member \c add, the resulting type
  /// of the member will be \c (self : Vector<Int>) -> (value : Int) -> ().
  ///
  /// \param module The module in which the substitution occurs.
  ///
  /// \param member The member whose type we are substituting.
  ///
  /// \param memberType The type of the member, in which archetypes will be
  /// replaced by the generic arguments provided by the base type. If null,
  /// the member's type will be used.
  ///
  /// \returns the resulting member type.
  Type getTypeOfMember(ModuleDecl *module, const ValueDecl *member,
                       Type memberType = Type());

  /// Get the type of a superclass member as seen from the subclass,
  /// substituting generic parameters, dynamic Self return, and the
  /// 'self' argument type as appropriate.
  Type adjustSuperclassMemberDeclType(const ValueDecl *baseDecl,
                                      const ValueDecl *derivedDecl,
                                      Type memberType);

  /// Return T if this type is Optional<T>; otherwise, return the null type.
  Type getOptionalObjectType();

  // Return type underlying type of a swift_newtype annotated imported struct;
  // otherwise, return the null type.
  Type getSwiftNewtypeUnderlyingType();

  /// Return the type T after looking through all of the optional
  /// types.
  Type lookThroughAllOptionalTypes();

  /// Return the type T after looking through all of the optional
  /// types.
  Type lookThroughAllOptionalTypes(SmallVectorImpl<Type> &optionals);

  /// Whether this is the AnyObject type.
  bool isAnyObject();

  /// Whether this is an existential composition containing
  /// Error.
  bool isExistentialWithError();

  void dump() const LLVM_ATTRIBUTE_USED;
  void dump(raw_ostream &os, unsigned indent = 0) const;

  void dumpPrint() const LLVM_ATTRIBUTE_USED;
  void print(raw_ostream &OS,
             const PrintOptions &PO = PrintOptions()) const;
  void print(ASTPrinter &Printer, const PrintOptions &PO) const;

  /// Can this type be written in source at all?
  ///
  /// If not, it shouldn't be shown in fix-its, for instance. The primary
  /// example is opaque result types, which are written `some P` at the point
  /// of definition but cannot be uttered anywhere else.
  bool hasTypeRepr() const;

  /// Does this type have grammatically simple syntax?
  bool hasSimpleTypeRepr() const;

  /// Return the name of the type as a string, for use in diagnostics only.
  std::string getString(const PrintOptions &PO = PrintOptions()) const;

  /// Return the name of the type, adding parens in cases where
  /// appending or prepending text to the result would cause that text
  /// to be appended to only a portion of the returned type. For
  /// example for a function type "Int -> Float", adding text after
  /// the type would make it appear that it's appended to "Float" as
  /// opposed to the entire type.
  std::string
  getStringAsComponent(const PrintOptions &PO = PrintOptions()) const;

  /// Return whether this type is or can be substituted for a bridgeable
  /// object type.
  TypeTraitResult canBeClass();

  // SWIFT_ENABLE_TENSORFLOW
  /// Return the associated tangent type. Return the null type if there is no
  /// associated tangent type.
  ///
  /// If the type conforms to `Differentiable`, then the associated
  /// tangent type is the associated `TangentVector` from the `Differentiable`
  /// requirement. If the type is a tuple, then the associated tangent type is
  /// the elementwise tangent type of its elements. If the type is a builtin
  /// float, then the associated tangent type is itself. Otherwise, there is no
  /// associated type.
  Optional<VectorSpace>
  getAutoDiffAssociatedTangentSpace(LookupConformanceFn lookupConformance);

private:
  // Make vanilla new/delete illegal for Types.
  void *operator new(size_t Bytes) throw() = delete;
  void operator delete(void *Data) throw() = delete;
public:
  // Only allow allocation of Types using the allocator in ASTContext
  // or by doing a placement new.
  void *operator new(size_t bytes, const ASTContext &ctx,
                     AllocationArena arena, unsigned alignment = 8);
  void *operator new(size_t Bytes, void *Mem) throw() { return Mem; }
};

/// AnyGenericType - This abstract class helps types ensure that fields
/// exist at the same offset in memory to improve code generation of the
/// compiler itself.
class AnyGenericType : public TypeBase {
  friend class NominalOrBoundGenericNominalType;

  /// TheDecl - This is the TypeDecl which declares the given type. It
  /// specifies the name and other useful information about this type.
  union {
    GenericTypeDecl *GenDecl;
    NominalTypeDecl *NomDecl;
  };

  /// The type of the parent, in which this type is nested.
  Type Parent;

  template <typename... Args>
  AnyGenericType(NominalTypeDecl *TheDecl, Type Parent, Args &&...args)
    : TypeBase(std::forward<Args>(args)...), NomDecl(TheDecl), Parent(Parent) {}

protected:
  template <typename... Args>
  AnyGenericType(GenericTypeDecl *TheDecl, Type Parent, Args &&...args)
    : TypeBase(std::forward<Args>(args)...), GenDecl(TheDecl), Parent(Parent) {}

public:

  /// Returns the declaration that declares this type.
  GenericTypeDecl *getDecl() const { return GenDecl; }

  /// Returns the type of the parent of this type. This will
  /// be null for top-level types or local types, and for non-generic types
  /// will simply be the same as the declared type of the declaration context
  /// of TheDecl. For types nested within generic types, however, this will
  /// involve \c BoundGenericType nodes that provide context for the nested
  /// type, e.g., the type Dictionary<String, Int>.ItemRange would be
  /// represented as a NominalType with Dictionary<String, Int> as its parent
  /// type.
  Type getParent() const { return Parent; }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() >= TypeKind::First_AnyGenericType &&
           T->getKind() <= TypeKind::Last_AnyGenericType;
  }
};
BEGIN_CAN_TYPE_WRAPPER(AnyGenericType, Type)
  PROXY_CAN_TYPE_SIMPLE_GETTER(getParent)
END_CAN_TYPE_WRAPPER(AnyGenericType, Type)

/// NominalOrBoundGenericNominal - This abstract class helps types ensure that
/// fields exist at the same offset in memory to improve code generation of the
/// compiler itself.
class NominalOrBoundGenericNominalType : public AnyGenericType {
public:
  template <typename... Args>
  NominalOrBoundGenericNominalType(Args &&...args)
    : AnyGenericType(std::forward<Args>(args)...) {}

  /// Returns the declaration that declares this type.
  NominalTypeDecl *getDecl() const { return NomDecl; }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() >= TypeKind::First_NominalOrBoundGenericNominalType &&
           T->getKind() <= TypeKind::Last_NominalOrBoundGenericNominalType;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(NominalOrBoundGenericNominalType, AnyGenericType)

/// ErrorType - This represents a type that was erroneously constructed.  This
/// is produced when parsing types and when name binding type aliases, and is
/// installed in declaration that use these erroneous types.  All uses of a
/// declaration of invalid type should be ignored and not re-diagnosed.
class ErrorType final : public TypeBase {
  friend class ASTContext;
  // The Error type is always canonical.
  ErrorType(ASTContext &C, Type originalType,
            RecursiveTypeProperties properties)
      : TypeBase(TypeKind::Error, &C, properties) {
    assert(properties.hasError());
    if (originalType) {
      Bits.ErrorType.HasOriginalType = true;
      *reinterpret_cast<Type *>(this + 1) = originalType;
    } else {
      Bits.ErrorType.HasOriginalType = false;
    }
  }

public:
  static Type get(const ASTContext &C);

  /// Produce an error type which records the original type we were trying to
  /// substitute when we ran into a problem.
  static Type get(Type originalType);

  /// Retrieve the original type that this error type replaces, or none if
  /// there is no such type.
  Type getOriginalType() const {
    if (Bits.ErrorType.HasOriginalType)
      return *reinterpret_cast<const Type *>(this + 1);

    return Type();
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Error;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(ErrorType, Type)

/// UnresolvedType - This represents a type variable that cannot be resolved to
/// a concrete type because the expression is ambiguous.  This is produced when
/// parsing expressions and producing diagnostics.  Any instance of this should
/// cause the entire expression to be ambiguously typed.
class UnresolvedType : public TypeBase {
  friend class ASTContext;
  // The Unresolved type is always canonical.
  UnresolvedType(ASTContext &C)
    : TypeBase(TypeKind::Unresolved, &C,
       RecursiveTypeProperties(RecursiveTypeProperties::HasUnresolvedType)) { }
public:
  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Unresolved;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(UnresolvedType, Type)

  
/// BuiltinType - An abstract class for all the builtin types.
class BuiltinType : public TypeBase {
protected:
  BuiltinType(TypeKind kind, const ASTContext &canTypeCtx)
  : TypeBase(kind, &canTypeCtx, RecursiveTypeProperties()) {}
public:
  static bool classof(const TypeBase *T) {
    return T->getKind() >= TypeKind::First_BuiltinType &&
           T->getKind() <= TypeKind::Last_BuiltinType;
  }

  /// Return the "canonical" name for this builtin. E.x.:
  ///
  ///   BuiltinRawPointerType -> BUILTIN_TYPE_NAME_RAWPOINTER ->
  ///   Builtin.RawPointer.
  ///
  /// If \p prependBuiltinNamespace is set to true, "Builtin." is left as a
  /// prefix on the name. This is the default behavior. If the user asks, we
  /// strip off the builtin prefix.
  StringRef getTypeName(SmallVectorImpl<char> &result,
                        bool prependBuiltinNamespace = true) const;

  BuiltinTypeKind getBuiltinTypeKind() const;
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinType, Type)

/// BuiltinRawPointerType - The builtin raw (and dangling) pointer type.  This
/// pointer is completely unmanaged and is equivalent to i8* in LLVM IR.
class BuiltinRawPointerType : public BuiltinType {
  friend class ASTContext;
  BuiltinRawPointerType(const ASTContext &C)
    : BuiltinType(TypeKind::BuiltinRawPointer, C) {}
public:
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::BuiltinRawPointer;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinRawPointerType, BuiltinType);

/// BuiltinNativeObjectType - The builtin opaque object-pointer type.
/// Useful for keeping an object alive when it is otherwise being
/// manipulated via an unsafe pointer type.
class BuiltinNativeObjectType : public BuiltinType {
  friend class ASTContext;
  BuiltinNativeObjectType(const ASTContext &C)
    : BuiltinType(TypeKind::BuiltinNativeObject, C) {}
public:
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::BuiltinNativeObject;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinNativeObjectType, BuiltinType);

/// A type that contains an owning reference to a heap object packed with
/// additional bits. The type uses a bit to discriminate native Swift objects
/// from Objective-C object pointers or tagged pointers.
class BuiltinBridgeObjectType : public BuiltinType {
  friend class ASTContext;
  BuiltinBridgeObjectType(const ASTContext &C)
    : BuiltinType(TypeKind::BuiltinBridgeObject, C) {}
public:
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::BuiltinBridgeObject;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinBridgeObjectType, BuiltinType);

/// BuiltinUnsafeValueBufferType - The builtin opaque fixed-size value
/// buffer type, into which storage for an arbitrary value can be
/// allocated using Builtin.allocateValueBuffer.
///
/// This type is unsafe because it does not permit ordinary value
/// operations.  It is essentially an Any without any type
/// information.  It should only be used in narrow circumstances in
/// carefully-written SIL.
class BuiltinUnsafeValueBufferType : public BuiltinType {
  friend class ASTContext;
  BuiltinUnsafeValueBufferType(const ASTContext &C)
    : BuiltinType(TypeKind::BuiltinUnsafeValueBuffer, C) {}
public:
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::BuiltinUnsafeValueBuffer;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinUnsafeValueBufferType, BuiltinType);

/// A builtin vector type.
class BuiltinVectorType : public BuiltinType, public llvm::FoldingSetNode {
  Type elementType;
  unsigned numElements;

  friend class ASTContext;

  BuiltinVectorType(const ASTContext &context, Type elementType,
                    unsigned numElements)
    : BuiltinType(TypeKind::BuiltinVector, context),
      elementType(elementType), numElements(numElements) { }

public:
  static BuiltinVectorType *get(const ASTContext &context, Type elementType,
                                unsigned numElements);

  /// Retrieve the type of this vector's elements.
  Type getElementType() const { return elementType; }

  /// Retrieve the number of elements in this vector.
  unsigned getNumElements() const { return numElements; }

  void Profile(llvm::FoldingSetNodeID &ID) {
    Profile(ID, getElementType(), getNumElements());
  }
  static void Profile(llvm::FoldingSetNodeID &ID, Type elementType,
                      unsigned numElements) {
    ID.AddPointer(elementType.getPointer());
    ID.AddInteger(numElements);
  }

  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::BuiltinVector;
  }
};
BEGIN_CAN_TYPE_WRAPPER(BuiltinVectorType, BuiltinType)
  PROXY_CAN_TYPE_SIMPLE_GETTER(getElementType)
END_CAN_TYPE_WRAPPER(BuiltinVectorType, BuiltinType)

/// Size descriptor for a builtin integer type. This is either a fixed bit
/// width or an abstract target-dependent value such as "size of a pointer".
class BuiltinIntegerWidth {
  /// Tag values for abstract integer sizes.
  enum : unsigned {
    /// Inhabitants stolen for use as DenseMap special values.
    DenseMapEmpty = ~0U,
    DenseMapTombstone = ~1U,

    /// An arbitrary-precision integer.
    ArbitraryWidth = ~2U,

    /// The size of a pointer on the target system.
    PointerWidth = ~3U,
    
    Least_SpecialValue = ~3U,
  };
  
  unsigned RawValue;
  
  friend struct llvm::DenseMapInfo<swift::BuiltinIntegerWidth>;
  
  /// Private constructor from a raw symbolic value.
  explicit BuiltinIntegerWidth(unsigned RawValue) : RawValue(RawValue) {}
public:
  BuiltinIntegerWidth() : RawValue(0) {}
  
  static BuiltinIntegerWidth fixed(unsigned bitWidth) {
    assert(bitWidth < Least_SpecialValue && "invalid bit width");
    return BuiltinIntegerWidth(bitWidth);
  }
  
  static BuiltinIntegerWidth pointer() {
    return BuiltinIntegerWidth(PointerWidth);
  }

  static BuiltinIntegerWidth arbitrary() {
    return BuiltinIntegerWidth(ArbitraryWidth);
  }
  
  /// Is this a fixed width?
  bool isFixedWidth() const { return RawValue < Least_SpecialValue; }

  /// Get the fixed width value. Fails if the width is abstract.
  unsigned getFixedWidth() const {
    assert(isFixedWidth() && "not fixed-width");
    return RawValue;
  }
  
  /// Is this the abstract target pointer width?
  bool isPointerWidth() const { return RawValue == PointerWidth; }

  /// Is this the abstract arbitrary-width value?
  bool isArbitraryWidth() const { return RawValue == ArbitraryWidth; }
  
  /// Get the least supported value for the width.
  ///
  /// FIXME: This should be build-configuration-dependent.
  unsigned getLeastWidth() const {
    if (isFixedWidth())
      return getFixedWidth();
    if (isPointerWidth())
      return 32;
    if (isArbitraryWidth())
      return 1;
    llvm_unreachable("impossible width value");
  }
  
  /// Get the greatest supported value for the width.
  ///
  /// FIXME: This should be build-configuration-dependent.
  unsigned getGreatestWidth() const {
    if (isFixedWidth())
      return getFixedWidth();
    if (isPointerWidth())
      return 64;
    if (isArbitraryWidth())
      return ~0U;
    llvm_unreachable("impossible width value");
  }

  /// Parse a value of this bit-width.
  ///
  /// If the radix is 0, it is autosensed.
  APInt parse(StringRef text, unsigned radix, bool negate,
              bool *hadError = nullptr) const;
  
  friend bool operator==(BuiltinIntegerWidth a, BuiltinIntegerWidth b) {
    return a.RawValue == b.RawValue;
  }
  friend bool operator!=(BuiltinIntegerWidth a, BuiltinIntegerWidth b) {
    return a.RawValue != b.RawValue;
  }
};

/// An abstract base class for the two integer types.
class AnyBuiltinIntegerType : public BuiltinType {
protected:
  AnyBuiltinIntegerType(TypeKind kind, const ASTContext &C)
    : BuiltinType(kind, C) {}

public:
  static bool classof(const TypeBase *T) {
    return T->getKind() >= TypeKind::First_AnyBuiltinIntegerType &&
           T->getKind() <= TypeKind::Last_AnyBuiltinIntegerType;
  }

  BuiltinIntegerWidth getWidth() const; // defined inline below
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(AnyBuiltinIntegerType, BuiltinType)

/// The builtin integer types.  These directly correspond
/// to LLVM IR integer types.  They lack signedness and have an arbitrary
/// bitwidth.
class BuiltinIntegerType : public AnyBuiltinIntegerType {
  friend class ASTContext;
private:
  BuiltinIntegerWidth Width;
  BuiltinIntegerType(BuiltinIntegerWidth BitWidth, const ASTContext &C)
    : AnyBuiltinIntegerType(TypeKind::BuiltinInteger, C), Width(BitWidth) {}
  
public:
  /// Get a builtin integer type.
  static BuiltinIntegerType *get(BuiltinIntegerWidth BitWidth,
                                 const ASTContext &C);
  
  /// Get a builtin integer type of fixed width.
  static BuiltinIntegerType *get(unsigned BitWidth, const ASTContext &C) {
    return get(BuiltinIntegerWidth::fixed(BitWidth), C);
  }
  
  /// Get the target-pointer-width builtin integer type.
  static BuiltinIntegerType *getWordType(const ASTContext &C) {
    return get(BuiltinIntegerWidth::pointer(), C);
  }
  
  /// Return the bit width of the integer.  Always returns a non-arbitrary
  /// width.
  BuiltinIntegerWidth getWidth() const {
    return Width;
  }
  
  /// Is the integer fixed-width?
  bool isFixedWidth() const {
    return Width.isFixedWidth();
  }
  
  /// Is the integer fixed-width with the given width?
  bool isFixedWidth(unsigned width) const {
    return Width.isFixedWidth() && Width.getFixedWidth() == width;
  }
  
  /// Get the fixed integer width. Fails if the integer has abstract width.
  unsigned getFixedWidth() const {
    return Width.getFixedWidth();
  }
  
  /// Return the least supported width of the integer.
  ///
  /// FIXME: This should be build-configuration-dependent.
  unsigned getLeastWidth() const {
    return Width.getLeastWidth();
  }
  
  /// Return the greatest supported width of the integer.
  ///
  /// FIXME: This should be build-configuration-dependent.
  unsigned getGreatestWidth() const {
    return Width.getGreatestWidth();
  }

  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::BuiltinInteger;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinIntegerType, AnyBuiltinIntegerType)

/// BuiltinIntegerLiteralType - The builtin arbitrary-precision integer type.
/// Useful for constructing integer literals.
class BuiltinIntegerLiteralType : public AnyBuiltinIntegerType {
  friend class ASTContext;
  BuiltinIntegerLiteralType(const ASTContext &C)
    : AnyBuiltinIntegerType(TypeKind::BuiltinIntegerLiteral, C) {}
public:
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::BuiltinIntegerLiteral;
  }

  BuiltinIntegerWidth getWidth() const = delete;
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinIntegerLiteralType, AnyBuiltinIntegerType);

inline BuiltinIntegerWidth AnyBuiltinIntegerType::getWidth() const {
  if (auto intTy = dyn_cast<BuiltinIntegerType>(this)) {
    return intTy->getWidth();
  } else {
    return BuiltinIntegerWidth::arbitrary();
  }
}

class BuiltinFloatType : public BuiltinType {
  friend class ASTContext;
public:
  enum FPKind {
    IEEE16, IEEE32, IEEE64, IEEE80, IEEE128, /// IEEE floating point types.
    PPC128   /// PowerPC "double double" type.
  };
private:
  FPKind Kind;
  
  BuiltinFloatType(FPKind Kind, const ASTContext &C)
    : BuiltinType(TypeKind::BuiltinFloat, C), Kind(Kind) {}
public:
  
  /// getFPKind - Get the 
  FPKind getFPKind() const {
    return Kind;
  }

  const llvm::fltSemantics &getAPFloatSemantics() const;

  unsigned getBitWidth() const {
    switch (Kind) {
    case IEEE16: return 16;
    case IEEE32: return 32;
    case IEEE64: return 64;
    case IEEE80: return 80;
    case IEEE128:
    case PPC128: return 128;
    }
    llvm_unreachable("bad FPKind");
  }

  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::BuiltinFloat;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinFloatType, BuiltinType)
  
/// An abstract type for all sugared types to make getDesugaredType() fast by
/// sharing field offsets and logic for the fast path.
class SugarType : public TypeBase {
  // The state of this union is known via Bits.SugarType.HasCachedType so that
  // we can avoid masking the pointer on the fast path.
  union {
    TypeBase *UnderlyingType;
    const ASTContext *Context;
  };

protected:
  // Sugar types are never canonical.
  SugarType(TypeKind K, const ASTContext *ctx,
            RecursiveTypeProperties properties)
      : TypeBase(K, nullptr, properties), Context(ctx) {
    assert(ctx != nullptr &&
           "Context for SugarType should not be null");
    Bits.SugarType.HasCachedType = false;
  }

  // Sugar types are never canonical.
  SugarType(TypeKind K, Type type, RecursiveTypeProperties properties)
      : TypeBase(K, nullptr, properties), UnderlyingType(type.getPointer()) {
    Bits.SugarType.HasCachedType = true;
  }

  void setUnderlyingType(Type type) {
    assert(!Bits.SugarType.HasCachedType && "Cached type already set");
    Bits.SugarType.HasCachedType = true;
    UnderlyingType = type.getPointer();
  }

public:
  /// Remove one level of top-level sugar from this type.
  Type getSinglyDesugaredTypeSlow();
  TypeBase *getSinglyDesugaredType() const {
    if (LLVM_LIKELY(Bits.SugarType.HasCachedType))
      return UnderlyingType;
    auto Ty = const_cast<SugarType*>(this);
    return Ty->getSinglyDesugaredTypeSlow().getPointer();
  }

  static bool classof(const TypeBase *T) {
    // Workaround: http://llvm.org/PR35906
    if (TypeKind::Last_Type == TypeKind::Last_SugarType)
      return T->getKind() >= TypeKind::First_SugarType;
    return T->getKind() >= TypeKind::First_SugarType &&
           T->getKind() <= TypeKind::Last_SugarType;
  }
};

/// A reference to a type alias that is somehow generic, along with the
/// set of substitutions to apply to make the type concrete.
class TypeAliasType final
  : public SugarType, public llvm::FoldingSetNode,
    llvm::TrailingObjects<TypeAliasType, Type, SubstitutionMap>
{
  TypeAliasDecl *typealias;

  friend class ASTContext;
  friend TrailingObjects;

  TypeAliasType(TypeAliasDecl *typealias, Type parent,
                SubstitutionMap substitutions, Type underlying,
                RecursiveTypeProperties properties);

  size_t numTrailingObjects(OverloadToken<Type>) const {
    return Bits.TypeAliasType.HasParent ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<SubstitutionMap>) const {
    return Bits.TypeAliasType.HasSubstitutionMap ? 1 : 0;
  }

public:
  /// Retrieve the generic signature used for substitutions.
  GenericSignature getGenericSignature() const {
    return getSubstitutionMap().getGenericSignature();
  }

  static TypeAliasType *get(TypeAliasDecl *typealias, Type parent,
                            SubstitutionMap substitutions, Type underlying);

  /// Returns the declaration that declares this type.
  TypeAliasDecl *getDecl() const {
    // Avoid requiring the definition of TypeAliasDecl.
    return typealias;
  }

  /// Retrieve the parent of this type as written, e.g., the part that was
  /// written before ".", if provided.
  Type getParent() const {
    return Bits.TypeAliasType.HasParent ? *getTrailingObjects<Type>()
                                        : Type();
  }

  /// Retrieve the substitution map applied to the declaration's underlying
  /// to produce the described type.
  SubstitutionMap getSubstitutionMap() const {
    if (!Bits.TypeAliasType.HasSubstitutionMap)
      return SubstitutionMap();

    return *getTrailingObjects<SubstitutionMap>();
  }

  /// Get the innermost generic arguments, which correspond to the generic
  /// arguments that are directly applied to the typealias declaration in
  /// produced by \c getDecl().
  ///
  /// The result can be empty, if the declaration itself is non-generic but
  /// the parent is generic.
  SmallVector<Type, 2> getInnermostGenericArgs() const;

  // Support for FoldingSet.
  void Profile(llvm::FoldingSetNodeID &id) const;

  static void Profile(llvm::FoldingSetNodeID &id, TypeAliasDecl *typealias,
                      Type parent, SubstitutionMap substitutions,
                      Type underlying);

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::TypeAlias;
  }
};

// TODO: As part of AST modernization, replace with a proper
// 'ParameterTypeElt' or similar, and have FunctionTypes only have a list
// of 'ParameterTypeElt's. Then, this information can be removed from
// TupleTypeElt.
//
/// Provide parameter type relevant flags, i.e. variadic, autoclosure, and
/// escaping.
class ParameterTypeFlags {
  enum ParameterFlags : uint8_t {
    None        = 0,
    Variadic    = 1 << 0,
    AutoClosure = 1 << 1,
    OwnershipShift = 2,
    Ownership   = 7 << OwnershipShift,
    // SWIFT_ENABLE_TENSORFLOW
    NonDifferentiable = 1 << 5,
    NumBits = 6
  };
  OptionSet<ParameterFlags> value;
  static_assert(NumBits < 8*sizeof(OptionSet<ParameterFlags>), "overflowed");

  ParameterTypeFlags(OptionSet<ParameterFlags, uint8_t> val) : value(val) {}

public:
  ParameterTypeFlags() = default;
  static ParameterTypeFlags fromRaw(uint8_t raw) {
    return ParameterTypeFlags(OptionSet<ParameterFlags>(raw));
  }

  ParameterTypeFlags(bool variadic, bool autoclosure,
                     // SWIFT_ENABLE_TENSORFLOW
                     ValueOwnership ownership, bool nonDifferentiable)
      : value((variadic ? Variadic : 0) | (autoclosure ? AutoClosure : 0) |
              // SWIFT_ENABLE_TENSORFLOW
              (uint8_t(ownership) << OwnershipShift) |
              (nonDifferentiable ? NonDifferentiable : 0)) {}

  /// Create one from what's present in the parameter type
  inline static ParameterTypeFlags
  // SWIFT_ENABLE_TENSORFLOW
  fromParameterType(Type paramTy, bool isVariadic, bool isAutoClosure,
                    ValueOwnership ownership, bool isNonDifferentiable);

  bool isNone() const { return !value; }
  bool isVariadic() const { return value.contains(Variadic); }
  bool isAutoClosure() const { return value.contains(AutoClosure); }
  bool isInOut() const { return getValueOwnership() == ValueOwnership::InOut; }
  bool isShared() const { return getValueOwnership() == ValueOwnership::Shared;}
  bool isOwned() const { return getValueOwnership() == ValueOwnership::Owned; }
  // SWIFT_ENABLE_TENSORFLOW
  bool isNonDifferentiable() const { return value.contains(NonDifferentiable); }

  ValueOwnership getValueOwnership() const {
    return ValueOwnership((value.toRaw() & Ownership) >> OwnershipShift);
  }

  ParameterTypeFlags withVariadic(bool variadic) const {
    return ParameterTypeFlags(variadic ? value | ParameterTypeFlags::Variadic
                                       : value - ParameterTypeFlags::Variadic);
  }

  ParameterTypeFlags withInOut(bool isInout) const {
    return withValueOwnership(isInout ? ValueOwnership::InOut
                                      : ValueOwnership::Default);
  }
  
  ParameterTypeFlags withShared(bool isShared) const {
    return withValueOwnership(isShared ? ValueOwnership::Shared
                                       : ValueOwnership::Default);
  }

  ParameterTypeFlags withOwned(bool isOwned) const {
    return withValueOwnership(isOwned ? ValueOwnership::Owned
                                      : ValueOwnership::Default);
  }

  ParameterTypeFlags withValueOwnership(ValueOwnership ownership) const {
    return (value - ParameterTypeFlags::Ownership)
            | ParameterFlags(uint8_t(ownership) << OwnershipShift);
  }

  ParameterTypeFlags withAutoClosure(bool isAutoClosure) const {
    return ParameterTypeFlags(isAutoClosure
                              ? value | ParameterTypeFlags::AutoClosure
                              : value - ParameterTypeFlags::AutoClosure);
  }

  // SWIFT_ENABLE_TENSORFLOW
  ParameterTypeFlags withNonDifferentiable(bool nonDifferentiable) const {
    return ParameterTypeFlags(nonDifferentiable
                              ? value | ParameterTypeFlags::NonDifferentiable
                              : value - ParameterTypeFlags::NonDifferentiable);
  }

  bool operator ==(const ParameterTypeFlags &other) const {
    return value.toRaw() == other.value.toRaw();
  }

  bool operator!=(const ParameterTypeFlags &other) const {
    return value.toRaw() != other.value.toRaw();
  }

  uint8_t toRaw() const { return value.toRaw(); }
};

class YieldTypeFlags {
  enum YieldFlags : uint8_t {
    None        = 0,
    Ownership   = 7,
    OwnershipShift = 0,

    NumBits = 3
  };
  OptionSet<YieldFlags> value;

  static_assert(NumBits < 8 * sizeof(OptionSet<YieldFlags>), "overflowed");

  YieldTypeFlags(OptionSet<YieldFlags, uint8_t> val) : value(val) {}

public:
  YieldTypeFlags() = default;
  static YieldTypeFlags fromRaw(uint8_t raw) {
    return YieldTypeFlags(OptionSet<YieldFlags>(raw));
  }

  YieldTypeFlags(ValueOwnership ownership)
      : value(uint8_t(ownership) << OwnershipShift) {}

  bool isInOut() const { return getValueOwnership() == ValueOwnership::InOut; }
  bool isShared() const { return getValueOwnership() == ValueOwnership::Shared;}
  bool isOwned() const { return getValueOwnership() == ValueOwnership::Owned; }

  ValueOwnership getValueOwnership() const {
    return ValueOwnership((value.toRaw() & Ownership) >> OwnershipShift);
  }

  YieldTypeFlags withInOut(bool isInout) const {
    return withValueOwnership(isInout ? ValueOwnership::InOut
                                      : ValueOwnership::Default);
  }
  
  YieldTypeFlags withShared(bool isShared) const {
    return withValueOwnership(isShared ? ValueOwnership::Shared
                                       : ValueOwnership::Default);
  }

  YieldTypeFlags withOwned(bool isOwned) const {
    return withValueOwnership(isOwned ? ValueOwnership::Owned
                                      : ValueOwnership::Default);
  }

  YieldTypeFlags withValueOwnership(ValueOwnership ownership) const {
    return (value - YieldTypeFlags::Ownership)
            | YieldFlags(uint8_t(ownership) << OwnershipShift);
  }

  /// Return these flags interpreted as parameter flags.
  ParameterTypeFlags asParamFlags() const {
    return ParameterTypeFlags(/*variadic*/ false,
                              /*autoclosure*/ false,
                              // SWIFT_ENABLE_TENSORFLOW
                              getValueOwnership(),
                              /*nondifferentiable*/ false);
  }

  bool operator ==(const YieldTypeFlags &other) const {
    return value.toRaw() == other.value.toRaw();
  }

  bool operator!=(const YieldTypeFlags &other) const {
    return value.toRaw() != other.value.toRaw();
  }

  uint8_t toRaw() const { return value.toRaw(); }
};

/// ParenType - A paren type is a type that's been written in parentheses.
class ParenType : public SugarType {
  friend class ASTContext;
  
  ParenType(Type UnderlyingType, RecursiveTypeProperties properties,
            ParameterTypeFlags flags);

public:
  Type getUnderlyingType() const { return getSinglyDesugaredType(); }

  static ParenType *get(const ASTContext &C, Type underlying,
                        ParameterTypeFlags flags = {});

  /// Get the parameter flags
  ParameterTypeFlags getParameterFlags() const {
    return ParameterTypeFlags::fromRaw(Bits.ParenType.Flags);
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Paren;
  }
};

/// TupleTypeElt - This represents a single element of a tuple.
class TupleTypeElt {
  /// An optional name for the field.
  Identifier Name;

  /// This is the type of the field.
  Type ElementType;

  /// Flags that are specific to and relevant for parameter types
  ParameterTypeFlags Flags;

  friend class TupleType;
  
public:
  TupleTypeElt() = default;
  TupleTypeElt(Type ty, Identifier name = Identifier(),
               ParameterTypeFlags fl = {});
  
  bool hasName() const { return !Name.empty(); }
  Identifier getName() const { return Name; }
  
  Type getRawType() const { return ElementType; }
  Type getType() const;

  ParameterTypeFlags getParameterFlags() const { return Flags; }

  /// Determine whether this field is variadic.
  bool isVararg() const { return Flags.isVariadic(); }

  /// Determine whether this field is an autoclosure parameter closure.
  bool isAutoClosure() const { return Flags.isAutoClosure(); }

  /// Determine whether this field is marked 'inout'.
  bool isInOut() const { return Flags.isInOut(); }
  
  /// Remove the type of this varargs element designator, without the array
  /// type wrapping it.
  Type getVarargBaseTy() const;
  
  /// Retrieve a copy of this tuple type element with the type replaced.
  TupleTypeElt getWithType(Type T) const;

  /// Retrieve a copy of this tuple type element with the name replaced.
  TupleTypeElt getWithName(Identifier name) const;

  /// Retrieve a copy of this tuple type element with no name
  TupleTypeElt getWithoutName() const { return getWithName(Identifier()); }
};

inline Type getTupleEltType(const TupleTypeElt &elt) {
  return elt.getType();
}
typedef ArrayRefView<TupleTypeElt,Type,getTupleEltType> TupleEltTypeArrayRef;

inline CanType getCanTupleEltType(const TupleTypeElt &elt) {
  return CanType(elt.getType());
}
typedef ArrayRefView<TupleTypeElt,CanType,getCanTupleEltType>
  CanTupleEltTypeArrayRef;

/// TupleType - A tuple is a parenthesized list of types where each name has an
/// optional name.
///
class TupleType final : public TypeBase, public llvm::FoldingSetNode,
    private llvm::TrailingObjects<TupleType, TupleTypeElt> {
  friend TrailingObjects;
  
public:
  /// get - Return the uniqued tuple type with the specified elements.
  /// Returns a ParenType instead if there is exactly one element which
  /// is unlabeled and not varargs, so it doesn't accidentally construct
  /// a tuple which is impossible to write.
  static Type get(ArrayRef<TupleTypeElt> Elements, const ASTContext &C);

  /// getEmpty - Return the empty tuple type '()'.
  static CanTypeWrapper<TupleType> getEmpty(const ASTContext &C);

  unsigned getNumElements() const { return Bits.TupleType.Count; }

  /// getElements - Return the elements of this tuple.
  ArrayRef<TupleTypeElt> getElements() const {
    return {getTrailingObjects<TupleTypeElt>(), getNumElements()};
  }

  const TupleTypeElt &getElement(unsigned i) const {
    return getTrailingObjects<TupleTypeElt>()[i];
  }

  /// getElementType - Return the type of the specified element.
  Type getElementType(unsigned ElementNo) const {
    return getTrailingObjects<TupleTypeElt>()[ElementNo].getType();
  }

  TupleEltTypeArrayRef getElementTypes() const {
    return TupleEltTypeArrayRef(getElements());
  }
  
  /// getNamedElementId - If this tuple has an element with the specified name,
  /// return the element index, otherwise return -1.
  int getNamedElementId(Identifier I) const;
  
  /// Returns true if this tuple has inout, __shared or __owned elements.
  bool hasElementWithOwnership() const {
    return static_cast<bool>(Bits.TupleType.HasElementWithOwnership);
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Tuple;
  }

  void Profile(llvm::FoldingSetNodeID &ID) {
    Profile(ID, getElements());
  }
  static void Profile(llvm::FoldingSetNodeID &ID, 
                      ArrayRef<TupleTypeElt> Elements);
  
private:
  TupleType(ArrayRef<TupleTypeElt> elements, const ASTContext *CanCtx,
            RecursiveTypeProperties properties,
            bool hasElementWithOwnership)
     : TypeBase(TypeKind::Tuple, CanCtx, properties) {
     Bits.TupleType.HasElementWithOwnership = hasElementWithOwnership;
     Bits.TupleType.Count = elements.size();
     std::uninitialized_copy(elements.begin(), elements.end(),
                             getTrailingObjects<TupleTypeElt>());
  }
};
BEGIN_CAN_TYPE_WRAPPER(TupleType, Type)
  CanType getElementType(unsigned elementNo) const {
    return CanType(getPointer()->getElementType(elementNo));
  }
  CanTupleEltTypeArrayRef getElementTypes() const {
    return CanTupleEltTypeArrayRef(getPointer()->getElements());
  }
END_CAN_TYPE_WRAPPER(TupleType, Type)

/// UnboundGenericType - Represents a generic type where the type arguments have
/// not yet been resolved.
class UnboundGenericType : public AnyGenericType,
    public llvm::FoldingSetNode {
private:
  UnboundGenericType(GenericTypeDecl *TheDecl, Type Parent, const ASTContext &C,
                     RecursiveTypeProperties properties)
    : AnyGenericType(TheDecl, Parent, TypeKind::UnboundGeneric,
                     (!Parent || Parent->isCanonical()) ? &C : nullptr,
                     properties | RecursiveTypeProperties::HasUnboundGeneric) {}

public:
  static UnboundGenericType* get(GenericTypeDecl *TheDecl, Type Parent,
                                 const ASTContext &C);

  void Profile(llvm::FoldingSetNodeID &ID) {
    Profile(ID, getDecl(), getParent());
  }
  static void Profile(llvm::FoldingSetNodeID &ID, GenericTypeDecl *D,
                      Type Parent);

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::UnboundGeneric;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(UnboundGenericType, AnyGenericType)

inline CanType getAsCanType(const Type &type) { return CanType(type); }
typedef ArrayRefView<Type,CanType,getAsCanType> CanTypeArrayRef;

/// BoundGenericType - An abstract class for applying a generic type to the
/// given type arguments.
class BoundGenericType : public NominalOrBoundGenericNominalType,
    public llvm::FoldingSetNode {
  
  /// Retrieve the intrusive pointer storage from the subtype
  const Type *getTrailingObjectsPointer() const;
  Type *getTrailingObjectsPointer() {
    const BoundGenericType *temp = this;
    return const_cast<Type *>(temp->getTrailingObjectsPointer());
  }

protected:
  BoundGenericType(TypeKind theKind, NominalTypeDecl *theDecl, Type parent,
                   ArrayRef<Type> genericArgs, const ASTContext *context,
                   RecursiveTypeProperties properties);

public:
  static BoundGenericType* get(NominalTypeDecl *TheDecl, Type Parent,
                               ArrayRef<Type> GenericArgs);

  /// Retrieve the set of generic arguments provided at this level.
  ArrayRef<Type> getGenericArgs() const {
    return {getTrailingObjectsPointer(), Bits.BoundGenericType.GenericArgCount};
  }

  void Profile(llvm::FoldingSetNodeID &ID) {
    Profile(ID, getDecl(), getParent(), getGenericArgs());
  }
  static void Profile(llvm::FoldingSetNodeID &ID, NominalTypeDecl *TheDecl,
                      Type Parent, ArrayRef<Type> GenericArgs);

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() >= TypeKind::First_BoundGenericType &&
           T->getKind() <= TypeKind::Last_BoundGenericType;
  }
};
BEGIN_CAN_TYPE_WRAPPER(BoundGenericType, NominalOrBoundGenericNominalType)
  CanTypeArrayRef getGenericArgs() const {
    return CanTypeArrayRef(getPointer()->getGenericArgs());
  }
END_CAN_TYPE_WRAPPER(BoundGenericType, NominalOrBoundGenericNominalType)


/// BoundGenericClassType - A subclass of BoundGenericType for the case
/// when the nominal type is a generic class type.
class BoundGenericClassType final : public BoundGenericType,
    private llvm::TrailingObjects<BoundGenericClassType, Type> {
  friend TrailingObjects;

private:
  BoundGenericClassType(ClassDecl *theDecl, Type parent,
                        ArrayRef<Type> genericArgs, const ASTContext *context,
                        RecursiveTypeProperties properties)
    : BoundGenericType(TypeKind::BoundGenericClass,
                       reinterpret_cast<NominalTypeDecl*>(theDecl), parent,
                       genericArgs, context, properties) {}
  friend class BoundGenericType;

public:
  static BoundGenericClassType* get(ClassDecl *theDecl, Type parent,
                                    ArrayRef<Type> genericArgs) {
    return cast<BoundGenericClassType>(
             BoundGenericType::get(reinterpret_cast<NominalTypeDecl*>(theDecl),
                                   parent, genericArgs));
  }

  /// Returns the declaration that declares this type.
  ClassDecl *getDecl() const {
    return reinterpret_cast<ClassDecl*>(BoundGenericType::getDecl());
  }

  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::BoundGenericClass;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(BoundGenericClassType, BoundGenericType)

/// BoundGenericEnumType - A subclass of BoundGenericType for the case
/// when the nominal type is a generic enum type.
class BoundGenericEnumType final : public BoundGenericType,
    private llvm::TrailingObjects<BoundGenericEnumType, Type> {
  friend TrailingObjects;

private:
  BoundGenericEnumType(EnumDecl *theDecl, Type parent,
                       ArrayRef<Type> genericArgs, const ASTContext *context,
                       RecursiveTypeProperties properties)
    : BoundGenericType(TypeKind::BoundGenericEnum,
                       reinterpret_cast<NominalTypeDecl*>(theDecl), parent,
                       genericArgs, context, properties) {}
  friend class BoundGenericType;

public:
  static BoundGenericEnumType* get(EnumDecl *theDecl, Type parent,
                                    ArrayRef<Type> genericArgs) {
    return cast<BoundGenericEnumType>(
             BoundGenericType::get(reinterpret_cast<NominalTypeDecl*>(theDecl),
                                   parent, genericArgs));
  }

  /// Returns the declaration that declares this type.
  EnumDecl *getDecl() const {
    return reinterpret_cast<EnumDecl*>(BoundGenericType::getDecl());
  }

  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::BoundGenericEnum;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(BoundGenericEnumType, BoundGenericType)

/// BoundGenericStructType - A subclass of BoundGenericType for the case
/// when the nominal type is a generic struct type.
class BoundGenericStructType final : public BoundGenericType,
    private llvm::TrailingObjects<BoundGenericStructType, Type> {
  friend TrailingObjects;

private:
  BoundGenericStructType(StructDecl *theDecl, Type parent,
                         ArrayRef<Type> genericArgs, const ASTContext *context,
                         RecursiveTypeProperties properties)
    : BoundGenericType(TypeKind::BoundGenericStruct, 
                       reinterpret_cast<NominalTypeDecl*>(theDecl), parent,
                       genericArgs, context, properties) {}
  friend class BoundGenericType;

public:
  static BoundGenericStructType* get(StructDecl *theDecl, Type parent,
                                    ArrayRef<Type> genericArgs) {
    return cast<BoundGenericStructType>(
             BoundGenericType::get(reinterpret_cast<NominalTypeDecl*>(theDecl),
                                   parent, genericArgs));
  }

  /// Returns the declaration that declares this type.
  StructDecl *getDecl() const {
    return reinterpret_cast<StructDecl*>(BoundGenericType::getDecl());
  }

  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::BoundGenericStruct;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(BoundGenericStructType, BoundGenericType)

/// NominalType - Represents a type with a name that is significant, such that
/// the name distinguishes it from other structurally-similar types that have
/// different names. Nominal types are always canonical.
class NominalType : public NominalOrBoundGenericNominalType {

protected:
  NominalType(TypeKind K, const ASTContext *C, NominalTypeDecl *TheDecl,
              Type Parent, RecursiveTypeProperties properties)
    : NominalOrBoundGenericNominalType(TheDecl, Parent, K,
               (!Parent || Parent->isCanonical())? C : nullptr, properties) {}

public:
  static NominalType *get(NominalTypeDecl *D, Type Parent, const ASTContext &C);

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() >= TypeKind::First_NominalType &&
           T->getKind() <= TypeKind::Last_NominalType;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(NominalType, NominalOrBoundGenericNominalType)

/// EnumType - This represents the type declared by an EnumDecl.
class EnumType : public NominalType {
public:
  /// getDecl() - Returns the decl which declares this type.
  EnumDecl *getDecl() const {
    return reinterpret_cast<EnumDecl *>(NominalType::getDecl());
  }

  /// Retrieve the type when we're referencing the given enum
  /// declaration in the parent type \c Parent.
  static EnumType *get(EnumDecl *D, Type Parent, const ASTContext &C);

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Enum;
  }

private:
  EnumType(EnumDecl *TheDecl, Type Parent, const ASTContext &Ctx,
            RecursiveTypeProperties properties);
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(EnumType, NominalType)

/// StructType - This represents the type declared by a StructDecl.
class StructType : public NominalType {
public:
  /// getDecl() - Returns the decl which declares this type.
  StructDecl *getDecl() const {
    return reinterpret_cast<StructDecl *>(NominalType::getDecl());
  }

  /// Retrieve the type when we're referencing the given struct
  /// declaration in the parent type \c Parent.
  static StructType *get(StructDecl *D, Type Parent, const ASTContext &C);

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Struct;
  }
  
private:
  StructType(StructDecl *TheDecl, Type Parent, const ASTContext &Ctx,
             RecursiveTypeProperties properties);
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(StructType, NominalType)

/// ClassType - This represents the type declared by a ClassDecl.
class ClassType : public NominalType {
public:
  /// getDecl() - Returns the decl which declares this type.
  ClassDecl *getDecl() const {
    return reinterpret_cast<ClassDecl *>(NominalType::getDecl());
  }

  /// Retrieve the type when we're referencing the given class
  /// declaration in the parent type \c Parent.
  static ClassType *get(ClassDecl *D, Type Parent, const ASTContext &C);

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Class;
  }
  
private:
  ClassType(ClassDecl *TheDecl, Type Parent, const ASTContext &Ctx,
            RecursiveTypeProperties properties);
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(ClassType, NominalType)

/// Describes the representation of a metatype.
///
/// There are several potential representations for metatypes within
/// SIL, which are distinguished by the metatype representation. This
/// enumeration captures the different representations. Some
/// conversions between representations are possible: for example, one
/// can convert a thin representation to a thick one (but not
/// vice-versa), and different representations are required in
/// different places.
enum class MetatypeRepresentation : char {
  /// A thin metatype requires no runtime information, because the
  /// type itself provides no dynamic behavior.
  ///
  /// Struct and enum metatypes are thin, because dispatch to static
  /// struct and enum members is completely static.
  Thin,
  /// A thick metatype refers to a complete metatype representation
  /// that allows introspection and dynamic dispatch. 
  ///
  /// Thick metatypes are used for class and existential metatypes,
  /// which permit dynamic behavior.
  Thick,
  /// An Objective-C metatype refers to an Objective-C class object.
  ObjC,

  Last_MetatypeRepresentation = ObjC
};

/// AnyMetatypeType - A common parent class of MetatypeType and
/// ExistentialMetatypeType.
class AnyMetatypeType : public TypeBase {
  Type InstanceType;
protected:
  AnyMetatypeType(TypeKind kind, const ASTContext *C,
                  RecursiveTypeProperties properties,
                  Type instanceType,
                  Optional<MetatypeRepresentation> repr);


public:
  Type getInstanceType() const { return InstanceType; }

  /// Does this metatype have a representation?
  ///
  /// Only SIL metatype types have a representation.
  bool hasRepresentation() const {
    return Bits.AnyMetatypeType.Representation > 0;
  }
  
  /// Retrieve the metatype representation.
  ///
  /// The metatype representation is a SIL-only property. Thin
  /// metatypes can be lowered away to empty types in IR, unless a
  /// metatype value is required at an abstraction level.
  MetatypeRepresentation getRepresentation() const {
    assert(Bits.AnyMetatypeType.Representation &&
           "metatype has no representation");
    return static_cast<MetatypeRepresentation>(
             Bits.AnyMetatypeType.Representation - 1);
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Metatype ||
           T->getKind() == TypeKind::ExistentialMetatype;
  }
};
BEGIN_CAN_TYPE_WRAPPER(AnyMetatypeType, Type)
  PROXY_CAN_TYPE_SIMPLE_GETTER(getInstanceType)
END_CAN_TYPE_WRAPPER(AnyMetatypeType, Type)

/// MetatypeType - This is the type given to a metatype value.  When a type is
/// declared, a 'metatype' value is injected into the value namespace to
/// resolve references to the type.  An example:
///
///  struct x { ... }  // declares type 'x' and metatype 'x'.
///  x.a()             // use of the metatype value since its a value context.
///
/// In general, this is spelled X.Type, unless X is an existential
/// type, in which case the ordinary metatype is spelled X.Protocol
/// and X.Type connotes the ExistentialMetatypeType.
class MetatypeType : public AnyMetatypeType {
  static MetatypeType *get(Type T, Optional<MetatypeRepresentation> Repr,
                           const ASTContext &C);

public:
  /// Return the MetatypeType for the specified type declaration.
  ///
  /// This leaves the 'representation' property unavailable.
  static MetatypeType *get(Type T, const ASTContext &C) {
    return get(T, None, C);
  }
  
  /// Return the MetatypeType for the specified type declaration with
  /// the given representation.
  ///
  /// Metatype representation is a SIL-only property. Thin metatypes
  /// can be lowered away to empty types in IR.
  static MetatypeType *get(Type T,
                           Optional<MetatypeRepresentation> repr = None) {
    return get(T, repr, T->getASTContext());
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Metatype;
  }
  
private:
  MetatypeType(Type T, const ASTContext *C,
               RecursiveTypeProperties properties,
               Optional<MetatypeRepresentation> repr);
  friend class TypeDecl;
};
BEGIN_CAN_TYPE_WRAPPER(MetatypeType, AnyMetatypeType)
  static CanMetatypeType get(CanType type) {
    return CanMetatypeType(MetatypeType::get(type));
  }
  static CanMetatypeType get(CanType type, MetatypeRepresentation repr) {
    return CanMetatypeType(MetatypeType::get(type, repr));
  }
END_CAN_TYPE_WRAPPER(MetatypeType, AnyMetatypeType)

/// ExistentialMetatypeType - This is the type given to an existential
/// metatype value, i.e. the type of the dynamic type of an
/// existential value.  The instance type must be an existential type
/// of some sort.
///
/// Formally, this type is \exists t : T... . t.Type.  In contrast,
/// the MetatypeType for a ProtocolType is a singleton.
///
/// This is spelled X.Type, where X is an existential type.
///
/// The representation of an existential metatype cannot be thin.
class ExistentialMetatypeType : public AnyMetatypeType {
public:
  static ExistentialMetatypeType *get(Type T,
                                      Optional<MetatypeRepresentation> Repr,
                                      const ASTContext &C);

  /// Return the ExistentialMetatypeType for the specified type
  /// with the given representation.
  ///
  /// Metatype representation is a SIL-only property. Existential
  /// metatypes cannot be thin.
  static ExistentialMetatypeType *get(Type T,
                                      Optional<MetatypeRepresentation> repr
                                        = None) {
    return get(T, repr, T->getASTContext());
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::ExistentialMetatype;
  }
  
private:
  ExistentialMetatypeType(Type T, const ASTContext *C,
                          RecursiveTypeProperties properties,
                          Optional<MetatypeRepresentation> repr);
  friend class TypeDecl;
};
BEGIN_CAN_TYPE_WRAPPER(ExistentialMetatypeType, AnyMetatypeType)
  static CanExistentialMetatypeType get(CanType type) {
    return CanExistentialMetatypeType(ExistentialMetatypeType::get(type));
  }
  static CanExistentialMetatypeType get(CanType type,
                                        MetatypeRepresentation repr) {
    return CanExistentialMetatypeType(ExistentialMetatypeType::get(type, repr));
  }
END_CAN_TYPE_WRAPPER(ExistentialMetatypeType, AnyMetatypeType)
  
/// ModuleType - This is the type given to a module value, e.g. the "Builtin" in
/// "Builtin.int".  This is typically given to a ModuleExpr, but can also exist
/// on ParenExpr, for example.
class ModuleType : public TypeBase {
  ModuleDecl *const TheModule;
  
public:
  /// get - Return the ModuleType for the specified module.
  static ModuleType *get(ModuleDecl *M);

  ModuleDecl *getModule() const { return TheModule; }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Module;
  }
  
private:
  ModuleType(ModuleDecl *M, const ASTContext &Ctx)
    : TypeBase(TypeKind::Module, &Ctx, // Always canonical
               RecursiveTypeProperties()),
      TheModule(M) {
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(ModuleType, Type)
  
/// The type given to a dynamic \c Self return type.
///
/// Example:
/// \code
/// class X {
///   class func factory() -> Self { ... }
/// };
/// \endcode
///
/// In this example, \c Self is represented by a 
/// \c DynamicSelfType node whose self type is \c X.
class DynamicSelfType : public TypeBase {
  Type SelfType;

public:
  /// Return the DynamicSelf for the specified self type.
  static DynamicSelfType *get(Type selfType, const ASTContext &ctx);

  /// Retrieve the (static) self type for this dynamic self type.
  Type getSelfType() const { return SelfType; }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::DynamicSelf;
  }
  
private:
  DynamicSelfType(Type selfType, const ASTContext &ctx,
                  RecursiveTypeProperties properties)
    : TypeBase(TypeKind::DynamicSelf, selfType->isCanonical()? &ctx : 0,
               properties | RecursiveTypeProperties(
                 RecursiveTypeProperties::HasDynamicSelf)),
      SelfType(selfType) { }

  friend class TypeDecl;
};
BEGIN_CAN_TYPE_WRAPPER(DynamicSelfType, Type)
  PROXY_CAN_TYPE_SIMPLE_GETTER(getSelfType)

  static CanDynamicSelfType get(CanType selfType, const ASTContext &ctx) {
    return CanDynamicSelfType(DynamicSelfType::get(selfType, ctx));
  }
END_CAN_TYPE_WRAPPER(DynamicSelfType, Type)

/// A language-level calling convention.
enum class SILFunctionLanguage : uint8_t {
  /// A variation of the Swift calling convention.
  Swift = 0,

  /// A variation of the C calling convention.
  C,
};

/// The representation form of a function.
enum class FunctionTypeRepresentation : uint8_t {
  /// A "thick" function that carries a context pointer to reference captured
  /// state. The default native function representation.
  Swift = 0,
  
  /// A thick function that is represented as an Objective-C block.
  Block,
  
  /// A "thin" function that needs no context.
  Thin,
  
  /// A C function pointer, which is thin and also uses the C calling
  /// convention.
  CFunctionPointer,

  /// The value of the greatest AST function representation.
  Last = CFunctionPointer,
};

/// The representation form of a SIL function.
///
/// This is a superset of FunctionTypeRepresentation. The common representations
/// must share an enum value.
///
/// TODO: The overlap of SILFunctionTypeRepresentation and
/// FunctionTypeRepresentation is a total hack necessitated by the way SIL
/// TypeLowering is currently written. We ought to refactor TypeLowering so that
/// it is not necessary to distinguish these cases.
enum class SILFunctionTypeRepresentation : uint8_t {
  /// A freestanding thick function.
  Thick = uint8_t(FunctionTypeRepresentation::Swift),
  
  /// A thick function that is represented as an Objective-C block.
  Block = uint8_t(FunctionTypeRepresentation::Block),
  
  /// A freestanding thin function that needs no context.
  Thin = uint8_t(FunctionTypeRepresentation::Thin),
  
  /// A C function pointer, which is thin and also uses the C calling
  /// convention.
  CFunctionPointer = uint8_t(FunctionTypeRepresentation::CFunctionPointer),

  /// The value of the greatest AST function representation.
  LastAST = CFunctionPointer,

  /// The value of the least SIL-only function representation.
  FirstSIL = 8,
  
  /// A Swift instance method.
  Method = FirstSIL,
  
  /// An Objective-C method.
  ObjCMethod,
  
  /// A Swift protocol witness.
  WitnessMethod,
  
  /// A closure invocation function that has not been bound to a context.
  Closure,
};

/// Can this calling convention result in a function being called indirectly
/// through the runtime.
inline bool canBeCalledIndirectly(SILFunctionTypeRepresentation rep) {
  switch (rep) {
  case SILFunctionTypeRepresentation::Thick:
  case SILFunctionTypeRepresentation::Thin:
  case SILFunctionTypeRepresentation::CFunctionPointer:
  case SILFunctionTypeRepresentation::Block:
  case SILFunctionTypeRepresentation::Closure:
    return false;
  case SILFunctionTypeRepresentation::ObjCMethod:
  case SILFunctionTypeRepresentation::Method:
  case SILFunctionTypeRepresentation::WitnessMethod:
    return true;
  }

  llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
}

/// Map a SIL function representation to the base language calling convention
/// it uses.
inline SILFunctionLanguage
getSILFunctionLanguage(SILFunctionTypeRepresentation rep) {
  switch (rep) {
  case SILFunctionTypeRepresentation::ObjCMethod:
  case SILFunctionTypeRepresentation::CFunctionPointer:
  case SILFunctionTypeRepresentation::Block:
    return SILFunctionLanguage::C;
  case SILFunctionTypeRepresentation::Thick:
  case SILFunctionTypeRepresentation::Thin:
  case SILFunctionTypeRepresentation::Method:
  case SILFunctionTypeRepresentation::WitnessMethod:
  case SILFunctionTypeRepresentation::Closure:
    return SILFunctionLanguage::Swift;
  }

  llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
}

/// AnyFunctionType - A function type has zero or more input parameters and a
/// single result. The result type may be a tuple. For example:
///   "(int) -> int" or "(a : int, b : int) -> (int, int)".
///
/// There are two kinds of function types:  monomorphic (FunctionType) and
/// polymorphic (GenericFunctionType). Both type families additionally can
/// be 'thin', indicating that a function value has no capture context and can be
/// represented at the binary level as a single function pointer.
class AnyFunctionType : public TypeBase {
  const Type Output;
  
public:
  using Representation = FunctionTypeRepresentation;

  class Param {
  public:
    explicit Param(Type t,
                   Identifier l = Identifier(),
                   ParameterTypeFlags f = ParameterTypeFlags())
        : Ty(t), Label(l), Flags(f) {
      assert(!t || !t->is<InOutType>() && "set flags instead");
    }

  private:
    /// The type of the parameter. For a variadic parameter, this is the
    /// element type.
    Type Ty;
    
    // The label associated with the parameter, if any.
    Identifier Label;
    
    /// Parameter specific flags.
    ParameterTypeFlags Flags = {};
    
  public:
    /// FIXME: Remove this. Return the formal type of the parameter in the
    /// function type, including the InOutType if there is one.
    ///
    /// For example, 'inout Int' => 'inout Int', 'Int...' => 'Int'.
    Type getOldType() const;

    /// Return the formal type of the parameter.
    ///
    /// For example, 'inout Int' => 'Int', 'Int...' => 'Int'.
    Type getPlainType() const { return Ty; }

    /// The type of the parameter when referenced inside the function body
    /// as an rvalue.
    ///
    /// For example, 'inout Int' => 'Int', 'Int...' => '[Int]'.
    Type getParameterType(bool forCanonical = false,
                          ASTContext *ctx = nullptr) const;

    bool hasLabel() const { return !Label.empty(); }
    Identifier getLabel() const { return Label; }
    
    ParameterTypeFlags getParameterFlags() const { return Flags; }

    /// Whether the parameter is varargs
    bool isVariadic() const { return Flags.isVariadic(); }
    
    /// Whether the parameter is marked '@autoclosure'
    bool isAutoClosure() const { return Flags.isAutoClosure(); }
    
    /// Whether the parameter is marked 'inout'
    bool isInOut() const { return Flags.isInOut(); }
    
    /// Whether the parameter is marked 'shared'
    bool isShared() const { return Flags.isShared(); }

    /// Whether the parameter is marked 'owned'
    bool isOwned() const { return Flags.isOwned(); }

    // SWIFT_ENABLE_TENSORFLOW
    /// Whether the parameter is marked '@nondiff'.
    bool isNonDifferentiable() const { return Flags.isNonDifferentiable(); }

    ValueOwnership getValueOwnership() const {
      return Flags.getValueOwnership();
    }

    bool operator==(Param const &b) const {
      return (Label == b.Label &&
              getPlainType()->isEqual(b.getPlainType()) &&
              Flags == b.Flags);
    }
    bool operator!=(Param const &b) const { return !(*this == b); }

    Param getWithoutLabel() const { return Param(Ty, Identifier(), Flags); }

    Param withType(Type newType) const { return Param(newType, Label, Flags); }
  };

  class CanParam : public Param {
    explicit CanParam(const Param &param) : Param(param) {}
  public:
    static CanParam getFromParam(const Param &param) { return CanParam(param); }

    CanType getOldType() const { return CanType(Param::getOldType()); }
    CanType getPlainType() const { return CanType(Param::getPlainType()); }
    CanType getParameterType() const {
      return CanType(Param::getParameterType(/*forCanonical*/ true));
    }
  };

  using CanParamArrayRef =
    ArrayRefView<Param,CanParam,CanParam::getFromParam,/*AccessOriginal*/true>;
  
  class CanYield;
  class Yield {
    Type Ty;
    YieldTypeFlags Flags;
  public:
    explicit Yield(Type type, YieldTypeFlags flags)
      : Ty(type), Flags(flags) {}

    Type getType() const { return Ty; }

    YieldTypeFlags getFlags() const { return Flags; }
    ValueOwnership getValueOwnership() const {
      return getFlags().getValueOwnership();
    }
    bool isInOut() const { return getFlags().isInOut(); }

    CanYield getCanonical() const;

    /// There are a number of places where it's convenient to re-use
    /// the call machinery, processing yields as if they were
    /// parameters of a call.  Return this reinterpreted as a parameter.
    Param asParam() const {
      return Param(getType(), Identifier(), getFlags().asParamFlags());
    }

    Yield subst(SubstitutionMap subs, SubstOptions options=None) const {
      return Yield(getType().subst(subs, options), getFlags());
    }

    bool operator==(const Yield &other) const {
      return getType()->isEqual(other.getType()) &&
             getFlags() == other.getFlags();
    }
    bool operator!=(const Yield &other) const {
      return !operator==(other);
    }
  };

  class CanYield : public Yield {
  public:
    explicit CanYield(CanType type, YieldTypeFlags flags)
      : Yield(type, flags) {}

    CanType getType() const { return CanType(Yield::getType()); }
    CanParam asParam() const { return CanParam::getFromParam(Yield::asParam());}

    CanYield subst(SubstitutionMap subs, SubstOptions options=None) const {
      return CanYield(getType().subst(subs, options)->getCanonicalType(),
                      getFlags());
    }
  };

  /// A class which abstracts out some details necessary for
  /// making a call.
  class ExtInfo {
    // If bits are added or removed, then TypeBase::AnyFunctionTypeBits
    // and NumMaskBits must be updated, and they must match.
    //
    //   SWIFT_ENABLE_TENSORFLOW
    //   |representation|noEscape|throws|differentiability|
    //   |    0 .. 3    |    4   |   5  |      6 .. 7     |
    //
    enum : unsigned {
      RepresentationMask           = 0xF << 0,
      NoEscapeMask                 = 1 << 4,
      ThrowsMask                   = 1 << 5,
      // SWIFT_ENABLE_TENSORFLOW
      DifferentiabilityMaskOffset  = 6,
      DifferentiabilityMask        = 0x3 << DifferentiabilityMaskOffset,
      NumDifferentiabilityMaskBits = 2,
      NumMaskBits                  = 8
    };

    unsigned Bits; // Naturally sized for speed.

    ExtInfo(unsigned Bits) : Bits(Bits) {}

    friend class AnyFunctionType;
    
  public:
    // Constructor with all defaults.
    ExtInfo() : Bits(0) {
      assert(getRepresentation() == Representation::Swift);
    }

    // Constructor for polymorphic type.
    ExtInfo(Representation Rep, bool Throws) {
      Bits = ((unsigned) Rep) | (Throws ? ThrowsMask : 0);
    }

    // Constructor with no defaults.
    ExtInfo(Representation Rep,
            bool IsNoEscape,
            // SWIFT_ENABLE_TENSORFLOW
            bool Throws, DifferentiabilityKind diffKind)
      : ExtInfo(Rep, Throws) {
      Bits |= (IsNoEscape ? NoEscapeMask : 0);
      // SWIFT_ENABLE_TENSORFLOW
      Bits |= ((unsigned)diffKind << DifferentiabilityMaskOffset)
              & DifferentiabilityMask;
    }

    bool isNoEscape() const { return Bits & NoEscapeMask; }
    bool throws() const { return Bits & ThrowsMask; }
    // SWIFT_ENABLE_TENSORFLOW
    bool isDifferentiable() const {
      return getDifferentiabilityKind() >= DifferentiabilityKind::Normal;
    }
    DifferentiabilityKind getDifferentiabilityKind() const {
      return DifferentiabilityKind((Bits & DifferentiabilityMask) >>
                                   DifferentiabilityMaskOffset);
    }
    Representation getRepresentation() const {
      unsigned rawRep = Bits & RepresentationMask;
      assert(rawRep <= unsigned(Representation::Last)
             && "unexpected SIL representation");
      return Representation(rawRep);
    }

    bool hasSelfParam() const {
      switch (getSILRepresentation()) {
      case SILFunctionTypeRepresentation::Thick:
      case SILFunctionTypeRepresentation::Block:
      case SILFunctionTypeRepresentation::Thin:
      case SILFunctionTypeRepresentation::CFunctionPointer:
      case SILFunctionTypeRepresentation::Closure:
        return false;
      case SILFunctionTypeRepresentation::ObjCMethod:
      case SILFunctionTypeRepresentation::Method:
      case SILFunctionTypeRepresentation::WitnessMethod:
        return true;
      }

      llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
    }

    /// True if the function representation carries context.
    bool hasContext() const {
      switch (getSILRepresentation()) {
      case SILFunctionTypeRepresentation::Thick:
      case SILFunctionTypeRepresentation::Block:
        return true;
      case SILFunctionTypeRepresentation::Thin:
      case SILFunctionTypeRepresentation::Method:
      case SILFunctionTypeRepresentation::ObjCMethod:
      case SILFunctionTypeRepresentation::WitnessMethod:
      case SILFunctionTypeRepresentation::CFunctionPointer:
      case SILFunctionTypeRepresentation::Closure:
        return false;
      }

      llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
    }
    
    // Note that we don't have setters. That is by design, use
    // the following with methods instead of mutating these objects.
    LLVM_NODISCARD
    ExtInfo withRepresentation(Representation Rep) const {
      return ExtInfo((Bits & ~RepresentationMask)
                     | (unsigned)Rep);
    }
    LLVM_NODISCARD
    ExtInfo withNoEscape(bool NoEscape = true) const {
      if (NoEscape)
        return ExtInfo(Bits | NoEscapeMask);
      else
        return ExtInfo(Bits & ~NoEscapeMask);
    }
    LLVM_NODISCARD
    ExtInfo withThrows(bool Throws = true) const {
      if (Throws)
        return ExtInfo(Bits | ThrowsMask);
      else
        return ExtInfo(Bits & ~ThrowsMask);
    }
    // SWIFT_ENABLE_TENSORFLOW
    LLVM_NODISCARD
    ExtInfo withDifferentiabilityKind(
        DifferentiabilityKind differentiability)
    const {
      return ExtInfo((Bits & ~DifferentiabilityMask) |
                     ((unsigned)differentiability <<
                      DifferentiabilityMaskOffset));
    }

    unsigned getFuncAttrKey() const {
      return Bits;
    }
    
    /// Put a SIL representation in the ExtInfo.
    ///
    /// SIL type lowering transiently generates AST function types with SIL
    /// representations. However, they shouldn't persist in the AST, and
    /// don't need to be parsed, printed, or serialized.
    ExtInfo withSILRepresentation(SILFunctionTypeRepresentation Rep) const {
      return ExtInfo((Bits & ~RepresentationMask)
                     | (unsigned)Rep);
    }
    
    SILFunctionTypeRepresentation getSILRepresentation() const {
      unsigned rawRep = Bits & RepresentationMask;
      return SILFunctionTypeRepresentation(rawRep);
    }

    bool operator==(ExtInfo Other) const {
      return Bits == Other.Bits;
    }
    bool operator!=(ExtInfo Other) const {
      return Bits != Other.Bits;
    }
  };

protected:
  AnyFunctionType(TypeKind Kind, const ASTContext *CanTypeContext,
                  Type Output, RecursiveTypeProperties properties,
                  unsigned NumParams, ExtInfo Info)
  : TypeBase(Kind, CanTypeContext, properties), Output(Output) {
    Bits.AnyFunctionType.ExtInfo = Info.Bits;
    Bits.AnyFunctionType.NumParams = NumParams;
    assert(Bits.AnyFunctionType.NumParams == NumParams && "Params dropped!");
    // The use of both assert() and static_assert() is intentional.
    assert(Bits.AnyFunctionType.ExtInfo == Info.Bits && "Bits were dropped!");
    static_assert(ExtInfo::NumMaskBits == NumAFTExtInfoBits,
                 "ExtInfo and AnyFunctionTypeBitfields must agree on bit size");
  }

public:
  /// Break an input type into an array of \c AnyFunctionType::Params.
  static void decomposeInput(Type type,
                             SmallVectorImpl<Param> &result);

  /// Take an array of parameters and turn it into an input type.
  ///
  /// The result type is only there as a way to extract the ASTContext when
  /// needed.
  static Type composeInput(ASTContext &ctx, ArrayRef<Param> params,
                           bool canonicalVararg);
  static Type composeInput(ASTContext &ctx, CanParamArrayRef params,
                           bool canonicalVararg) {
    return composeInput(ctx, params.getOriginalArray(), canonicalVararg);
  }

  /// Given two arrays of parameters determine if they are equal.
  static bool equalParams(ArrayRef<Param> a, ArrayRef<Param> b);

  /// Given two arrays of parameters determine if they are equal.
  static bool equalParams(CanParamArrayRef a, CanParamArrayRef b);

  /// Given an array of parameters and an array of labels of the
  /// same length, update each parameter to have the corresponding label.
  static void relabelParams(MutableArrayRef<Param> params,
                            ArrayRef<Identifier> labels);

  Type getResult() const { return Output; }
  ArrayRef<Param> getParams() const;
  unsigned getNumParams() const { return Bits.AnyFunctionType.NumParams; }

  GenericSignature getOptGenericSignature() const;
  
  ExtInfo getExtInfo() const {
    return ExtInfo(Bits.AnyFunctionType.ExtInfo);
  }

  /// Get the representation of the function type.
  Representation getRepresentation() const {
    return getExtInfo().getRepresentation();
  }

  // SWIFT_ENABLE_TENSORFLOW
  /// Given `indices` and `kind`, calculates the type of the corresponding
  /// autodiff derivative function.
  ///
  /// By default, if the original type has a self parameter list and parameter
  /// indices include self, the computed derivative function type will return a
  /// linear map taking/returning self's tangent *last* instead of first, for
  /// consistency with SIL.
  ///
  /// If `makeSelfParamFirst` is true, self's tangent is reordered to appear
  /// first. This should be used during type-checking, e.g. type-checking
  /// `@differentiable`, `@differentiating`, and `@transposing` attributes.
  ///
  /// \note The original function type (`self`) need not be `@differentiable`.
  /// The resulting function will preserve all `ExtInfo` of the original
  /// function, including `@differentiable`.
  AnyFunctionType *getAutoDiffDerivativeFunctionType(
      IndexSubset *indices, unsigned resultIndex,
      AutoDiffDerivativeFunctionKind kind,
      LookupConformanceFn lookupConformance,
      GenericSignature whereClauseGenericSignature = GenericSignature(),
      bool makeSelfParamFirst = false);

  /// Given the type of an autodiff derivative function, returns the
  /// corresponding original function type.
  AnyFunctionType *getAutoDiffOriginalFunctionType();
  
  /// Given the type of a transposing derivative function, returns the
  /// corresponding original function type.
  AnyFunctionType *
  getTransposeOriginalFunctionType(TransposingAttr *attr,
                                   IndexSubset *wrtParamIndices,
                                   bool wrtSelf);

  AnyFunctionType *getWithoutDifferentiability() const;

  /// True if the parameter declaration it is attached to is guaranteed
  /// to not persist the closure for longer than the duration of the call.
  bool isNoEscape() const {
    return getExtInfo().isNoEscape();
  }

  bool throws() const {
    return getExtInfo().throws();
  }
  
  // SWIFT_ENABLE_TENSORFLOW
  bool isDifferentiable() const {
    return getExtInfo().isDifferentiable();
  }
  DifferentiabilityKind getDifferentiabilityKind() const {
    return getExtInfo().getDifferentiabilityKind();
  }

  /// Returns a new function type exactly like this one but with the ExtInfo
  /// replaced.
  AnyFunctionType *withExtInfo(ExtInfo info) const;

  static void printParams(ArrayRef<Param> Params, raw_ostream &OS,
                          const PrintOptions &PO = PrintOptions());
  static void printParams(ArrayRef<Param> Params, ASTPrinter &Printer,
                          const PrintOptions &PO);

  static std::string getParamListAsString(ArrayRef<Param> Params,
                                          const PrintOptions &PO = PrintOptions());

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() >= TypeKind::First_AnyFunctionType &&
           T->getKind() <= TypeKind::Last_AnyFunctionType;
  }
};
BEGIN_CAN_TYPE_WRAPPER(AnyFunctionType, Type)
  using ExtInfo = AnyFunctionType::ExtInfo;
  using CanParamArrayRef = AnyFunctionType::CanParamArrayRef;

  static CanAnyFunctionType get(CanGenericSignature signature,
                                CanParamArrayRef params,
                                CanType result,
                                ExtInfo info = ExtInfo());

  CanGenericSignature getOptGenericSignature() const;

  CanParamArrayRef getParams() const {
    return CanParamArrayRef(getPointer()->getParams());
  }

  PROXY_CAN_TYPE_SIMPLE_GETTER(getResult)
  
  CanAnyFunctionType withExtInfo(ExtInfo info) const {
    return CanAnyFunctionType(getPointer()->withExtInfo(info));
  }
END_CAN_TYPE_WRAPPER(AnyFunctionType, Type)

inline AnyFunctionType::CanYield AnyFunctionType::Yield::getCanonical() const {
  return CanYield(getType()->getCanonicalType(), getFlags());
}

/// FunctionType - A monomorphic function type, specified with an arrow.
///
/// For example:
///   let x : (Float, Int) -> Int
class FunctionType final : public AnyFunctionType,
    public llvm::FoldingSetNode,
    private llvm::TrailingObjects<FunctionType, AnyFunctionType::Param> {
  friend TrailingObjects;
      
public:
  /// 'Constructor' Factory Function
  static FunctionType *get(ArrayRef<Param> params, Type result,
                           ExtInfo info = ExtInfo());

  // Retrieve the input parameters of this function type.
  ArrayRef<Param> getParams() const {
    return {getTrailingObjects<Param>(), getNumParams()};
  }

  void Profile(llvm::FoldingSetNodeID &ID) {
    Profile(ID, getParams(), getResult(), getExtInfo());
  }
  static void Profile(llvm::FoldingSetNodeID &ID,
                      ArrayRef<Param> params,
                      Type result,
                      ExtInfo info);

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Function;
  }
      
private:
  FunctionType(ArrayRef<Param> params, Type result, ExtInfo info,
               const ASTContext *ctx, RecursiveTypeProperties properties);
};
BEGIN_CAN_TYPE_WRAPPER(FunctionType, AnyFunctionType)
  static CanFunctionType get(CanParamArrayRef params, CanType result,
                             ExtInfo info = ExtInfo()) {
    auto fnType = FunctionType::get(params.getOriginalArray(), result, info);
    return cast<FunctionType>(fnType->getCanonicalType());
  }

  CanFunctionType withExtInfo(ExtInfo info) const {
    return CanFunctionType(cast<FunctionType>(getPointer()->withExtInfo(info)));
  }
END_CAN_TYPE_WRAPPER(FunctionType, AnyFunctionType)

/// Provides information about the parameter list of a given declaration, including whether each parameter
/// has a default argument.
struct ParameterListInfo {
  SmallBitVector defaultArguments;
  std::vector<Type> functionBuilderTypes;

public:
  ParameterListInfo() { }

  ParameterListInfo(ArrayRef<AnyFunctionType::Param> params,
                    const ValueDecl *paramOwner, bool skipCurriedSelf);

  /// Whether the parameter at the given index has a default argument.
  bool hasDefaultArgument(unsigned paramIdx) const;

  /// Retrieve the number of non-defaulted parameters.
  unsigned numNonDefaultedParameters() const {
    return defaultArguments.count();
  }

  /// Retrieve the number of parameters for which we have information.
  unsigned size() const { return defaultArguments.size(); }

  /// Retrieve the function builder type for the given parameter.
  Type getFunctionBuilderType(unsigned paramIdx) const;
};

/// Turn a param list into a symbolic and printable representation that does not
/// include the types, something like (: , b:, c:)
std::string getParamListAsString(ArrayRef<AnyFunctionType::Param> parameters);

/// Describes a generic function type.
///
/// A generic function type describes a function that is polymorphic with
/// respect to some set of generic parameters and the requirements placed
/// on those parameters and dependent member types thereof. The input and
/// output types of the generic function can be expressed in terms of those
/// generic parameters.
class GenericFunctionType final : public AnyFunctionType,
    public llvm::FoldingSetNode,
    private llvm::TrailingObjects<GenericFunctionType, AnyFunctionType::Param> {
  friend TrailingObjects;
      
  GenericSignature Signature;

  /// Construct a new generic function type.
  GenericFunctionType(GenericSignature sig,
                      ArrayRef<Param> params,
                      Type result,
                      ExtInfo info,
                      const ASTContext *ctx,
                      RecursiveTypeProperties properties);
      
public:
  /// Create a new generic function type.
  static GenericFunctionType *get(GenericSignature sig,
                                  ArrayRef<Param> params,
                                  Type result,
                                  ExtInfo info = ExtInfo());

  // Retrieve the input parameters of this function type.
  ArrayRef<Param> getParams() const {
    return {getTrailingObjects<Param>(), getNumParams()};
  }
      
  /// Retrieve the generic signature of this function type.
  GenericSignature getGenericSignature() const {
    return Signature;
  }
  
  /// Retrieve the generic parameters of this polymorphic function type.
  TypeArrayView<GenericTypeParamType> getGenericParams() const;

  /// Retrieve the requirements of this polymorphic function type.
  ArrayRef<Requirement> getRequirements() const;
                              
  /// Substitute the given generic arguments into this generic
  /// function type and return the resulting non-generic type.
  FunctionType *substGenericArgs(SubstitutionMap subs);
  FunctionType *substGenericArgs(llvm::function_ref<Type(Type)> substFn) const;

  void Profile(llvm::FoldingSetNodeID &ID) {
    Profile(ID, getGenericSignature(), getParams(), getResult(),
            getExtInfo());
  }
  static void Profile(llvm::FoldingSetNodeID &ID,
                      GenericSignature sig,
                      ArrayRef<Param> params,
                      Type result,
                      ExtInfo info);

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::GenericFunction;
  }
};

BEGIN_CAN_TYPE_WRAPPER(GenericFunctionType, AnyFunctionType)
  /// Create a new generic function type.
  static CanGenericFunctionType get(CanGenericSignature sig,
                                    CanParamArrayRef params,
                                    CanType result,
                                    ExtInfo info = ExtInfo()) {
    // Knowing that the argument types are independently canonical is
    // not sufficient to guarantee that the function type will be canonical.
    auto fnType = GenericFunctionType::get(sig, params.getOriginalArray(),
                                           result, info);
    return cast<GenericFunctionType>(fnType->getCanonicalType());
  }

  CanFunctionType substGenericArgs(SubstitutionMap subs) const;

  CanGenericSignature getGenericSignature() const {
    return CanGenericSignature(getPointer()->getGenericSignature());
  }
  
  ArrayRef<CanTypeWrapper<GenericTypeParamType>> getGenericParams() const {
    return getGenericSignature().getGenericParams();
  }

  CanGenericFunctionType withExtInfo(ExtInfo info) const {
    return CanGenericFunctionType(
                    cast<GenericFunctionType>(getPointer()->withExtInfo(info)));
  }
END_CAN_TYPE_WRAPPER(GenericFunctionType, AnyFunctionType)

inline CanAnyFunctionType
CanAnyFunctionType::get(CanGenericSignature signature, CanParamArrayRef params,
                        CanType result, ExtInfo extInfo) {
  if (signature) {
    return CanGenericFunctionType::get(signature, params, result, extInfo);
  } else {
    return CanFunctionType::get(params, result, extInfo);
  }
}

inline GenericSignature AnyFunctionType::getOptGenericSignature() const {
  if (auto genericFn = dyn_cast<GenericFunctionType>(this)) {
    return genericFn->getGenericSignature();
  } else {
    return nullptr;
  }
}

inline CanGenericSignature CanAnyFunctionType::getOptGenericSignature() const {
  if (auto genericFn = dyn_cast<GenericFunctionType>(*this)) {
    return genericFn.getGenericSignature();
  } else {
    return CanGenericSignature();
  }
}

/// Conventions for passing arguments as parameters.
enum class ParameterConvention {
  /// This argument is passed indirectly, i.e. by directly passing the address
  /// of an object in memory.  The callee is responsible for destroying the
  /// object.  The callee may assume that the address does not alias any valid
  /// object.
  Indirect_In,

  /// This argument is passed indirectly, i.e. by directly passing the address
  /// of an object in memory.  The callee must treat the object as read-only
  /// The callee may assume that the address does not alias any valid object.
  Indirect_In_Constant,

  /// This argument is passed indirectly, i.e. by directly passing the address
  /// of an object in memory.  The callee may not modify and does not destroy
  /// the object.
  Indirect_In_Guaranteed,

  /// This argument is passed indirectly, i.e. by directly passing the address
  /// of an object in memory.  The object is always valid, but the callee may
  /// assume that the address does not alias any valid object and reorder loads
  /// stores to the parameter as long as the whole object remains valid. Invalid
  /// single-threaded aliasing may produce inconsistent results, but should
  /// remain memory safe.
  Indirect_Inout,

  /// This argument is passed indirectly, i.e. by directly passing the address
  /// of an object in memory. The object is allowed to be aliased by other
  /// well-typed references, but is not allowed to be escaped. This is the
  /// convention used by mutable captures in @noescape closures.
  Indirect_InoutAliasable,

  /// This argument is passed directly.  Its type is non-trivial, and the callee
  /// is responsible for destroying it.
  Direct_Owned,

  /// This argument is passed directly.  Its type may be trivial, or it may
  /// simply be that the callee is not responsible for destroying it.  Its
  /// validity is guaranteed only at the instant the call begins.
  Direct_Unowned,

  /// This argument is passed directly.  Its type is non-trivial, and the caller
  /// guarantees its validity for the entirety of the call.
  Direct_Guaranteed,
};
// Check that the enum values fit inside Bits.SILFunctionType.
static_assert(unsigned(ParameterConvention::Direct_Guaranteed) < (1<<3),
              "fits in Bits.SILFunctionType and SILParameterInfo");

// Does this parameter convention require indirect storage? This reflects a
// SILFunctionType's formal (immutable) conventions, as opposed to the transient
// SIL conventions that dictate SILValue types.
inline bool isIndirectFormalParameter(ParameterConvention conv) {
  switch (conv) {
  case ParameterConvention::Indirect_In:
  case ParameterConvention::Indirect_In_Constant:
  case ParameterConvention::Indirect_Inout:
  case ParameterConvention::Indirect_InoutAliasable:
  case ParameterConvention::Indirect_In_Guaranteed:
    return true;

  case ParameterConvention::Direct_Unowned:
  case ParameterConvention::Direct_Guaranteed:
  case ParameterConvention::Direct_Owned:
    return false;
  }
  llvm_unreachable("covered switch isn't covered?!");
}
inline bool isConsumedParameter(ParameterConvention conv) {
  switch (conv) {
  case ParameterConvention::Indirect_In:
  case ParameterConvention::Indirect_In_Constant:
  case ParameterConvention::Direct_Owned:
    return true;

  case ParameterConvention::Indirect_Inout:
  case ParameterConvention::Indirect_InoutAliasable:
  case ParameterConvention::Direct_Unowned:
  case ParameterConvention::Direct_Guaranteed:
  case ParameterConvention::Indirect_In_Guaranteed:
    return false;
  }
  llvm_unreachable("bad convention kind");
}

/// Returns true if conv is a guaranteed parameter. This may look unnecessary
/// but this will allow code to generalize to handle Indirect_Guaranteed
/// parameters when they are added.
inline bool isGuaranteedParameter(ParameterConvention conv) {
  switch (conv) {
  case ParameterConvention::Direct_Guaranteed:
  case ParameterConvention::Indirect_In_Guaranteed:
    return true;

  case ParameterConvention::Indirect_Inout:
  case ParameterConvention::Indirect_InoutAliasable:
  case ParameterConvention::Indirect_In:
  case ParameterConvention::Indirect_In_Constant:
  case ParameterConvention::Direct_Unowned:
  case ParameterConvention::Direct_Owned:
    return false;
  }
  llvm_unreachable("bad convention kind");
}

/// SWIFT_ENABLE_TENSORFLOW
/// Determines whether a differentiable function type is differentiable with
/// respect to this parameter.
enum class SILParameterDifferentiability : unsigned {
  /// The function type is differentiable with respect to this parameter, or
  /// differentiability is not applicable because the function is not
  /// differentiable.
  DifferentiableOrNotApplicable,

  /// The function type is not differentiable with respect to this parameter.
  NotDifferentiable,
};

/// A parameter type and the rules for passing it.
class SILParameterInfo {
  llvm::PointerIntPair<CanType, 3, ParameterConvention> TypeAndConvention;

  // SWIFT_ENABLE_TENSORFLOW
  SILParameterDifferentiability Differentiability : 1;
public:
  SILParameterInfo() = default;//: Ty(), Convention((ParameterConvention)0) {}
  // SWIFT_ENABLE_TENSORFLOW
  SILParameterInfo(
      CanType type, ParameterConvention conv,
      SILParameterDifferentiability differentiability =
          SILParameterDifferentiability::DifferentiableOrNotApplicable)
    : TypeAndConvention(type, conv), Differentiability(differentiability) {
    assert(type->isLegalSILType() && "SILParameterInfo has illegal SIL type");
  }

  CanType getType() const {
    return TypeAndConvention.getPointer();
  }
  ParameterConvention getConvention() const {
    return TypeAndConvention.getInt();
  }
  // Does this parameter convention require indirect storage? This reflects a
  // SILFunctionType's formal (immutable) conventions, as opposed to the
  // transient SIL conventions that dictate SILValue types.
  bool isFormalIndirect() const {
    return isIndirectFormalParameter(getConvention());
  }

  bool isDirectGuaranteed() const {
    return getConvention() == ParameterConvention::Direct_Guaranteed;
  }

  bool isIndirectInGuaranteed() const {
    return getConvention() == ParameterConvention::Indirect_In_Guaranteed;
  }

  bool isIndirectInOut() const {
    return getConvention() == ParameterConvention::Indirect_Inout;
  }
  bool isIndirectMutating() const {
    return getConvention() == ParameterConvention::Indirect_Inout
        || getConvention() == ParameterConvention::Indirect_InoutAliasable;
  }

  /// True if this parameter is consumed by the callee, either
  /// indirectly or directly.
  bool isConsumed() const {
    return isConsumedParameter(getConvention());
  }

  /// Returns true if this parameter is guaranteed, either indirectly or
  /// directly.
  bool isGuaranteed() const {
    return isGuaranteedParameter(getConvention());
  }

  // SWIFT_ENABLE_TENSORFLOW
  SILParameterDifferentiability getDifferentiability() const {
    return Differentiability;
  }

  SILParameterInfo getWithDifferentiability(
      SILParameterDifferentiability differentiability) const {
    return SILParameterInfo(getType(), getConvention(), differentiability);
  }

  /// The SIL storage type determines the ABI for arguments based purely on the
  /// formal parameter conventions. The actual SIL type for the argument values
  /// may differ in canonical SIL. In particular, opaque values require indirect
  /// storage. Therefore they will be passed using an indirect formal
  /// convention, and this method will return an address type. However, in
  /// canonical SIL the opaque arguments might not have an address type.
  SILType getSILStorageType() const; // in SILFunctionConventions.h

  /// Return a version of this parameter info with the type replaced.
  SILParameterInfo getWithType(CanType type) const {
    // SWIFT_ENABLE_TENSORFLOW
    return SILParameterInfo(type, getConvention(), getDifferentiability());
  }

  /// Transform this SILParameterInfo by applying the user-provided
  /// function to its type.
  ///
  /// Note that this does not perform a recursive transformation like
  /// Type::transform does.
  template<typename F>
  SILParameterInfo map(const F &fn) const {
    return getWithType(fn(getType()));
  }

  void profile(llvm::FoldingSetNodeID &id) {
    id.AddPointer(getType().getPointer());
    id.AddInteger((unsigned)getConvention());
    // SWIFT_ENABLE_TENSORFLOW
    id.AddInteger((unsigned)getDifferentiability());
  }

  void dump() const;
  void print(llvm::raw_ostream &out,
             const PrintOptions &options = PrintOptions()) const;
  void print(ASTPrinter &Printer, const PrintOptions &Options) const;
  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &out,
                                       SILParameterInfo type) {
    type.print(out);
    return out;
  }

  bool operator==(SILParameterInfo rhs) const {
    // SWIFT_ENABLE_TENSORFLOW
    return getType() == rhs.getType() &&
           getConvention() == rhs.getConvention() &&
           getDifferentiability() == rhs.getDifferentiability();
  }
  bool operator!=(SILParameterInfo rhs) const {
    return !(*this == rhs);
  }
};

/// Conventions for returning values.
enum class ResultConvention {
  /// This result is returned indirectly, i.e. by passing the address
  /// of an uninitialized object in memory.  The callee is responsible
  /// for leaving an initialized object at this address.  The callee
  /// may assume that the address does not alias any valid object.
  Indirect,

  /// The caller is responsible for destroying this return value.
  /// Its type is non-trivial.
  Owned,

  /// The caller is not responsible for destroying this return value.
  /// Its type may be trivial, or it may simply be offered unsafely.
  /// It is valid at the instant of the return, but further operations
  /// may invalidate it.
  Unowned,

  /// The caller is not responsible for destroying this return value.
  /// The validity of the return value is dependent on the 'self' parameter,
  /// so it may be invalidated if that parameter is released.
  UnownedInnerPointer,
  
  /// This value has been (or may have been) returned autoreleased.
  /// The caller should make an effort to reclaim the autorelease.
  /// The type must be a class or class existential type, and this
  /// must be the only return value.
  Autoreleased,
};

// Does this result require indirect storage for the purpose of reabstraction?
inline bool isIndirectFormalResult(ResultConvention convention) {
  return convention == ResultConvention::Indirect;
}

/// A result type and the rules for returning it.
class SILResultInfo {
  llvm::PointerIntPair<CanType, 3, ResultConvention> TypeAndConvention;
public:
  SILResultInfo() = default;
  SILResultInfo(CanType type, ResultConvention conv)
    : TypeAndConvention(type, conv) {
    assert(type->isLegalSILType() && "SILResultInfo has illegal SIL type");
  }

  CanType getType() const {
    return TypeAndConvention.getPointer();
  }
  ResultConvention getConvention() const {
    return TypeAndConvention.getInt();
  }
  /// The SIL storage type determines the ABI for arguments based purely on the
  /// formal result conventions. The actual SIL type for the result values may
  /// differ in canonical SIL. In particular, opaque values require indirect
  /// storage. Therefore they will be returned using an indirect formal
  /// convention, and this method will return an address type. However, in
  /// canonical SIL the opaque results might not have an address type.
  SILType getSILStorageType() const; // in SILFunctionConventions.h

  /// Return a version of this result info with the type replaced.
  SILResultInfo getWithType(CanType type) const {
    return SILResultInfo(type, getConvention());
  }

  // Does this result convention require indirect storage? This reflects a
  // SILFunctionType's formal (immutable) conventions, as opposed to the
  // transient SIL conventions that dictate SILValue types.
  bool isFormalIndirect() const {
    return isIndirectFormalResult(getConvention());
  }
  bool isFormalDirect() const {
    return !isIndirectFormalResult(getConvention());
  }

  /// Transform this SILResultInfo by applying the user-provided
  /// function to its type.
  ///
  /// Note that this does not perform a recursive transformation like
  /// Type::transform does.
  template <typename F>
  SILResultInfo map(F &&fn) const {
    return getWithType(fn(getType()));
  }

  void profile(llvm::FoldingSetNodeID &id) {
    id.AddPointer(TypeAndConvention.getOpaqueValue());
  }

  void dump() const;
  void print(llvm::raw_ostream &out,
             const PrintOptions &options = PrintOptions()) const;
  void print(ASTPrinter &Printer, const PrintOptions &Options) const;
  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &out,
                                       SILResultInfo type) {
    type.print(out);
    return out;
  }

  ValueOwnershipKind
  getOwnershipKind(SILFunction &) const; // in SILType.cpp

  bool operator==(SILResultInfo rhs) const {
    return TypeAndConvention == rhs.TypeAndConvention;
  }
  bool operator!=(SILResultInfo rhs) const {
    return !(*this == rhs);
  }
};

using YieldConvention = ParameterConvention;

/// The type and convention of a value yielded from a yield-once or
/// yield-many coroutine.
class SILYieldInfo : public SILParameterInfo {
public:
  SILYieldInfo() {}
  SILYieldInfo(CanType type, YieldConvention conv)
    : SILParameterInfo(type, conv) {
  }

  SILYieldInfo getWithType(CanType type) const {
    return SILYieldInfo(type, getConvention());
  }

  template<typename F>
  SILYieldInfo map(const F &fn) const {
    return getWithType(fn(getType()));
  }
};

/// SILCoroutineKind - What kind of coroutine is this SILFunction?
enum class SILCoroutineKind : uint8_t {
  /// This function is not a coroutine.  It may have arbitrary normal
  /// results and may not have yield results.
  None,

  /// This function is a yield-once coroutine (used by e.g. accessors).
  /// It must not have normal results and may have arbitrary yield results.
  YieldOnce,

  /// This function is a yield-many coroutine (used by e.g. generators).
  /// It must not have normal results and may have arbitrary yield results.
  YieldMany,
};
  
class SILFunctionType;
typedef CanTypeWrapper<SILFunctionType> CanSILFunctionType;
class SILFunctionConventions;

/// SILFunctionType - The lowered type of a function value, suitable
/// for use by SIL.
///
/// This type is defined by the AST library because it must be capable
/// of appearing in secondary positions, e.g. within tuple and
/// function parameter and result types.
class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
    private llvm::TrailingObjects<SILFunctionType, SILParameterInfo,
                                  SILResultInfo> {
  friend TrailingObjects;

  size_t numTrailingObjects(OverloadToken<SILParameterInfo>) const {
    return NumParameters;
  }

  size_t numTrailingObjects(OverloadToken<SILResultInfo>) const {
    return hasErrorResult() ? 1 : 0;
  }

public:
  using Language = SILFunctionLanguage;
  using Representation = SILFunctionTypeRepresentation;

  /// A class which abstracts out some details necessary for
  /// making a call.
  class ExtInfo {
    // If bits are added or removed, then TypeBase::SILFunctionTypeBits
    // and NumMaskBits must be updated, and they must match.

    // SWIFT_ENABLE_TENSORFLOW
    //   |representation|pseudogeneric|noescape|differentiability|
    //   |    0 .. 3    |      4      |     5  |      6 .. 7     |
    //
    enum : unsigned {
      RepresentationMask           = 0xF << 0,
      PseudogenericMask            = 1 << 4,
      NoEscapeMask                 = 1 << 5,
      // SWIFT_ENABLE_TENSORFLOW
      DifferentiabilityMaskOffset  = 6,
      DifferentiabilityMask        = 0x3 << DifferentiabilityMaskOffset,
      NumDifferentiabilityMaskBits = 2,
      NumMaskBits                  = 8
    };
    unsigned Bits; // Naturally sized for speed.

    ExtInfo(unsigned Bits) : Bits(Bits) {}

    friend class SILFunctionType;
    
  public:
    // Constructor with all defaults.
    ExtInfo() : Bits(0) { }

    // Constructor for polymorphic type.
    // SWIFT_ENABLE_TENSORFLOW
    ExtInfo(Representation rep, bool isPseudogeneric, bool isNoEscape,
            DifferentiabilityKind diffKind) {
      Bits = ((unsigned) rep) |
             (isPseudogeneric ? PseudogenericMask : 0) |
             // SWIFT_ENABLE_TENSORFLOW
             (isNoEscape ? NoEscapeMask : 0) |
             (((unsigned)diffKind << DifferentiabilityMaskOffset)
              & DifferentiabilityMask);
    }

    /// Is this function pseudo-generic?  A pseudo-generic function
    /// is not permitted to dynamically depend on its type arguments.
    bool isPseudogeneric() const { return Bits & PseudogenericMask; }

    // Is this function guaranteed to be no-escape by the type system?
    bool isNoEscape() const { return Bits & NoEscapeMask; }
    
    // SWIFT_ENABLE_TENSORFLOW
    bool isDifferentiable() const {
      return getDifferentiabilityKind() >= DifferentiabilityKind::Normal;
    }
    
    DifferentiabilityKind getDifferentiabilityKind() const {
      return DifferentiabilityKind((Bits & DifferentiabilityMask) >>
                                   DifferentiabilityMaskOffset);
    }

    /// What is the abstract representation of this function value?
    Representation getRepresentation() const {
      return Representation(Bits & RepresentationMask);
    }
    Language getLanguage() const {
      return getSILFunctionLanguage(getRepresentation());
    }

    bool hasSelfParam() const {
      switch (getRepresentation()) {
      case Representation::Thick:
      case Representation::Block:
      case Representation::Thin:
      case Representation::CFunctionPointer:
      case Representation::Closure:
        return false;
      case Representation::ObjCMethod:
      case Representation::Method:
      case Representation::WitnessMethod:
        return true;
      }

      llvm_unreachable("Unhandled Representation in switch.");
    }

    /// True if the function representation carries context.
    bool hasContext() const {
      switch (getRepresentation()) {
      case Representation::Thick:
      case Representation::Block:
        return true;
      case Representation::Thin:
      case Representation::CFunctionPointer:
      case Representation::ObjCMethod:
      case Representation::Method:
      case Representation::WitnessMethod:
      case Representation::Closure:
        return false;
      }

      llvm_unreachable("Unhandled Representation in switch.");
    }
    
    // Note that we don't have setters. That is by design, use
    // the following with methods instead of mutating these objects.
    ExtInfo withRepresentation(Representation Rep) const {
      return ExtInfo((Bits & ~RepresentationMask)
                     | (unsigned)Rep);
    }
    ExtInfo withIsPseudogeneric(bool isPseudogeneric = true) const {
      if (isPseudogeneric)
        return ExtInfo(Bits | PseudogenericMask);
      else
        return ExtInfo(Bits & ~PseudogenericMask);
    }
    ExtInfo withNoEscape(bool NoEscape = true) const {
      if (NoEscape)
        return ExtInfo(Bits | NoEscapeMask);
      else
        return ExtInfo(Bits & ~NoEscapeMask);
    }
    // SWIFT_ENABLE_TENSORFLOW
    ExtInfo withDifferentiabilityKind(
        DifferentiabilityKind differentiability) const {
      return ExtInfo((Bits & ~DifferentiabilityMask) |
                     ((unsigned)differentiability <<
                      DifferentiabilityMaskOffset));
    }

    unsigned getFuncAttrKey() const {
      return Bits;
    }

    bool operator==(ExtInfo Other) const {
      return Bits == Other.Bits;
    }
    bool operator!=(ExtInfo Other) const {
      return Bits != Other.Bits;
    }
  };

private:
  unsigned NumParameters;

  // These are *normal* results if this is not a coroutine and *yield* results
  // otherwise.
  unsigned NumAnyResults : 16;         // Not including the ErrorResult.
  unsigned NumAnyIndirectFormalResults : 16; // Subset of NumAnyResults.

  // The layout of a SILFunctionType in memory is:
  //   SILFunctionType
  //   SILParameterInfo[NumParameters]
  //   SILResultInfo[isCoroutine() ? 0 : NumAnyResults]
  //   SILYieldInfo[isCoroutine() ? NumAnyResults : 0]
  //   SILResultInfo?    // if hasErrorResult()
  //   CanType?          // if !isCoro && NumAnyResults > 1, formal result cache
  //   CanType?          // if !isCoro && NumAnyResults > 1, all result cache

  CanGenericSignature GenericSig;
  Optional<ProtocolConformanceRef> WitnessMethodConformance;

  MutableArrayRef<SILParameterInfo> getMutableParameters() {
    return {getTrailingObjects<SILParameterInfo>(), NumParameters};
  }

  MutableArrayRef<SILResultInfo> getMutableResults() {
    auto *ptr = reinterpret_cast<SILResultInfo *>(getMutableParameters().end());
    return {ptr, getNumResults()};
  }

  MutableArrayRef<SILYieldInfo> getMutableYields() {
    auto *ptr = reinterpret_cast<SILYieldInfo *>(getMutableParameters().end());
    return {ptr, getNumYields()};
  }

  /// Return a pointer past the end of the formal results, whether they
  /// are yield-results or normal results.
  void *getEndOfFormalResults() {
    return isCoroutine() ? static_cast<void*>(getMutableYields().end())
                         : static_cast<void*>(getMutableResults().end());
  }

  SILResultInfo &getMutableErrorResult() {
    assert(hasErrorResult());
    return *reinterpret_cast<SILResultInfo*>(getEndOfFormalResults());
  }

  /// Return a pointer past the end of all of the results, including the
  /// error result if one is present.
  void *getEndOfAllResults() {
    void *end = getEndOfFormalResults();
    if (hasErrorResult())
      end = reinterpret_cast<char*>(end) + sizeof(SILResultInfo);
    return end;
  }

  /// Do we have slots for caches of the normal-result tuple type?
  bool hasResultCache() const {
    return NumAnyResults > 1 && !isCoroutine();
  }

  CanType &getMutableFormalResultsCache() const {
    assert(hasResultCache());
    auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfAllResults();
    return *reinterpret_cast<CanType*>(ptr);
  }

  CanType &getMutableAllResultsCache() const {
    assert(hasResultCache());
    auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfAllResults();
    return *(reinterpret_cast<CanType *>(ptr) + 1);
  }

  SILFunctionType(GenericSignature genericSig, ExtInfo ext,
                  SILCoroutineKind coroutineKind,
                  ParameterConvention calleeConvention,
                  ArrayRef<SILParameterInfo> params,
                  ArrayRef<SILYieldInfo> yieldResults,
                  ArrayRef<SILResultInfo> normalResults,
                  Optional<SILResultInfo> errorResult,
                  const ASTContext &ctx,
                  RecursiveTypeProperties properties,
                  Optional<ProtocolConformanceRef> witnessMethodConformance);

public:
  static CanSILFunctionType get(GenericSignature genericSig,
                                ExtInfo ext,
                                SILCoroutineKind coroutineKind,
                                ParameterConvention calleeConvention,
                                ArrayRef<SILParameterInfo> interfaceParams,
                                ArrayRef<SILYieldInfo> interfaceYields,
                                ArrayRef<SILResultInfo> interfaceResults,
                                Optional<SILResultInfo> interfaceErrorResult,
                                const ASTContext &ctx,
              Optional<ProtocolConformanceRef> witnessMethodConformance = None);

  /// Return a structurally-identical function type with a slightly tweaked
  /// ExtInfo.
  CanSILFunctionType getWithExtInfo(ExtInfo ext);

  /// Return a structurally-identical function type with a slightly tweaked
  /// representation.
  CanSILFunctionType getWithRepresentation(Representation repr);

  /// Given that this function type uses a C-language convention, return its
  /// formal semantic result type.
  ///
  /// C functions represented in SIL are always in one of three cases:
  ///   - no results at all; this corresponds to a void result type;
  ///   - a single direct result and no indirect results; or
  ///   - a single indirect result and no direct results.
  ///
  /// If the result is formally indirect, return the empty tuple.
  SILType getFormalCSemanticResult();

  /// Return the convention under which the callee is passed, if this
  /// is a thick non-block callee.
  ParameterConvention getCalleeConvention() const {
    return ParameterConvention(Bits.SILFunctionType.CalleeConvention);
  }
  bool isCalleeConsumed() const {
    return getCalleeConvention() == ParameterConvention::Direct_Owned;
  }
  bool isCalleeUnowned() const {
    return getCalleeConvention() == ParameterConvention::Direct_Unowned;
  }
  bool isCalleeGuaranteed() const {
    return getCalleeConvention() == ParameterConvention::Direct_Guaranteed;
  }

  /// Is this some kind of coroutine?
  bool isCoroutine() const {
    return getCoroutineKind() != SILCoroutineKind::None;
  }
  SILCoroutineKind getCoroutineKind() const {
    return SILCoroutineKind(Bits.SILFunctionType.CoroutineKind);
  }

  /// Return the array of all the yields.
  ArrayRef<SILYieldInfo> getYields() const {
    return const_cast<SILFunctionType *>(this)->getMutableYields();
  }
  unsigned getNumYields() const { return isCoroutine() ? NumAnyResults : 0; }

  /// Return the array of all result information. This may contain inter-mingled
  /// direct and indirect results.
  ArrayRef<SILResultInfo> getResults() const {
    return const_cast<SILFunctionType *>(this)->getMutableResults();
  }
  unsigned getNumResults() const { return isCoroutine() ? 0 : NumAnyResults; }

  /// Given that this function type has exactly one result, return it.
  /// This is a common situation when working with a function with a known
  /// signature.  It is *not* safe to assume that C functions satisfy
  /// this, because void functions have zero results.
  SILResultInfo getSingleResult() const {
    assert(getNumResults() == 1);
    return getResults()[0];
  }

  /// Given that this function type has exactly one formally direct result,
  /// return it. Some formal calling conventions only apply when a single
  /// direct result is present.
  SILResultInfo getSingleDirectFormalResult() const {
    assert(getNumDirectFormalResults() == 1);
    for (auto &result : getResults()) {
      if (!result.isFormalIndirect())
        return result;
    }
    llvm_unreachable("Missing indirect result");
  }

  // Get the number of results that require a formal indirect calling
  // convention regardless of whether SIL requires address types. Even if the
  // substituted SIL types match, a formal direct argument may not be passed
  // to a formal indirect parameter and vice-versa. Hence, the formally
  // indirect property, not the SIL indirect property, should be consulted to
  // determine whether function reabstraction is necessary.
  unsigned getNumIndirectFormalResults() const {
    return isCoroutine() ? 0 : NumAnyIndirectFormalResults;
  }
  /// Does this function have any formally indirect results?
  bool hasIndirectFormalResults() const {
    return getNumIndirectFormalResults() != 0;
  }
  unsigned getNumDirectFormalResults() const {
    return isCoroutine() ? 0 : NumAnyResults - NumAnyIndirectFormalResults;
  }

  struct IndirectFormalResultFilter {
    bool operator()(SILResultInfo result) const {
      return result.isFormalIndirect();
    }
  };
  using IndirectFormalResultIter =
      llvm::filter_iterator<const SILResultInfo *, IndirectFormalResultFilter>;
  using IndirectFormalResultRange = iterator_range<IndirectFormalResultIter>;

  /// A range of SILResultInfo for all formally indirect results.
  IndirectFormalResultRange getIndirectFormalResults() const {
    return llvm::make_filter_range(getResults(), IndirectFormalResultFilter());
  }

  struct DirectFormalResultFilter {
    bool operator()(SILResultInfo result) const {
      return !result.isFormalIndirect();
    }
  };
  using DirectFormalResultIter =
      llvm::filter_iterator<const SILResultInfo *, DirectFormalResultFilter>;
  using DirectFormalResultRange = iterator_range<DirectFormalResultIter>;

  /// A range of SILResultInfo for all formally direct results.
  DirectFormalResultRange getDirectFormalResults() const {
    return llvm::make_filter_range(getResults(), DirectFormalResultFilter());
  }

  /// Get a single non-address SILType that represents all formal direct
  /// results. The actual SIL result type of an apply instruction that calls
  /// this function depends on the current SIL stage and is known by
  /// SILFunctionConventions. It may be a wider tuple that includes formally
  /// indirect results.
  SILType getDirectFormalResultsType();

  /// Get a single non-address SILType for all SIL results regardless of whether
  /// they are formally indirect. The actual SIL result type of an apply
  /// instruction that calls this function depends on the current SIL stage and
  /// is known by SILFunctionConventions. It may be a narrower tuple that omits
  /// formally indirect results.
  SILType getAllResultsType();

  /// Does this function have a blessed Swift-native error result?
  bool hasErrorResult() const {
    return Bits.SILFunctionType.HasErrorResult;
  }
  SILResultInfo getErrorResult() const {
    return const_cast<SILFunctionType*>(this)->getMutableErrorResult();
  }
  Optional<SILResultInfo> getOptionalErrorResult() const {
    if (hasErrorResult()) {
      return getErrorResult();
    } else {
      return None;
    }
  }

  /// Returns the number of function parameters, not including any formally
  /// indirect results.
  unsigned getNumParameters() const { return NumParameters; }

  ArrayRef<SILParameterInfo> getParameters() const {
    return const_cast<SILFunctionType*>(this)->getMutableParameters();
  }

  /// Returns the 'self' parameter, assuming that this is the type of
  /// a method.
  SILParameterInfo getSelfParameter() const {
    return getParameters().back();
  }

  bool isPolymorphic() const { return !GenericSig.isNull(); }
  CanGenericSignature getGenericSignature() const { return GenericSig; }

  CanType getSelfInstanceType() const;

  // SWIFT_ENABLE_TENSORFLOW
  CanSILFunctionType getWithDifferentiability(
      DifferentiabilityKind kind, IndexSubset *parameterIndices);

  CanSILFunctionType getWithoutDifferentiability();

  /// Returns the type of the derivative function.
  CanSILFunctionType getAutoDiffDerivativeFunctionType(
      IndexSubset *parameterIndices, unsigned resultIndex,
      AutoDiffDerivativeFunctionKind kind, Lowering::TypeConverter &TC,
      LookupConformanceFn lookupConformance,
      CanGenericSignature derivativeFunctionGenericSignature = nullptr);

  /// Returns the type of the transpose function.
  CanSILFunctionType getAutoDiffTransposeFunctionType(
      IndexSubset *parameterIndices, Lowering::TypeConverter &TC,
      LookupConformanceFn lookupConformance,
      CanGenericSignature derivativeFunctionGenericSignature = nullptr);

  /// Returns a bit vector that specifices which parameters you can
  /// differentiate with respect to for this differentiable function type. (e.g.
  /// which parameters are not `@nondiff`). The function type must be
  /// differentiable.
  IndexSubset *getDifferentiationParameterIndices();

  /// If this is a @convention(witness_method) function with a class
  /// constrained self parameter, return the class constraint for the
  /// Self type.
  ClassDecl *getWitnessMethodClass() const;

  /// If this is a @convention(witness_method) function, return the conformance
  /// for which the method is a witness.
  ProtocolConformanceRef getWitnessMethodConformance() const {
    assert(getRepresentation() == Representation::WitnessMethod);
    return *WitnessMethodConformance;
  }

  /// If this is a @convention(witness_method) function, return the conformance
  /// for which the method is a witness, if it isn't that convention, return
  /// None.
  Optional<ProtocolConformanceRef> getWitnessMethodConformanceOrNone() const {
    return WitnessMethodConformance;
  }

  ExtInfo getExtInfo() const { return ExtInfo(Bits.SILFunctionType.ExtInfo); }

  /// Returns the language-level calling convention of the function.
  Language getLanguage() const {
    return getExtInfo().getLanguage();
  }

  bool hasSelfParam() const {
    return getExtInfo().hasSelfParam();
  }

  /// Get the representation of the function type.
  Representation getRepresentation() const {
    return getExtInfo().getRepresentation();
  }

  bool isPseudogeneric() const {
    return getExtInfo().isPseudogeneric();
  }

  bool isNoEscape() const {
    return getExtInfo().isNoEscape();
  }

  /// Thick swift noescape function types are trivial.
  bool isTrivialNoEscape() const {
    return isNoEscape() &&
           getRepresentation() == SILFunctionTypeRepresentation::Thick;
  }

  // SWIFT_ENABLE_TENSORFLOW
  DifferentiabilityKind getDifferentiabilityKind() const {
    return getExtInfo().getDifferentiabilityKind();
  }

  bool isDifferentiable() const {
    return getExtInfo().isDifferentiable();
  }

  bool isNoReturnFunction() const; // Defined in SILType.cpp

  class ABICompatibilityCheckResult {
    friend class SILFunctionType;

    enum innerty {
      None,
      DifferentFunctionRepresentations,
      ABIEscapeToNoEscapeConversion,
      DifferentNumberOfResults,
      DifferentReturnValueConventions,
      ABIIncompatibleReturnValues,
      DifferentErrorResultConventions,
      ABIIncompatibleErrorResults,
      DifferentNumberOfParameters,
      DifferingParameterConvention,
      ABIIncompatibleParameterType,
    } kind;
    Optional<uintptr_t> payload;

    ABICompatibilityCheckResult(innerty kind) : kind(kind) {}
    ABICompatibilityCheckResult(innerty kind, uintptr_t payload)
        : kind(kind), payload(payload) {}

  public:
    ABICompatibilityCheckResult() = delete;

    bool isCompatible() const { return kind == innerty::None; }
    bool isCompatibleUpToNoEscapeConversion() {
      return kind == innerty::None ||
             kind == innerty::ABIEscapeToNoEscapeConversion;
    }

    bool hasPayload() const { return payload.hasValue(); }
    uintptr_t getPayload() const { return payload.getValue(); }
    StringRef getMessage() const;
  };

  /// Returns no-error if this SILFunctionType is ABI compatible with \p
  /// other. Otherwise, it returns a true error with a message in
  /// std::error_code. This is only meant to be used in assertions. When
  /// assertions are disabled, this just returns true.
  ABICompatibilityCheckResult
  isABICompatibleWith(CanSILFunctionType other,
                      SILFunction *context = nullptr) const;

  CanSILFunctionType substGenericArgs(SILModule &silModule,
                                      SubstitutionMap subs);
  CanSILFunctionType substGenericArgs(SILModule &silModule,
                                      TypeSubstitutionFn subs,
                                      LookupConformanceFn conformances);

  void Profile(llvm::FoldingSetNodeID &ID) {
    Profile(ID, getGenericSignature(), getExtInfo(), getCoroutineKind(),
            getCalleeConvention(), getParameters(), getYields(),
            getResults(), getOptionalErrorResult(),
            getWitnessMethodConformanceOrNone());
  }
  static void Profile(llvm::FoldingSetNodeID &ID,
                      GenericSignature genericSig,
                      ExtInfo info,
                      SILCoroutineKind coroutineKind,
                      ParameterConvention calleeConvention,
                      ArrayRef<SILParameterInfo> params,
                      ArrayRef<SILYieldInfo> yields,
                      ArrayRef<SILResultInfo> results,
                      Optional<SILResultInfo> errorResult,
                      Optional<ProtocolConformanceRef> conformance);

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::SILFunction;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(SILFunctionType, Type)

class SILBoxType;
class SILLayout; // From SIL
class SILModule; // From SIL
typedef CanTypeWrapper<SILBoxType> CanSILBoxType;

/// The SIL-only type for boxes, which represent a reference to a (non-class)
/// refcounted value referencing an aggregate with a given lowered layout.
class SILBoxType final : public TypeBase, public llvm::FoldingSetNode
{
  SILLayout *Layout;
  SubstitutionMap Substitutions;

  SILBoxType(ASTContext &C,
             SILLayout *Layout, SubstitutionMap Substitutions);

public:
  static CanSILBoxType get(ASTContext &C,
                           SILLayout *Layout,
                           SubstitutionMap Substitutions);

  SILLayout *getLayout() const { return Layout; }
  SubstitutionMap getSubstitutions() const { return Substitutions; }

  // TODO: SILBoxTypes should be explicitly constructed in terms of specific
  // layouts. As a staging mechanism, we expose the old single-boxed-type
  // interface.
  
  static CanSILBoxType get(CanType BoxedType);

  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::SILBox;
  }
  
  /// Produce a profile of this box, for use in a folding set.
  static void Profile(llvm::FoldingSetNodeID &id,
                      SILLayout *Layout,
                      SubstitutionMap Args);
  
  /// Produce a profile of this box, for use in a folding set.
  void Profile(llvm::FoldingSetNodeID &id) {
    Profile(id, getLayout(), getSubstitutions());
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(SILBoxType, Type)

class SILBlockStorageType;
typedef CanTypeWrapper<SILBlockStorageType> CanSILBlockStorageType;
  
/// The SIL-only type @block_storage T, which represents the layout of an
/// on-stack block that captures a value of type T.
///
/// This type does not have to be able to appear positionally, unlike
/// SILFunctionType, so it is only parsed and defined within the SIL library.
class SILBlockStorageType : public TypeBase {
  CanType CaptureType;
  
  SILBlockStorageType(CanType CaptureType)
    : TypeBase(TypeKind::SILBlockStorage,
               &CaptureType->getASTContext(),
               CaptureType->getRecursiveProperties()),
      CaptureType(CaptureType) {}
  
public:
  static CanSILBlockStorageType get(CanType CaptureType);
                      
  CanType getCaptureType() const { return CaptureType; }
  // In SILType.h
  SILType getCaptureAddressType() const;
  
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::SILBlockStorage;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(SILBlockStorageType, Type)

/// A singleton 'token' type, which establishes a formal dependency
/// between two SIL nodes.  A token 'value' cannot be abstracted in
/// SIL: it cannot be returned, yielded, or passed as a function or
/// block argument.
class SILTokenType final : public TypeBase {
  friend class ASTContext;
  SILTokenType(const ASTContext &C)
    : TypeBase(TypeKind::SILToken, &C, RecursiveTypeProperties()) {}
public:
  // The singleton instance of this type is ASTContext::TheSILTokenType.

  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::SILToken;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(SILTokenType, Type)

/// A type with a special syntax that is always sugar for a library type. The
/// library type may have multiple base types. For unary syntax sugar, see
/// UnarySyntaxSugarType.
///
/// The prime examples are:
/// Arrays: [T] -> Array<T>
/// Optionals: T? -> Optional<T>
/// Dictionaries: [K : V]  -> Dictionary<K, V>
class SyntaxSugarType : public SugarType {
protected:
  // Syntax sugar types are never canonical.
  SyntaxSugarType(TypeKind K, const ASTContext &ctx,
                  RecursiveTypeProperties properties)
    : SugarType(K, &ctx, properties) {}

public:
  Type getImplementationType() const { return getSinglyDesugaredType(); }

  static bool classof(const TypeBase *T) {
    return T->getKind() >= TypeKind::First_SyntaxSugarType &&
           T->getKind() <= TypeKind::Last_SyntaxSugarType;
  }
};

/// A type with a special syntax that is always sugar for a library type that
/// wraps a single other type.
///
/// The prime examples are arrays ([T] -> Array<T>) and
/// optionals (T? -> Optional<T>).
class UnarySyntaxSugarType : public SyntaxSugarType {
  Type Base;

protected:
  UnarySyntaxSugarType(TypeKind K, const ASTContext &ctx, Type base,
                       RecursiveTypeProperties properties)
    : SyntaxSugarType(K, ctx, properties), Base(base) {}

public:
  Type getBaseType() const {
    return Base;
  }

  static bool classof(const TypeBase *T) {
    return T->getKind() >= TypeKind::First_UnarySyntaxSugarType &&
           T->getKind() <= TypeKind::Last_UnarySyntaxSugarType;
  }
};
  
/// The type [T], which is always sugar for a library type.
class ArraySliceType : public UnarySyntaxSugarType {
  ArraySliceType(const ASTContext &ctx, Type base,
                 RecursiveTypeProperties properties)
    : UnarySyntaxSugarType(TypeKind::ArraySlice, ctx, base, properties) {}

public:
  /// Return a uniqued array slice type with the specified base type.
  static ArraySliceType *get(Type baseTy);

  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::ArraySlice;
  }
};

/// The type T?, which is always sugar for a library type.
class OptionalType : public UnarySyntaxSugarType {
  OptionalType(const ASTContext &ctx,Type base,
               RecursiveTypeProperties properties)
    : UnarySyntaxSugarType(TypeKind::Optional, ctx, base, properties) {}

public:
  /// Return a uniqued optional type with the specified base type.
  static OptionalType *get(Type baseTy);

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Optional;
  }
};

/// The dictionary type [K : V], which is syntactic sugar for Dictionary<K, V>.
///
/// Example:
/// \code
/// var dict: [String : Int] = ["hello" : 0, "world" : 1]
/// \endcode
class DictionaryType : public SyntaxSugarType {
  Type Key;
  Type Value;

protected:
  // Syntax sugar types are never canonical.
  DictionaryType(const ASTContext &ctx, Type key, Type value,
                 RecursiveTypeProperties properties)
    : SyntaxSugarType(TypeKind::Dictionary, ctx, properties), 
      Key(key), Value(value) {}

public:
  /// Return a uniqued dictionary type with the specified key and value types.
  static DictionaryType *get(Type keyTy, Type valueTy);

  Type getKeyType() const { return Key; }
  Type getValueType() const { return Value; }

  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Dictionary;
  }

  static bool classof(const DictionaryType *T) {
    return true;
  }
};

/// ProtocolType - A protocol type describes an abstract interface implemented
/// by another type.
class ProtocolType : public NominalType {
public:
  /// Retrieve the type when we're referencing the given protocol.
  /// declaration.
  static ProtocolType *get(ProtocolDecl *D, Type Parent, const ASTContext &C);

  ProtocolDecl *getDecl() const {
    return reinterpret_cast<ProtocolDecl *>(NominalType::getDecl());
  }

  /// True if only classes may conform to the protocol.
  bool requiresClass();

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::Protocol;
  }

  /// Canonicalizes the given set of protocols by eliminating any mentions
  /// of protocols that are already covered by inheritance due to other entries
  /// in the protocol list, then sorting them in some stable order.
  static void canonicalizeProtocols(SmallVectorImpl<ProtocolDecl *> &protocols);

  /// Visit all of the protocols in the given list of protocols, along with their
  ///
  /// \param fn Visitor function called for each protocol (just once). If it
  /// returns \c true, the visit operation will abort and return \c true.
  ///
  /// \returns \c true if any invocation of \c fn returns \c true, and \c false
  /// otherwise.
  static bool visitAllProtocols(ArrayRef<ProtocolDecl *> protocols,
                                llvm::function_ref<bool(ProtocolDecl *)> fn);

private:
  friend class NominalTypeDecl;
  ProtocolType(ProtocolDecl *TheDecl, Type Parent, const ASTContext &Ctx,
               RecursiveTypeProperties properties);
};
BEGIN_CAN_TYPE_WRAPPER(ProtocolType, NominalType)
END_CAN_TYPE_WRAPPER(ProtocolType, NominalType)

/// ProtocolCompositionType - A type that composes some number of protocols
/// together to represent types that conform to all of the named protocols.
///
/// \code
/// protocol P { /* ... */ }
/// protocol Q { /* ... */ }
/// var x : P & Q
/// \endcode
///
/// Here, the type of x is a composition of the protocols 'P' and 'Q'.
///
/// The canonical form of a protocol composition type is based on a sorted (by
/// module and name), minimized (based on redundancy due to protocol
/// inheritance) protocol list. If the sorted, minimized list is a single
/// protocol, then the canonical type is that protocol type. Otherwise, it is
/// a composition of the protocols in that list.
class ProtocolCompositionType final : public TypeBase,
    public llvm::FoldingSetNode,
    private llvm::TrailingObjects<ProtocolCompositionType, Type> {
  friend TrailingObjects;
  
public:
  /// Retrieve an instance of a protocol composition type with the
  /// given set of members.
  static Type get(const ASTContext &C, ArrayRef<Type> Members,
                  bool HasExplicitAnyObject);
  
  /// Retrieve the set of members composed to create this type.
  ///
  /// For non-canonical types, this can contain classes, protocols and
  /// protocol compositions in any order. There can be at most one unique
  /// class constraint, either stated directly or as recursive member.
  ///
  /// In canonical types, this list will contain the superclass first if
  /// any, followed by zero or more protocols in a canonical sorted order,
  /// minimized to remove duplicates or protocols implied by inheritance.
  ///
  /// Note that the list of members is not sufficient to uniquely identify
  /// a protocol composition type; you also have to look at
  /// hasExplicitAnyObject().
  ArrayRef<Type> getMembers() const {
    return {getTrailingObjects<Type>(), Bits.ProtocolCompositionType.Count};
  }

  void Profile(llvm::FoldingSetNodeID &ID) {
    Profile(ID, getMembers(), hasExplicitAnyObject());
  }
  static void Profile(llvm::FoldingSetNodeID &ID,
                      ArrayRef<Type> Members,
                      bool HasExplicitAnyObject);

  /// True if the composition requires the concrete conforming type to
  /// be a class, either via a directly-stated superclass constraint or
  /// one of its member protocols being class-constrained.
  bool requiresClass();

  /// True if the class requirement is stated directly via '& AnyObject'.
  bool hasExplicitAnyObject() const {
    return Bits.ProtocolCompositionType.HasExplicitAnyObject;
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::ProtocolComposition;
  }
  
private:
  static ProtocolCompositionType *build(const ASTContext &C,
                                        ArrayRef<Type> Members,
                                        bool HasExplicitAnyObject);

  ProtocolCompositionType(const ASTContext *ctx, ArrayRef<Type> members,
                          bool hasExplicitAnyObject,
                          RecursiveTypeProperties properties)
    : TypeBase(TypeKind::ProtocolComposition, /*Context=*/ctx, properties) {
    Bits.ProtocolCompositionType.HasExplicitAnyObject = hasExplicitAnyObject;
    Bits.ProtocolCompositionType.Count = members.size();
    std::uninitialized_copy(members.begin(), members.end(),
                            getTrailingObjects<Type>());
  }
};
BEGIN_CAN_TYPE_WRAPPER(ProtocolCompositionType, Type)
END_CAN_TYPE_WRAPPER(ProtocolCompositionType, Type)

/// LValueType - An l-value is a handle to a physical object.  The
/// type of that object uniquely determines the type of an l-value
/// for it.
///
/// L-values are not fully first-class in Swift:
///
///  A type is said to "carry" an l-value if
///   - it is an l-value type or
///   - it is a tuple and at least one of its element types
///     carries an l-value.
///
/// The type of a function argument may carry an l-value.  This is done by
/// annotating the bound variable with InOutType.
///
/// The type of a return value, local variable, or field may not
/// carry an l-value.
///
/// When inferring a value type from an expression whose type
/// carries an l-value, the carried l-value types are converted
/// to their object type.
class LValueType : public TypeBase {
  Type ObjectTy;

  LValueType(Type objectTy, const ASTContext *canonicalContext,
             RecursiveTypeProperties properties)
    : TypeBase(TypeKind::LValue, canonicalContext, properties),
      ObjectTy(objectTy) {}

public:
  static LValueType *get(Type type);

  Type getObjectType() const { return ObjectTy; }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *type) {
    return type->getKind() == TypeKind::LValue;
  }
};
BEGIN_CAN_TYPE_WRAPPER(LValueType, Type)
  PROXY_CAN_TYPE_SIMPLE_GETTER(getObjectType)
  static CanLValueType get(CanType type) {
    return CanLValueType(LValueType::get(type));
  }
END_CAN_TYPE_WRAPPER(LValueType, Type)
  
/// InOutType - An inout qualified type is an argument to a function passed
/// with an explicit "Address of" operator.  It is read in and then written back
/// to after the callee function is done.  This also models the receiver of
/// @mutable methods on value types.
///
class InOutType : public TypeBase {
  Type ObjectTy;
  
  InOutType(Type objectTy, const ASTContext *canonicalContext,
            RecursiveTypeProperties properties)
  : TypeBase(TypeKind::InOut, canonicalContext, properties),
    ObjectTy(objectTy) {}
  
public:
  static InOutType *get(Type type);
  
  Type getObjectType() const { return ObjectTy; }
  
  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *type) {
    return type->getKind() == TypeKind::InOut;
  }
};
BEGIN_CAN_TYPE_WRAPPER(InOutType, Type)
PROXY_CAN_TYPE_SIMPLE_GETTER(getObjectType)
static CanInOutType get(CanType type) {
  return CanInOutType(InOutType::get(type));
}
END_CAN_TYPE_WRAPPER(InOutType, Type)


/// SubstitutableType - A reference to a type that can be substituted, i.e.,
/// an archetype or a generic parameter.
class SubstitutableType : public TypeBase {
protected:
  SubstitutableType(TypeKind K, const ASTContext *C,
                    RecursiveTypeProperties properties)
    : TypeBase(K, C, properties) { }

public:
  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() >= TypeKind::First_SubstitutableType &&
           T->getKind() <= TypeKind::Last_SubstitutableType;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(SubstitutableType, Type)

/// Common trailing objects for all ArchetypeType implementations, used to
/// store the constraints on the archetype.
template<typename Base, typename...AdditionalTrailingObjects>
using ArchetypeTrailingObjects = llvm::TrailingObjects<Base,
  ProtocolDecl *, Type, LayoutConstraint, AdditionalTrailingObjects...>;

class PrimaryArchetypeType;
class OpaqueTypeArchetypeType;
  
/// An archetype is a type that represents a runtime type that is
/// known to conform to some set of requirements.
///
/// Archetypes are used to represent generic type parameters and their
/// associated types, as well as the runtime type stored within an
/// existential container.
class ArchetypeType : public SubstitutableType,
                private llvm::trailing_objects_internal::TrailingObjectsBase
{
protected:
  // Each subclass has these same trailing objects and flags.
  size_t numTrailingObjects(OverloadToken<ProtocolDecl *>) const {
    return Bits.ArchetypeType.NumProtocols;
  }

  size_t numTrailingObjects(OverloadToken<Type>) const {
    return Bits.ArchetypeType.HasSuperclass ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<LayoutConstraint>) const {
    return Bits.ArchetypeType.HasLayoutConstraint ? 1 : 0;
  }
  Type InterfaceType;
  MutableArrayRef<std::pair<Identifier, Type>> NestedTypes;

  void populateNestedTypes() const;
  void resolveNestedType(std::pair<Identifier, Type> &nested) const;

  
  // Helper to get the trailing objects of one of the subclasses.
  template<typename Type>
  const Type *getSubclassTrailingObjects() const;
  
  template<typename Type>
  Type *getSubclassTrailingObjects() {
    const auto *constThis = this;
    return const_cast<Type*>(constThis->getSubclassTrailingObjects<Type>());
  }

public:
  /// Retrieve the name of this archetype.
  Identifier getName() const;

  /// Retrieve the fully-dotted name that should be used to display this
  /// archetype.
  std::string getFullName() const;

  /// Retrieve the interface type of this associated type, which will either
  /// be a GenericTypeParamType or a DependentMemberType.
  Type getInterfaceType() const { return InterfaceType; }

  /// getConformsTo - Retrieve the set of protocols to which this substitutable
  /// type shall conform.
  ArrayRef<ProtocolDecl *> getConformsTo() const {
    return { getSubclassTrailingObjects<ProtocolDecl *>(),
             static_cast<size_t>(Bits.ArchetypeType.NumProtocols) };
  }
  
  /// requiresClass - True if the type can only be substituted with class types.
  /// This is true if the type conforms to one or more class protocols or has
  /// a superclass constraint.
  bool requiresClass() const;

  /// Retrieve the superclass of this type, if such a requirement exists.
  Type getSuperclass() const {
    if (!Bits.ArchetypeType.HasSuperclass) return Type();

    return *getSubclassTrailingObjects<Type>();
  }

  /// Retrieve the layout constraint of this type, if such a requirement exists.
  LayoutConstraint getLayoutConstraint() const {
    if (!Bits.ArchetypeType.HasLayoutConstraint) return LayoutConstraint();

    return *getSubclassTrailingObjects<LayoutConstraint>();
  }

  /// Return true if the archetype has any requirements at all.
  bool hasRequirements() const {
    return !getConformsTo().empty() || getSuperclass();
  }

  /// Retrieve the nested type with the given name.
  Type getNestedType(Identifier Name) const;

  /// Retrieve the nested type with the given name, if it's already
  /// known.
  ///
  /// This is an implementation detail used by the generic signature builder.
  Optional<Type> getNestedTypeIfKnown(Identifier Name) const;

  /// Check if the archetype contains a nested type with the given name.
  bool hasNestedType(Identifier Name) const;

  /// Retrieve the known nested types of this archetype.
  ///
  /// Useful only for debugging dumps; all other queries should attempt to
  /// find a particular nested type by name, directly, or look at the
  /// protocols to which this archetype conforms.
  ArrayRef<std::pair<Identifier, Type>>
  getKnownNestedTypes(bool resolveTypes = true) const {
    return getAllNestedTypes(/*resolveTypes=*/false);
  }

  /// Retrieve the nested types of this archetype.
  ///
  /// \param resolveTypes Whether to eagerly resolve the nested types
  /// (defaults to \c true). Otherwise, the nested types might be
  /// null.
  ///
  /// FIXME: This operation should go away, because it breaks recursive
  /// protocol constraints.
  ArrayRef<std::pair<Identifier, Type>>
  getAllNestedTypes(bool resolveTypes = true) const;

  /// Set the nested types to a copy of the given array of
  /// archetypes.
  void setNestedTypes(ASTContext &Ctx,
                      ArrayRef<std::pair<Identifier, Type>> Nested);

  /// Register a nested type with the given name.
  void registerNestedType(Identifier name, Type nested);

  /// Return the root archetype parent of this archetype.
  ArchetypeType *getRoot() const;
  
  /// Get the generic environment this archetype lives in.
  GenericEnvironment *getGenericEnvironment() const;
  
  /// Get the protocol/class existential type that most closely represents the
  /// set of constraints on this archetype.
  ///
  /// Right now, this only considers constraints on the archetype itself, not
  /// any of its associated types, since those are the only kind of existential
  /// type we can represent.
  Type getExistentialType() const;

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() >= TypeKind::First_ArchetypeType
        && T->getKind() <= TypeKind::Last_ArchetypeType;
  }
protected:
  ArchetypeType(TypeKind Kind,
                const ASTContext &C,
                RecursiveTypeProperties properties,
                Type InterfaceType,
                ArrayRef<ProtocolDecl *> ConformsTo,
                Type Superclass, LayoutConstraint Layout);
};
BEGIN_CAN_TYPE_WRAPPER(ArchetypeType, SubstitutableType)
END_CAN_TYPE_WRAPPER(ArchetypeType, SubstitutableType)
  
/// An archetype that represents a primary generic argument inside the generic
/// context that binds it.
class PrimaryArchetypeType final : public ArchetypeType,
    private ArchetypeTrailingObjects<PrimaryArchetypeType>
{
  friend TrailingObjects;
  friend ArchetypeType;
                                  
  GenericEnvironment *Environment;

public:
  /// getNew - Create a new primary archetype with the given name.
  ///
  /// The ConformsTo array will be minimized then copied into the ASTContext
  /// by this routine.
  static CanTypeWrapper<PrimaryArchetypeType>
                        getNew(const ASTContext &Ctx,
                               GenericEnvironment *GenericEnv,
                               GenericTypeParamType *InterfaceType,
                               SmallVectorImpl<ProtocolDecl *> &ConformsTo,
                               Type Superclass, LayoutConstraint Layout);

  /// Retrieve the generic environment in which this archetype resides.
  GenericEnvironment *getGenericEnvironment() const {
    return Environment;
  }
      
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::PrimaryArchetype;
  }
private:
  PrimaryArchetypeType(const ASTContext &Ctx,
                       GenericEnvironment *GenericEnv,
                       Type InterfaceType,
                       ArrayRef<ProtocolDecl *> ConformsTo,
                       Type Superclass, LayoutConstraint Layout);
};
BEGIN_CAN_TYPE_WRAPPER(PrimaryArchetypeType, ArchetypeType)
END_CAN_TYPE_WRAPPER(PrimaryArchetypeType, ArchetypeType)

/// An archetype that represents an opaque type.
class OpaqueTypeArchetypeType final : public ArchetypeType,
    public llvm::FoldingSetNode,
    private ArchetypeTrailingObjects<OpaqueTypeArchetypeType>
{
  friend TrailingObjects;
  friend ArchetypeType;
  friend GenericSignatureBuilder;

  /// The declaration that defines the opaque type.
  OpaqueTypeDecl *OpaqueDecl;
  /// The substitutions into the interface signature of the opaque type.
  SubstitutionMap Substitutions;
  
  /// A GenericEnvironment with this opaque archetype bound to the interface
  /// type of the output type from the OpaqueDecl.
  GenericEnvironment *Environment;
  
public:
  /// Get 
  
  /// Get an opaque archetype representing the underlying type of the given
  /// opaque type decl.
  static OpaqueTypeArchetypeType *get(OpaqueTypeDecl *Decl,
                                      SubstitutionMap Substitutions);
  
  OpaqueTypeDecl *getDecl() const {
    return OpaqueDecl;
  }
  SubstitutionMap getSubstitutions() const {
    return Substitutions;
  }
  
  /// Get the generic signature used to build out this archetype. This is
  /// equivalent to the OpaqueTypeDecl's interface generic signature, with
  /// all of the generic parameters aside from the opaque type's interface
  /// type same-type-constrained to their substitutions for this type.
  GenericSignature getBoundSignature() const;
  
  /// Get a generic environment that has this opaque archetype bound within it.
  GenericEnvironment *getGenericEnvironment() const {
    return Environment;
  }
  
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::OpaqueTypeArchetype;
  }
  
  /// Get the ordinal of the type within the declaration's opaque signature.
  ///
  /// If a method declared its return type as:
  ///
  ///   func foo() -> (some P, some Q)
  ///
  /// then the underlying type of `some P` would be ordinal 0, and `some Q` would be ordinal 1.
  unsigned getOrdinal() const {
    // TODO: multiple opaque types
    return 0;
  }
  
  static void Profile(llvm::FoldingSetNodeID &ID,
                      OpaqueTypeDecl *OpaqueDecl,
                      SubstitutionMap Substitutions);
  
  void Profile(llvm::FoldingSetNodeID &ID) {
    Profile(ID, getDecl(), getSubstitutions());
  };
  
private:
  OpaqueTypeArchetypeType(OpaqueTypeDecl *OpaqueDecl,
                          SubstitutionMap Substitutions,
                          RecursiveTypeProperties Props,
                          Type InterfaceType,
                          ArrayRef<ProtocolDecl*> ConformsTo,
                          Type Superclass, LayoutConstraint Layout);
};
BEGIN_CAN_TYPE_WRAPPER(OpaqueTypeArchetypeType, ArchetypeType)
END_CAN_TYPE_WRAPPER(OpaqueTypeArchetypeType, ArchetypeType)

/// A function object that can be used as a \c TypeSubstitutionFn and
/// \c LookupConformanceFn for \c Type::subst style APIs to map opaque
/// archetypes with underlying types visible at a given resilience expansion
/// to their underlying types.
class ReplaceOpaqueTypesWithUnderlyingTypes {
public:
  ModuleDecl *contextModule;
  ResilienceExpansion contextExpansion;
  ReplaceOpaqueTypesWithUnderlyingTypes(ModuleDecl *contextModule,
                                        ResilienceExpansion contextExpansion)
      : contextModule(contextModule), contextExpansion(contextExpansion) {}

  /// TypeSubstitutionFn
  Type operator()(SubstitutableType *maybeOpaqueType) const;

  /// LookupConformanceFn
  Optional<ProtocolConformanceRef> operator()(CanType maybeOpaqueType,
                                              Type replacementType,
                                              ProtocolDecl *protocol) const;

  bool shouldPerformSubstitution(OpaqueTypeDecl *opaque) const;

  static bool shouldPerformSubstitution(OpaqueTypeDecl *opaque,
                                        ModuleDecl *contextModule,
                                        ResilienceExpansion contextExpansion);
};

/// An archetype that represents the dynamic type of an opened existential.
class OpenedArchetypeType final : public ArchetypeType,
    private ArchetypeTrailingObjects<OpenedArchetypeType>
{
  friend TrailingObjects;
  friend ArchetypeType;
  
  mutable GenericEnvironment *Environment = nullptr;
  TypeBase *Opened;
  UUID ID;
public:
  /// Create a new archetype that represents the opened type
  /// of an existential value.
  ///
  /// \param existential The existential type to open.
  ///
  /// \param knownID When non-empty, the known ID of the archetype. When empty,
  /// a fresh archetype with a unique ID will be opened.
  static CanTypeWrapper<OpenedArchetypeType>
                        get(Type existential,
                            Optional<UUID> knownID = None);

  /// Create a new archetype that represents the opened type
  /// of an existential value.
  ///
  /// \param existential The existential type or existential metatype to open.
  static CanType getAny(Type existential);

  /// Retrieve the ID number of this opened existential.
  UUID getOpenedExistentialID() const { return ID; }
  
  /// Retrieve the opened existential type
  Type getOpenedExistentialType() const {
    return Opened;
  }
  
  /// Get a generic environment with this opened type bound to its generic
  /// parameter.
  GenericEnvironment *getGenericEnvironment() const;
  
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::OpenedArchetype;
  }
  
private:
  OpenedArchetypeType(const ASTContext &Ctx,
                      Type Existential,
                      ArrayRef<ProtocolDecl *> ConformsTo, Type Superclass,
                      LayoutConstraint Layout, UUID uuid);
};
BEGIN_CAN_TYPE_WRAPPER(OpenedArchetypeType, ArchetypeType)
END_CAN_TYPE_WRAPPER(OpenedArchetypeType, ArchetypeType)

/// An archetype that is a nested associated type of another archetype.
class NestedArchetypeType final : public ArchetypeType,
    private ArchetypeTrailingObjects<NestedArchetypeType>
{
  friend TrailingObjects;
  friend ArchetypeType;
  
  ArchetypeType *Parent;

public:
  /// getNew - Create a new nested archetype with the given associated type.
  ///
  /// The ConformsTo array will be copied into the ASTContext by this routine.
  static CanTypeWrapper<NestedArchetypeType>
  getNew(const ASTContext &Ctx, ArchetypeType *Parent,
         DependentMemberType *InterfaceType,
         SmallVectorImpl<ProtocolDecl *> &ConformsTo,
         Type Superclass, LayoutConstraint Layout);

  /// Retrieve the parent of this archetype, or null if this is a
  /// primary archetype.
  ArchetypeType *getParent() const {
    return Parent;
  }
  
  AssociatedTypeDecl *getAssocType() const;

  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::NestedArchetype;
  }
  
  DependentMemberType *getInterfaceType() const {
    return cast<DependentMemberType>(InterfaceType.getPointer());
  }

private:
  NestedArchetypeType(const ASTContext &Ctx,
                     ArchetypeType *Parent,
                     Type InterfaceType,
                     ArrayRef<ProtocolDecl *> ConformsTo,
                     Type Superclass, LayoutConstraint Layout);
};
BEGIN_CAN_TYPE_WRAPPER(NestedArchetypeType, ArchetypeType)
CanArchetypeType getParent() const {
  return CanArchetypeType(getPointer()->getParent());
}
END_CAN_TYPE_WRAPPER(NestedArchetypeType, ArchetypeType)

template<typename Type>
const Type *ArchetypeType::getSubclassTrailingObjects() const {
  if (auto contextTy = dyn_cast<PrimaryArchetypeType>(this)) {
    return contextTy->getTrailingObjects<Type>();
  }
  if (auto opaqueTy = dyn_cast<OpaqueTypeArchetypeType>(this)) {
    return opaqueTy->getTrailingObjects<Type>();
  }
  if (auto openedTy = dyn_cast<OpenedArchetypeType>(this)) {
    return openedTy->getTrailingObjects<Type>();
  }
  if (auto childTy = dyn_cast<NestedArchetypeType>(this)) {
    return childTy->getTrailingObjects<Type>();
  }
  llvm_unreachable("unhandled ArchetypeType subclass?");
}
  
/// Describes the type of a generic parameter.
///
/// \sa GenericTypeParamDecl
class GenericTypeParamType : public SubstitutableType {
  using DepthIndexTy = llvm::PointerEmbeddedInt<unsigned, 31>;

  /// The generic type parameter or depth/index.
  llvm::PointerUnion<GenericTypeParamDecl *, DepthIndexTy> ParamOrDepthIndex;

public:
  /// Retrieve a generic type parameter at the given depth and index.
  static GenericTypeParamType *get(unsigned depth, unsigned index,
                                   const ASTContext &ctx);

  /// Retrieve the declaration of the generic type parameter, or null if
  /// there is no such declaration.
  GenericTypeParamDecl *getDecl() const {
    return ParamOrDepthIndex.dyn_cast<GenericTypeParamDecl *>();
  }

  /// Get the name of the generic type parameter.
  Identifier getName() const;
  
  /// The depth of this generic type parameter, i.e., the number of outer
  /// levels of generic parameter lists that enclose this type parameter.
  ///
  /// \code
  /// struct X<T> {
  ///   func f<U>() { }
  /// }
  /// \endcode
  ///
  /// Here 'T' has depth 0 and 'U' has depth 1. Both have index 0.
  unsigned getDepth() const;

  /// The index of this generic type parameter within its generic parameter
  /// list.
  ///
  /// \code
  /// struct X<T, U> {
  ///   func f<V>() { }
  /// }
  /// \endcode
  ///
  /// Here 'T' and 'U' have indexes 0 and 1, respectively. 'V' has index 0.
  unsigned getIndex() const;

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::GenericTypeParam;
  }

private:
  friend class GenericTypeParamDecl;

  explicit GenericTypeParamType(GenericTypeParamDecl *param)
    : SubstitutableType(TypeKind::GenericTypeParam, nullptr,
                        RecursiveTypeProperties::HasTypeParameter),
      ParamOrDepthIndex(param) { }

  explicit GenericTypeParamType(unsigned depth,
                                unsigned index,
                                const ASTContext &ctx)
    : SubstitutableType(TypeKind::GenericTypeParam, &ctx,
                        RecursiveTypeProperties::HasTypeParameter),
      ParamOrDepthIndex(depth << 16 | index) { }
};
BEGIN_CAN_TYPE_WRAPPER(GenericTypeParamType, SubstitutableType)
  static CanGenericTypeParamType get(unsigned depth, unsigned index,
                                     const ASTContext &C) {
    return CanGenericTypeParamType(GenericTypeParamType::get(depth, index, C));
  }
END_CAN_TYPE_WRAPPER(GenericTypeParamType, SubstitutableType)

/// A type that refers to a member type of some type that is dependent on a
/// generic parameter.
class DependentMemberType : public TypeBase {
  Type Base;
  llvm::PointerUnion<Identifier, AssociatedTypeDecl *> NameOrAssocType;

  DependentMemberType(Type base, Identifier name, const ASTContext *ctx,
                      RecursiveTypeProperties properties)
    : TypeBase(TypeKind::DependentMember, ctx, properties),
      Base(base), NameOrAssocType(name) { }

  DependentMemberType(Type base, AssociatedTypeDecl *assocType,
                      const ASTContext *ctx,
                      RecursiveTypeProperties properties)
    : TypeBase(TypeKind::DependentMember, ctx, properties),
      Base(base), NameOrAssocType(assocType) { }

public:
  static DependentMemberType *get(Type base, Identifier name);
  static DependentMemberType *get(Type base, AssociatedTypeDecl *assocType);

  /// Retrieve the base type.
  Type getBase() const { return Base; }

  /// Retrieve the name of the member type.
  Identifier getName() const;

  /// Retrieve the associated type referenced as a member.
  ///
  /// The associated type will only be available after successful type checking.
  AssociatedTypeDecl *getAssocType() const {
    return NameOrAssocType.dyn_cast<AssociatedTypeDecl *>();
  }
  
  /// Substitute the base type, looking up our associated type in it if it is
  /// non-dependent. Returns null if the member could not be found in the new
  /// base.
  Type substBaseType(ModuleDecl *M, Type base);

  /// Substitute the base type, looking up our associated type in it if it is
  /// non-dependent. Returns null if the member could not be found in the new
  /// base.
  Type substBaseType(Type base, LookupConformanceFn lookupConformance);

  /// Substitute the root generic type, looking up the chain of associated types.
  /// Returns null if the member could not be found in the new root.
  Type substRootParam(Type newRoot, LookupConformanceFn lookupConformance);

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::DependentMember;
  }
};
BEGIN_CAN_TYPE_WRAPPER(DependentMemberType, Type)
  static CanDependentMemberType get(CanType base, AssociatedTypeDecl *assocType,
                                    const ASTContext &C) {
    return CanDependentMemberType(DependentMemberType::get(base, assocType));
  }

  PROXY_CAN_TYPE_SIMPLE_GETTER(getBase)
END_CAN_TYPE_WRAPPER(DependentMemberType, Type)

/// The storage type of a variable with non-strong reference
/// ownership semantics.
///
/// The referent type always satisfies allowsOwnership().
///
/// These types may appear in the AST only as the type of a variable;
/// getTypeOfReference strips this layer from the formal type of a
/// reference to the variable.  However, it is extremely useful to
/// represent this as a distinct type in SIL and IR-generation.
class ReferenceStorageType : public TypeBase {
protected:
  ReferenceStorageType(TypeKind kind, Type referent, const ASTContext *C,
                       RecursiveTypeProperties properties)
    : TypeBase(kind, C, properties), Referent(referent) {}

private:
  Type Referent;
public:
  static ReferenceStorageType *get(Type referent, ReferenceOwnership ownership,
                                   const ASTContext &C);

  Type getReferentType() const { return Referent; }
  ReferenceOwnership getOwnership() const {
    switch (getKind()) {
#define REF_STORAGE(Name, ...) \
    case TypeKind::Name##Storage: \
      return ReferenceOwnership::Name;
#include "swift/AST/ReferenceStorage.def"
    default:
      llvm_unreachable("Unhandled reference storage type");
    }
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() >= TypeKind::First_ReferenceStorageType &&
           T->getKind() <= TypeKind::Last_ReferenceStorageType;
  }
};
BEGIN_CAN_TYPE_WRAPPER(ReferenceStorageType, Type)
static CanReferenceStorageType get(CanType referent,
                                   ReferenceOwnership ownership) {
  return CanReferenceStorageType(ReferenceStorageType::get(
      referent, ownership, referent->getASTContext()));
  }
  PROXY_CAN_TYPE_SIMPLE_GETTER(getReferentType)
END_CAN_TYPE_WRAPPER(ReferenceStorageType, Type)

#define REF_STORAGE_HELPER(Name, isLoadable) \
class Name##StorageType : public ReferenceStorageType { \
  friend class ReferenceStorageType; \
  Name##StorageType(Type referent, const ASTContext *C, \
                    RecursiveTypeProperties properties) \
    : ReferenceStorageType(TypeKind::Name##Storage, referent, C, properties){} \
public: \
  static Name##StorageType *get(Type referent, const ASTContext &C) { \
    return static_cast<Name##StorageType *>( \
        ReferenceStorageType::get(referent, ReferenceOwnership::Name, C)); \
  } \
  isLoadable \
  static bool classof(const TypeBase *T) { \
    return T->getKind() == TypeKind::Name##Storage; \
  } \
}; \
BEGIN_CAN_TYPE_WRAPPER(Name##StorageType, ReferenceStorageType) \
  static Can##Name##StorageType get(CanType referent) { \
    return cast<Name##StorageType>( \
        CanType(Name##StorageType::get(referent, referent->getASTContext()))); \
  } \
END_CAN_TYPE_WRAPPER(Name##StorageType, ReferenceStorageType)
#define UNCHECKED_REF_STORAGE(Name, ...) \
  REF_STORAGE_HELPER(Name, )
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
  REF_STORAGE_HELPER(Name, )
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
  REF_STORAGE_HELPER(Name, )
#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
  REF_STORAGE_HELPER(Name, bool isLoadable(ResilienceExpansion resilience) const;)
#include "swift/AST/ReferenceStorage.def"
#undef REF_STORAGE_HELPER

/// A type variable used during type checking.
class alignas(1 << TypeVariableAlignInBits)
TypeVariableType : public TypeBase {
  // Note: We can't use llvm::TrailingObjects here because the trailing object
  // type is opaque.

  TypeVariableType(const ASTContext &C, unsigned ID)
    : TypeBase(TypeKind::TypeVariable, &C,
               RecursiveTypeProperties::HasTypeVariable) {
    // Note: the ID may overflow (current limit is 2^20 - 1).
    Bits.TypeVariableType.ID = ID;
    if (Bits.TypeVariableType.ID != ID) {
      llvm::report_fatal_error("Type variable id overflow");
    }
  }

  class Implementation;
  
public:
 
  /// Create a new type variable whose implementation is constructed
  /// with the given arguments.
  template<typename ...Args>
  static TypeVariableType *getNew(const ASTContext &C, unsigned ID,
                                  Args &&...args);
  
  /// Retrieve the implementation data corresponding to this type
  /// variable.
  ///
  /// The contents of the implementation data for this type are hidden in the
  /// details of the constraint solver used for type checking.
  Implementation &getImpl() {
    return *reinterpret_cast<Implementation *>(this + 1);
  }

  /// Retrieve the implementation data corresponding to this type
  /// variable.
  ///
  /// The contents of the implementation data for this type are hidden in the
  /// details of the constraint solver used for type checking.
  const Implementation &getImpl() const {
    return *reinterpret_cast<const Implementation *>(this + 1);
  }

  /// Access the implementation object for this type variable.
  Implementation *operator->() {
    return reinterpret_cast<Implementation *>(this + 1);
  }

  /// Type variable IDs are not globally unique and are
  /// used in equivalence class merging (so representative
  /// is always a type variable with smaller id), as well
  /// as a visual aid when dumping AST.
  unsigned getID() const { return Bits.TypeVariableType.ID; }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const TypeBase *T) {
    return T->getKind() == TypeKind::TypeVariable;
  }
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(TypeVariableType, Type)

inline bool TypeBase::isTypeVariableOrMember() {
  if (is<TypeVariableType>())
    return true;

  if (auto depMemTy = getAs<DependentMemberType>())
    return depMemTy->getBase()->isTypeVariableOrMember();

  return false;
}

inline bool TypeBase::isTypeParameter() {
  if (is<GenericTypeParamType>())
    return true;

  if (auto depMemTy = getAs<DependentMemberType>())
    return depMemTy->getBase()->isTypeParameter();

  return false;
}

inline bool TypeBase::isMaterializable() {
  if (hasLValueType())
    return false;

  if (is<InOutType>())
    return false;

  if (auto *TTy = getAs<TupleType>())
    return !TTy->hasElementWithOwnership();

  return true;
}

inline GenericTypeParamType *TypeBase::getRootGenericParam() {
  Type t(this);

  while (auto *memberTy = t->getAs<DependentMemberType>())
    t = memberTy->getBase();

  return t->castTo<GenericTypeParamType>();
}

inline bool TypeBase::isExistentialType() {
  return getCanonicalType().isExistentialType();
}

inline bool TypeBase::isAnyExistentialType() {
  return getCanonicalType().isAnyExistentialType();
}

inline bool CanType::isExistentialTypeImpl(CanType type) {
  return isa<ProtocolType>(type) || isa<ProtocolCompositionType>(type);
}

inline bool CanType::isAnyExistentialTypeImpl(CanType type) {
  return isExistentialTypeImpl(type) || isa<ExistentialMetatypeType>(type);
}

inline bool TypeBase::isClassExistentialType() {
  CanType T = getCanonicalType();
  if (auto pt = dyn_cast<ProtocolType>(T))
    return pt->requiresClass();
  if (auto pct = dyn_cast<ProtocolCompositionType>(T))
    return pct->requiresClass();
  return false;
}

inline bool TypeBase::isOpenedExistential() const {
  if (!hasOpenedExistential())
    return false;

  CanType T = getCanonicalType();
  return isa<OpenedArchetypeType>(T);
}

inline bool TypeBase::isOpenedExistentialWithError() {
  if (!hasOpenedExistential())
    return false;

  CanType T = getCanonicalType();
  if (auto archetype = dyn_cast<OpenedArchetypeType>(T)) {
    auto openedExistentialType = archetype->getOpenedExistentialType();
    return openedExistentialType->isExistentialWithError();
  }
  return false;
}

inline bool TypeBase::canDynamicallyBeOptionalType(bool includeExistential) {
  CanType T = getCanonicalType();
  auto isArchetypeOrExistential = isa<ArchetypeType>(T) ||
    (includeExistential && T.isExistentialType());

  return isArchetypeOrExistential && !T.isAnyClassReferenceType();
}

inline ClassDecl *TypeBase::getClassOrBoundGenericClass() {
  return getCanonicalType().getClassOrBoundGenericClass();
}

inline ClassDecl *CanType::getClassOrBoundGenericClass() const {
  if (auto classTy = dyn_cast<ClassType>(*this))
    return classTy->getDecl();

  if (auto boundTy = dyn_cast<BoundGenericClassType>(*this))
    return boundTy->getDecl();

  return nullptr;
}

inline StructDecl *TypeBase::getStructOrBoundGenericStruct() {
  return getCanonicalType().getStructOrBoundGenericStruct();
}

inline StructDecl *CanType::getStructOrBoundGenericStruct() const {
  if (auto structTy = dyn_cast<StructType>(*this))
    return structTy->getDecl();

  if (auto boundTy = dyn_cast<BoundGenericStructType>(*this))
    return boundTy->getDecl();
  
  return nullptr;
}

inline EnumDecl *TypeBase::getEnumOrBoundGenericEnum() {
  return getCanonicalType().getEnumOrBoundGenericEnum();
}

inline EnumDecl *CanType::getEnumOrBoundGenericEnum() const {
  if (auto enumTy = dyn_cast<EnumType>(*this))
    return enumTy->getDecl();

  if (auto boundTy = dyn_cast<BoundGenericEnumType>(*this))
    return boundTy->getDecl();
  
  return nullptr;
}

inline NominalTypeDecl *TypeBase::getNominalOrBoundGenericNominal() {
  return getCanonicalType().getNominalOrBoundGenericNominal();
}

inline NominalTypeDecl *CanType::getNominalOrBoundGenericNominal() const {
  if (auto Ty = dyn_cast<NominalOrBoundGenericNominalType>(*this))
    return Ty->getDecl();
  return nullptr;
}

inline NominalTypeDecl *TypeBase::getAnyNominal() {
  return getCanonicalType().getAnyNominal();
}

inline Type TypeBase::getNominalParent() {
  return castTo<AnyGenericType>()->getParent();
}

inline GenericTypeDecl *TypeBase::getAnyGeneric() {
  return getCanonicalType().getAnyGeneric();
}

  
  
inline bool TypeBase::isBuiltinIntegerType(unsigned n) {
  if (auto intTy = dyn_cast<BuiltinIntegerType>(getCanonicalType()))
    return intTy->getWidth().isFixedWidth()
      && intTy->getWidth().getFixedWidth() == n;
  return false;
}

/// getInOutObjectType - For an inout type, retrieves the underlying object
/// type.  Otherwise, returns the type itself.
inline Type TypeBase::getInOutObjectType() {
  if (auto iot = getAs<InOutType>())
    return iot->getObjectType();
  return this;
}

/// getWithoutSpecifierType - For a non-materializable type
/// e.g. @lvalue or inout, retrieves the underlying object type.
/// Otherwise, returns the type itself.
inline Type TypeBase::getWithoutSpecifierType() {
  if (auto iot = getAs<InOutType>())
    return iot->getObjectType();
  if (auto lv = getAs<LValueType>())
    return lv->getObjectType();
  return this;
}

/// For a ReferenceStorageType like @unowned, this returns the referent.
/// Otherwise, it returns the type itself.
inline Type TypeBase::getReferenceStorageReferent() {
  if (auto rst = getAs<ReferenceStorageType>())
    return rst->getReferentType();
  return this;
}

inline CanType CanType::getReferenceStorageReferentImpl(CanType type) {
  if (auto refType = dyn_cast<ReferenceStorageType>(type))
    return refType.getReferentType();
  return type;
}

inline CanType CanType::getWithoutSpecifierTypeImpl(CanType type) {
  if (auto refType = dyn_cast<InOutType>(type))
    return refType.getObjectType();
  if (auto refType = dyn_cast<LValueType>(type))
    return refType.getObjectType();
  return type;
}

inline CanType CanType::getNominalParent() const {
  return cast<NominalOrBoundGenericNominalType>(*this).getParent();
}

inline bool CanType::isActuallyCanonicalOrNull() const {
  return getPointer() == nullptr ||
         getPointer() == llvm::DenseMapInfo<TypeBase *>::getEmptyKey() ||
         getPointer() == llvm::DenseMapInfo<TypeBase *>::getTombstoneKey() ||
         getPointer()->isCanonical();
}

inline Type TupleTypeElt::getVarargBaseTy() const {
  TypeBase *T = getType().getPointer();
  if (auto *AT = dyn_cast<ArraySliceType>(T))
    return AT->getBaseType();
  if (auto *BGT = dyn_cast<BoundGenericType>(T)) {
    // It's the stdlib Array<T>.
    return BGT->getGenericArgs()[0];
  }
  assert(T->hasError());
  return T;
}

inline TupleTypeElt TupleTypeElt::getWithName(Identifier name) const {
  assert(getParameterFlags().isInOut() == getType()->is<InOutType>());
  return TupleTypeElt(getRawType(), name, getParameterFlags());
}

inline TupleTypeElt TupleTypeElt::getWithType(Type T) const {
  auto flags = getParameterFlags().withInOut(T->is<InOutType>());
  return TupleTypeElt(T->getInOutObjectType(), getName(), flags);
}

/// Create one from what's present in the parameter decl and type
inline ParameterTypeFlags
ParameterTypeFlags::fromParameterType(Type paramTy, bool isVariadic,
                                      bool isAutoClosure,
                                      // SWIFT_ENABLE_TENSORFLOW
                                      ValueOwnership ownership,
                                      bool isNonDifferentiable) {
  // FIXME(Remove InOut): The last caller that needs this is argument
  // decomposition.  Start by enabling the assertion there and fixing up those
  // callers, then remove this, then remove
  // ParameterTypeFlags::fromParameterType entirely.
  if (paramTy->is<InOutType>()) {
    assert(ownership == ValueOwnership::Default ||
           ownership == ValueOwnership::InOut);
    ownership = ValueOwnership::InOut;
  }
  // SWIFT_ENABLE_TENSORFLOW
  return {isVariadic, isAutoClosure, ownership, isNonDifferentiable};
}

inline const Type *BoundGenericType::getTrailingObjectsPointer() const {
  if (auto ty = dyn_cast<BoundGenericStructType>(this))
    return ty->getTrailingObjects<Type>();
  if (auto ty = dyn_cast<BoundGenericEnumType>(this))
    return ty->getTrailingObjects<Type>();
  if (auto ty = dyn_cast<BoundGenericClassType>(this))
    return ty->getTrailingObjects<Type>();
  llvm_unreachable("Unhandled BoundGenericType!");
}

inline ArrayRef<AnyFunctionType::Param> AnyFunctionType::getParams() const {
  switch (getKind()) {
  case TypeKind::Function:
    return cast<FunctionType>(this)->getParams();
  case TypeKind::GenericFunction:
    return cast<GenericFunctionType>(this)->getParams();
  default:
    llvm_unreachable("Undefined function type");
  }
}
  
/// If this is a method in a type or extension thereof, compute
/// and return a parameter to be used for the 'self' argument.  The type of
/// the parameter is the empty Type() if no 'self' argument should exist. This
/// can only be used after name binding has resolved types.
///
/// \param isInitializingCtor Specifies whether we're computing the 'self'
/// type of an initializing constructor, which accepts an instance 'self'
/// rather than a metatype 'self'.
///
/// \param wantDynamicSelf Specifies whether the 'self' type should be
/// wrapped in a DynamicSelfType, which is the case for the 'self' parameter
/// type inside a class method returning 'Self'.
AnyFunctionType::Param computeSelfParam(AbstractFunctionDecl *AFD,
                                        bool isInitializingCtor=false,
                                        bool wantDynamicSelf=false);

#define TYPE(id, parent)
#define SUGARED_TYPE(id, parent) \
template <> \
constexpr bool TypeBase::isSugaredType<id##Type>() { \
  return true; \
}
#include "swift/AST/TypeNodes.def"

inline GenericParamKey::GenericParamKey(const GenericTypeParamType *p)
  : Depth(p->getDepth()), Index(p->getIndex()) { }

inline TypeBase *TypeBase::getDesugaredType() {
  if (!isa<SugarType>(this))
    return this;
  return cast<SugarType>(this)->getSinglyDesugaredType()->getDesugaredType();
}

inline bool TypeBase::hasSimpleTypeRepr() const {
  // NOTE: Please keep this logic in sync with TypeRepr::isSimple().
  switch (getKind()) {
  case TypeKind::Function:
  case TypeKind::GenericFunction:
    return false;

  case TypeKind::Metatype:
  case TypeKind::ExistentialMetatype:
    return !cast<const AnyMetatypeType>(this)->hasRepresentation();

  case TypeKind::NestedArchetype:
    return cast<NestedArchetypeType>(this)->getParent()->hasSimpleTypeRepr();
      
  case TypeKind::OpaqueTypeArchetype:
  case TypeKind::OpenedArchetype:
    return false;

  case TypeKind::ProtocolComposition: {
    // 'Any', 'AnyObject' and single protocol compositions are simple
    auto composition = cast<const ProtocolCompositionType>(this);
    auto memberCount = composition->getMembers().size();
    if (composition->hasExplicitAnyObject())
      return memberCount == 0;
    return memberCount <= 1;
  }

  default:
    return true;
  }
}

} // end namespace swift

namespace llvm {

// DenseMapInfo for BuiltinIntegerWidth.
template<>
struct DenseMapInfo<swift::BuiltinIntegerWidth> {
  using BuiltinIntegerWidth = swift::BuiltinIntegerWidth;
  
  static inline BuiltinIntegerWidth getEmptyKey() {
    return BuiltinIntegerWidth(BuiltinIntegerWidth::DenseMapEmpty);
  }
  
  static inline BuiltinIntegerWidth getTombstoneKey() {
    return BuiltinIntegerWidth(BuiltinIntegerWidth::DenseMapTombstone);
  }
  
  static unsigned getHashValue(BuiltinIntegerWidth w) {
    return DenseMapInfo<unsigned>::getHashValue(w.RawValue);
  }
  
  static bool isEqual(BuiltinIntegerWidth a, BuiltinIntegerWidth b) {
    return a == b;
  }
};

}
  
#endif
