| //===--- 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, which describe the Swift |
| // and SIL ASTs. See also: Type.h. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_TYPES_H |
| #define SWIFT_TYPES_H |
| |
| #include "swift/AST/AutoDiff.h" |
| #include "swift/AST/DeclContext.h" |
| #include "swift/AST/ExtInfo.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/SubstitutionMap.h" |
| #include "swift/AST/Type.h" |
| #include "swift/AST/TypeAlignments.h" |
| #include "swift/AST/TypeExpansionContext.h" |
| #include "swift/Basic/ArrayRefView.h" |
| #include "swift/Basic/Debug.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/Error.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; |
| enum BufferPointerTypeKind : unsigned; |
| class ClassDecl; |
| class ClangModuleLoader; |
| 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 SILFunctionType; |
| class StructDecl; |
| class ProtocolDecl; |
| class TypeVariableType; |
| class ValueDecl; |
| class ModuleDecl; |
| class ModuleType; |
| class ProtocolConformance; |
| enum PointerTypeKind : unsigned; |
| struct ValueOwnershipKind; |
| class ErrorExpr; |
| |
| typedef CanTypeWrapper<SILFunctionType> CanSILFunctionType; |
| |
| 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, |
| |
| /// This type contains a type hole. |
| HasTypeHole = 0x800, |
| |
| Last_Property = HasTypeHole |
| }; |
| 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; } |
| |
| /// Does a type with these properties structurally contain a |
| /// type hole? |
| bool hasTypeHole() const { return Bits & HasTypeHole; } |
| |
| /// 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>; |
| |
| /// Base class for all types which describe the Swift and SIL ASTs. |
| /// |
| /// See TypeNodes.def for a succinct description of the full class hierarchy. |
| class alignas(1 << TypeAlignInBits) TypeBase { |
| |
| friend class ASTContext; |
| TypeBase(const TypeBase&) = delete; |
| void operator=(const TypeBase&) = delete; |
| |
| /// This union contains to 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: |
| enum { NumAFTExtInfoBits = 9 }; |
| enum { NumSILExtInfoBits = 9 }; |
| 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+1+16, |
| /// Extra information which affects how the function is called, like |
| /// regparm and the calling convention. |
| ExtInfoBits : NumAFTExtInfoBits, |
| HasClangTypeInfo : 1, |
| : 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, 5+32, |
| /// Type variable options. |
| Options : 5, |
| : NumPadBits, |
| /// The unique number assigned to this type variable. |
| ID : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(SILFunctionType, TypeBase, NumSILExtInfoBits+1+3+1+2+1+1, |
| ExtInfoBits : NumSILExtInfoBits, |
| HasClangTypeInfo : 1, |
| CalleeConvention : 3, |
| HasErrorResult : 1, |
| CoroutineKind : 2, |
| HasInvocationSubs : 1, |
| HasPatternSubs : 1 |
| ); |
| |
| 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(); |
| |
| bool isHole(); |
| |
| /// 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(const 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 this type involves a hole. |
| bool hasHole() const { return getRecursiveProperties().hasTypeHole(); } |
| |
| /// 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(); |
| |
| // // Is this an ObjC generic class. |
| bool isTypeErasedGenericClassType(); |
| |
| /// 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); |
| |
| /// Determines the element type of a known Unsafe[Mutable][Raw]BufferPointer |
| /// variant, or returns null if the type is not a buffer pointer. |
| Type getAnyBufferPointerElementType(BufferPointerTypeKind &BPTK); |
| Type getAnyBufferPointerElementType() { |
| BufferPointerTypeKind Ignore; |
| return getAnyBufferPointerElementType(Ignore); |
| } |
| |
| /// 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); |
| |
| /// Check if this is a nominal type defined at the top level of the Swift module |
| bool isStdlibType(); |
| |
| /// Check if this is either an Array, Set or Dictionary collection type defined |
| /// at the top level of the Swift module |
| bool isKnownStdlibCollectionType(); |
| |
| /// 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()); |
| } |
| |
| /// Checks whether this is a type that supports being called through the |
| /// implementation of a \c callAsFunction method. Note that this does not |
| /// check access control. |
| bool isCallableNominalType(DeclContext *dc); |
| |
| /// Return true if the specified type or a super-class/super-protocol has the |
| /// @dynamicMemberLookup attribute on it. |
| bool hasDynamicMemberLookupAttribute(); |
| |
| /// Return true if the specified type or a super-class/super-protocol has the |
| /// @dynamicCallable attribute on it. |
| bool hasDynamicCallableAttribute(); |
| |
| /// 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); |
| |
| /// Retrieve the root class of this type by repeatedly retrieving the |
| /// superclass. |
| /// |
| /// \param useArchetypes Whether to use context archetypes for outer generic |
| /// parameters if the class is nested inside a generic function. |
| /// |
| /// \returns The base class of this type, or this type itself if it has no |
| /// superclasses. |
| Type getRootClass(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); |
| |
| /// Visit this type and the argument type in parallel, invoking the callback |
| /// function with each archetype-to-substituted-type binding. The callback |
| /// may return a new type to substitute into the result type, or return |
| /// CanType() to error out of the operation. Each invocation of the callback |
| /// receives three arguments: |
| /// - The `orig` archetype from a position in `this` type. |
| /// - The `subst` type in the same structural position of `ty` that is trying to be bound |
| /// to `orig`. |
| /// - The `upperBound` archetype, which if set, indicates the minimum set of constraints |
| /// that any type substituted in this structural position must conform to. May be null, |
| /// indicating an unconstrained context. |
| /// - If `upperBound` is set, then the `substConformances` array will contain the |
| /// protocol conformances for `subst` to each of the protocol requirements |
| /// on `upperBound` in `getConformsTo` order. |
| /// |
| /// Returns the substituted type, or a null CanType() if this type |
| /// is not bindable to the substituted type, or the callback returns |
| /// CanType(). |
| CanType substituteBindingsTo(Type ty, |
| llvm::function_ref<CanType(ArchetypeType *orig, |
| CanType subst, |
| ArchetypeType *upperBound, |
| ArrayRef<ProtocolConformanceRef> substConformances)> substFn); |
| |
| /// 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 at most one optional type. |
| Type lookThroughSingleOptionalType(); |
| |
| /// 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(); |
| |
| SWIFT_DEBUG_DUMP; |
| void dump(raw_ostream &os, unsigned indent = 0) const; |
| |
| SWIFT_DEBUG_DUMPER(dumpPrint()); |
| 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(); |
| |
| Type replaceSubstitutedSILFunctionTypesWithUnsubstituted(SILModule &M) const; // in SILType.cpp |
| |
| /// Return the tangent space of the given type, if it exists. Otherwise, |
| /// return `None`. |
| Optional<TangentSpace> |
| getAutoDiffTangentSpace(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 - Represents the type of an erroneously constructed declaration, |
| /// expression, or type. When creating ErrorTypes, an associated error |
| /// diagnostic should always be emitted. That way when later stages of |
| /// compilation encounter an ErrorType installed by earlier phases they do not |
| /// have to emit further diagnostics to abort compilation. |
| 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); |
| |
| /// BuiltinRawContinuationType - The builtin raw unsafe continuation type. |
| /// In C, this is a non-null AsyncTask*. This pointer is completely |
| /// unmanaged (the unresumed task is self-owning), but has more spare bits |
| /// than Builtin.RawPointer. |
| class BuiltinRawUnsafeContinuationType : public BuiltinType { |
| friend class ASTContext; |
| BuiltinRawUnsafeContinuationType(const ASTContext &C) |
| : BuiltinType(TypeKind::BuiltinRawUnsafeContinuation, C) {} |
| public: |
| static bool classof(const TypeBase *T) { |
| return T->getKind() == TypeKind::BuiltinRawUnsafeContinuation; |
| } |
| }; |
| DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinRawUnsafeContinuationType, BuiltinType); |
| |
| /// BuiltinJobType - The builtin job type. In C, this is a |
| /// non-null Job*. This pointer is completely unmanaged (the unscheduled |
| /// job is self-owning), but has more spare bits than Builtin.RawPointer. |
| class BuiltinJobType : public BuiltinType { |
| friend class ASTContext; |
| BuiltinJobType(const ASTContext &C) |
| : BuiltinType(TypeKind::BuiltinJob, C) {} |
| public: |
| static bool classof(const TypeBase *T) { |
| return T->getKind() == TypeKind::BuiltinJob; |
| } |
| }; |
| DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinJobType, BuiltinType); |
| |
| /// BuiltinDefaultActorStorageType - The type of the stored property |
| /// that's added implicitly to default actors. No C equivalent because |
| /// the C types all include a heap-object header. Similarly, this type |
| /// generally does not appear in the AST/SIL around default actors; |
| /// it's purely a convenience in IRGen. |
| class BuiltinDefaultActorStorageType : public BuiltinType { |
| friend class ASTContext; |
| BuiltinDefaultActorStorageType(const ASTContext &C) |
| : BuiltinType(TypeKind::BuiltinDefaultActorStorage, C) {} |
| public: |
| static bool classof(const TypeBase *T) { |
| return T->getKind() == TypeKind::BuiltinDefaultActorStorage; |
| } |
| }; |
| DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinDefaultActorStorageType, 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 direct generic arguments, which correspond to the generic |
| /// arguments that are directly applied to the typealias declaration |
| /// this type references. |
| ArrayRef<Type> getDirectGenericArgs() 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, |
| NonEphemeral = 1 << 2, |
| OwnershipShift = 3, |
| Ownership = 7 << OwnershipShift, |
| NoDerivative = 1 << 7, |
| NumBits = 7 |
| }; |
| 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, bool nonEphemeral, |
| ValueOwnership ownership, bool noDerivative) |
| : value((variadic ? Variadic : 0) | (autoclosure ? AutoClosure : 0) | |
| (nonEphemeral ? NonEphemeral : 0) | |
| uint8_t(ownership) << OwnershipShift | |
| (noDerivative ? NoDerivative : 0)) {} |
| |
| /// Create one from what's present in the parameter type |
| inline static ParameterTypeFlags |
| fromParameterType(Type paramTy, bool isVariadic, bool isAutoClosure, |
| bool isNonEphemeral, ValueOwnership ownership, |
| bool isNoDerivative); |
| |
| bool isNone() const { return !value; } |
| bool isVariadic() const { return value.contains(Variadic); } |
| bool isAutoClosure() const { return value.contains(AutoClosure); } |
| bool isNonEphemeral() const { return value.contains(NonEphemeral); } |
| bool isInOut() const { return getValueOwnership() == ValueOwnership::InOut; } |
| bool isShared() const { return getValueOwnership() == ValueOwnership::Shared;} |
| bool isOwned() const { return getValueOwnership() == ValueOwnership::Owned; } |
| bool isNoDerivative() const { return value.contains(NoDerivative); } |
| |
| 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); |
| } |
| |
| ParameterTypeFlags withNonEphemeral(bool isNonEphemeral) const { |
| return ParameterTypeFlags(isNonEphemeral |
| ? value | ParameterTypeFlags::NonEphemeral |
| : value - ParameterTypeFlags::NonEphemeral); |
| } |
| |
| ParameterTypeFlags withNoDerivative(bool noDerivative) const { |
| return ParameterTypeFlags(noDerivative |
| ? value | ParameterTypeFlags::NoDerivative |
| : value - ParameterTypeFlags::NoDerivative); |
| } |
| |
| 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, |
| /*nonEphemeral*/ false, getValueOwnership(), |
| /*noDerivative*/ 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. |
| /// |
| /// This type is on its way out. Try to avoid introducing new usages. |
| 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) |
| |
| /// 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 && "param type must be non-null"); |
| assert(!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(); } |
| |
| /// Whether the parameter is marked '@_nonEphemeral' |
| bool isNonEphemeral() const { return Flags.isNonEphemeral(); } |
| |
| /// Whether the parameter is marked '@noDerivative'. |
| bool isNoDerivative() const { return Flags.isNoDerivative(); } |
| |
| 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 withLabel(Identifier newLabel) const { |
| return Param(Ty, newLabel, Flags); |
| } |
| |
| Param withType(Type newType) const { return Param(newType, Label, Flags); } |
| |
| Param withFlags(ParameterTypeFlags flags) const { |
| return Param(Ty, Label, flags); |
| } |
| }; |
| |
| class CanParam : public Param { |
| explicit CanParam(const Param ¶m) : Param(param) {} |
| public: |
| static CanParam getFromParam(const Param ¶m) { 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 ExtInfo = swift::ASTExtInfo; |
| using ExtInfoBuilder = swift::ASTExtInfoBuilder; |
| 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()); |
| } |
| }; |
| |
| protected: |
| /// Create an AnyFunctionType. |
| /// |
| /// Subclasses are responsible for storing and retrieving the |
| /// ClangTypeInfo value if one is present. |
| AnyFunctionType(TypeKind Kind, const ASTContext *CanTypeContext, |
| Type Output, RecursiveTypeProperties properties, |
| unsigned NumParams, ExtInfo Info) |
| : TypeBase(Kind, CanTypeContext, properties), Output(Output) { |
| Bits.AnyFunctionType.ExtInfoBits = Info.getBits(); |
| Bits.AnyFunctionType.HasClangTypeInfo = !Info.getClangTypeInfo().empty(); |
| Bits.AnyFunctionType.NumParams = NumParams; |
| assert(Bits.AnyFunctionType.NumParams == NumParams && "Params dropped!"); |
| // The use of both assert() and static_assert() is intentional. |
| assert(Bits.AnyFunctionType.ExtInfoBits == Info.getBits() && |
| "Bits were dropped!"); |
| static_assert( |
| ASTExtInfoBuilder::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; |
| |
| bool hasClangTypeInfo() const { |
| return Bits.AnyFunctionType.HasClangTypeInfo; |
| } |
| |
| ClangTypeInfo getClangTypeInfo() const; |
| ClangTypeInfo getCanonicalClangTypeInfo() const; |
| |
| /// Returns true if the function type stores a Clang type that cannot |
| /// be derived from its Swift type. Returns false otherwise, including if |
| /// the function type is not @convention(c) or @convention(block). |
| /// |
| /// For example, if you have a function pointer from C getting imported with |
| /// the following type: |
| /// |
| /// @convention(c, cType: "void (*)(size_t (*)(size_t))") |
| /// (@convention(c, cType: "size_t (*)(size_t)") (Int) -> Int)) -> Void |
| /// |
| /// The parameter's function type will have hasNonDerivableClangType() = true, |
| /// but the outer function type will have hasNonDerivableClangType() = false, |
| /// because the parameter and result type are sufficient to correctly derive |
| /// the Clang type for the outer function type. In terms of mangling, |
| /// the parameter type's mangling will incorporate the Clang type but the |
| /// outer function type's mangling doesn't need to duplicate that information. |
| bool hasNonDerivableClangType(); |
| |
| ExtInfo getExtInfo() const { |
| return ExtInfo(Bits.AnyFunctionType.ExtInfoBits, getClangTypeInfo()); |
| } |
| |
| /// Get the canonical ExtInfo for the function type. |
| /// |
| /// The parameter useClangFunctionType is present only for staging purposes. |
| /// In the future, we will always use the canonical clang function type. |
| ExtInfo getCanonicalExtInfo(bool useClangFunctionType) const { |
| return ExtInfo(Bits.AnyFunctionType.ExtInfoBits, |
| |