| //===--- Type.h - Value objects for Swift and SIL types ---------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 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 Type and CanType classes, which are value objects |
| // used to cheaply pass around different kinds of types. The full hierarchy for |
| // Swift and SIL types -- including tuple types, function types and more -- is |
| // defined in Types.h. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_TYPE_H |
| #define SWIFT_TYPE_H |
| |
| #include "llvm/ADT/DenseMap.h" |
| #include "llvm/ADT/DenseMapInfo.h" |
| #include "llvm/ADT/Hashing.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "swift/Basic/Debug.h" |
| #include "swift/Basic/LLVM.h" |
| #include "swift/Basic/ArrayRefView.h" |
| #include "swift/AST/LayoutConstraint.h" |
| #include "swift/AST/PrintOptions.h" |
| #include "swift/AST/TypeAlignments.h" |
| #include "swift/Basic/OptionSet.h" |
| #include "swift/Basic/Compiler.h" |
| #include <functional> |
| #include <string> |
| |
| namespace swift { |
| |
| class ASTPrinter; |
| class ArchetypeType; |
| class ClassDecl; |
| class CanType; |
| class EnumDecl; |
| class GenericSignatureImpl; |
| class ModuleDecl; |
| class NominalTypeDecl; |
| class GenericTypeDecl; |
| class NormalProtocolConformance; |
| class ProtocolConformanceRef; |
| class ProtocolDecl; |
| class ProtocolType; |
| class SILModule; |
| class StructDecl; |
| class SubstitutableType; |
| class SubstitutionMap; |
| class TypeBase; |
| class Type; |
| class TypeWalker; |
| struct ExistentialLayout; |
| enum class ResilienceExpansion : unsigned; |
| |
| /// Type substitution mapping from substitutable types to their |
| /// replacements. |
| typedef llvm::DenseMap<SubstitutableType *, Type> TypeSubstitutionMap; |
| |
| /// Function used to provide substitutions. |
| /// |
| /// Returns a null \c Type to indicate that there is no substitution for |
| /// this substitutable type; otherwise, the replacement type. |
| using TypeSubstitutionFn |
| = llvm::function_ref<Type(SubstitutableType *dependentType)>; |
| |
| /// A function object suitable for use as a \c TypeSubstitutionFn that |
| /// replaces archetypes with their interface types. |
| struct MapTypeOutOfContext { |
| Type operator()(SubstitutableType *type) const; |
| }; |
| |
| /// A function object suitable for use as a \c TypeSubstitutionFn that |
| /// queries an underlying \c TypeSubstitutionMap. |
| struct QueryTypeSubstitutionMap { |
| const TypeSubstitutionMap &substitutions; |
| |
| Type operator()(SubstitutableType *type) const; |
| }; |
| |
| /// A function object suitable for use as a \c TypeSubstitutionFn that |
| /// queries an underlying \c TypeSubstitutionMap, or returns the original type |
| /// if no match was found. |
| struct QueryTypeSubstitutionMapOrIdentity { |
| const TypeSubstitutionMap &substitutions; |
| |
| Type operator()(SubstitutableType *type) const; |
| }; |
| |
| /// Function used to resolve conformances. |
| using GenericFunction = auto(CanType dependentType, |
| Type conformingReplacementType, |
| ProtocolDecl *conformedProtocol) |
| -> ProtocolConformanceRef; |
| using LookupConformanceFn = llvm::function_ref<GenericFunction>; |
| |
| /// Functor class suitable for use as a \c LookupConformanceFn to look up a |
| /// conformance through a module. |
| class LookUpConformanceInModule { |
| ModuleDecl *M; |
| public: |
| explicit LookUpConformanceInModule(ModuleDecl *M) |
| : M(M) {} |
| |
| ProtocolConformanceRef operator()(CanType dependentType, |
| Type conformingReplacementType, |
| ProtocolDecl *conformedProtocol) const; |
| }; |
| |
| /// Functor class suitable for use as a \c LookupConformanceFn that provides |
| /// only abstract conformances for generic types. Asserts that the replacement |
| /// type is an opaque generic type. |
| class MakeAbstractConformanceForGenericType { |
| public: |
| ProtocolConformanceRef operator()(CanType dependentType, |
| Type conformingReplacementType, |
| ProtocolDecl *conformedProtocol) const; |
| }; |
| |
| /// Functor class suitable for use as a \c LookupConformanceFn that fetches |
| /// conformances from a generic signature. |
| class LookUpConformanceInSignature { |
| const GenericSignatureImpl *Sig; |
| public: |
| LookUpConformanceInSignature(const GenericSignatureImpl *Sig) |
| : Sig(Sig) { |
| assert(Sig && "Cannot lookup conformance in null signature!"); |
| } |
| |
| ProtocolConformanceRef operator()(CanType dependentType, |
| Type conformingReplacementType, |
| ProtocolDecl *conformedProtocol) const; |
| }; |
| |
| /// Flags that can be passed when substituting into a type. |
| enum class SubstFlags { |
| /// Allow substitutions to recurse into SILFunctionTypes. |
| /// Normally, SILType::subst() should be used for lowered |
| /// types, however in special cases where the substitution |
| /// is just changing between contextual and interface type |
| /// representations, using Type::subst() is allowed. |
| AllowLoweredTypes = 0x01, |
| /// Map member types to their desugared witness type. |
| DesugarMemberTypes = 0x02, |
| /// Substitute types involving opaque type archetypes. |
| SubstituteOpaqueArchetypes = 0x04 |
| }; |
| |
| /// Options for performing substitutions into a type. |
| struct SubstOptions : public OptionSet<SubstFlags> { |
| // Note: The unfortunate use of TypeBase * here, rather than Type, |
| // is due to a libc++ quirk that requires the result type to be |
| // complete. |
| typedef std::function<TypeBase *(const NormalProtocolConformance *, |
| AssociatedTypeDecl *)> |
| GetTentativeTypeWitness; |
| |
| /// Function that retrieves a tentative type witness for a protocol |
| /// conformance with the state \c CheckingTypeWitnesses. |
| GetTentativeTypeWitness getTentativeTypeWitness; |
| |
| SubstOptions(llvm::NoneType) : OptionSet(None) { } |
| |
| SubstOptions(SubstFlags flags) : OptionSet(flags) { } |
| |
| SubstOptions(OptionSet<SubstFlags> options) : OptionSet(options) { } |
| }; |
| |
| inline SubstOptions operator|(SubstFlags lhs, SubstFlags rhs) { |
| return SubstOptions(lhs) | rhs; |
| } |
| |
| /// Enumeration describing foreign languages to which Swift may be |
| /// bridged. |
| enum class ForeignLanguage { |
| C, |
| ObjectiveC, |
| }; |
| |
| /// Describes how a particular type is representable in a foreign language. |
| enum class ForeignRepresentableKind : uint8_t { |
| /// This type is not representable in the foreign language. |
| None, |
| /// This type is trivially representable in the foreign language. |
| Trivial, |
| /// This type is trivially representable as an object in the foreign |
| /// language. |
| Object, |
| /// This type is representable in the foreign language via bridging. |
| Bridged, |
| /// This type is representable in the foreign language via bridging |
| /// of Error. |
| BridgedError, |
| /// This type is representable in the foreign language via static |
| /// bridging code, only (which is not available at runtime). |
| StaticBridged, |
| }; |
| |
| /// Type - This is a simple value object that contains a pointer to a type |
| /// class. This is potentially sugared. We use this throughout the codebase |
| /// instead of a raw "TypeBase*" to disable equality comparison, which is unsafe |
| /// for sugared types. |
| class Type { |
| TypeBase *Ptr; |
| public: |
| /*implicit*/ Type(TypeBase *P = 0) : Ptr(P) {} |
| |
| TypeBase *getPointer() const { return Ptr; } |
| |
| bool isNull() const { return Ptr == 0; } |
| |
| TypeBase *operator->() const { |
| assert(Ptr && "Cannot dereference a null Type!"); |
| return Ptr; |
| } |
| |
| explicit operator bool() const { return Ptr != 0; } |
| |
| /// Walk this type. |
| /// |
| /// Returns true if the walk was aborted. |
| bool walk(TypeWalker &walker) const; |
| bool walk(TypeWalker &&walker) const { |
| return walk(walker); |
| } |
| |
| /// Look through the given type and its children to find a type for |
| /// which the given predicate returns true. |
| /// |
| /// \param pred A predicate function object. It should return true if the give |
| /// type node satisfies the criteria. |
| /// |
| /// \returns true if the predicate returns true for the given type or any of |
| /// its children. |
| bool findIf(llvm::function_ref<bool(Type)> pred) const; |
| |
| /// Transform the given type by applying the user-provided function to |
| /// each type. |
| /// |
| /// This routine applies the given function to transform one type into |
| /// another. If the function leaves the type unchanged, recurse into the |
| /// child type nodes and transform those. If any child type node changes, |
| /// the parent type node will be rebuilt. |
| /// |
| /// If at any time the function returns a null type, the null will be |
| /// propagated out. |
| /// |
| /// \param fn A function object with the signature \c Type(Type), which |
| /// accepts a type and returns either a transformed type or a null type. |
| /// |
| /// \returns the result of transforming the type. |
| Type transform(llvm::function_ref<Type(Type)> fn) const; |
| |
| /// Transform the given type by applying the user-provided function to |
| /// each type. |
| /// |
| /// This routine applies the given function to transform one type into |
| /// another. If the function leaves the type unchanged, recurse into the |
| /// child type nodes and transform those. If any child type node changes, |
| /// the parent type node will be rebuilt. |
| /// |
| /// If at any time the function returns a null type, the null will be |
| /// propagated out. |
| /// |
| /// If the function returns \c None, the transform operation will |
| /// |
| /// \param fn A function object with the signature |
| /// \c Optional<Type>(TypeBase *), which accepts a type pointer and returns a |
| /// transformed type, a null type (which will propagate the null type to the |
| /// outermost \c transform() call), or None (to indicate that the transform |
| /// operation should recursively transform the subtypes). The function object |
| /// should use \c dyn_cast rather \c getAs, because the transform itself |
| /// handles desugaring. |
| /// |
| /// \returns the result of transforming the type. |
| Type transformRec(llvm::function_ref<Optional<Type>(TypeBase *)> fn) const; |
| |
| /// Look through the given type and its children and apply fn to them. |
| void visit(llvm::function_ref<void (Type)> fn) const { |
| findIf([&fn](Type t) -> bool { |
| fn(t); |
| return false; |
| }); |
| } |
| |
| /// Replace references to substitutable types with new, concrete types and |
| /// return the substituted result. |
| /// |
| /// \param substitutions The mapping from substitutable types to their |
| /// replacements and conformances. |
| /// |
| /// \param options Options that affect the substitutions. |
| /// |
| /// \returns the substituted type, or a null type if an error occurred. |
| Type subst(SubstitutionMap substitutions, |
| SubstOptions options=None) const; |
| |
| /// Replace references to substitutable types with new, concrete types and |
| /// return the substituted result. |
| /// |
| /// \param substitutions A function mapping from substitutable types to their |
| /// replacements. |
| /// |
| /// \param conformances A function for looking up conformances. |
| /// |
| /// \param options Options that affect the substitutions. |
| /// |
| /// \returns the substituted type, or a null type if an error occurred. |
| Type subst(TypeSubstitutionFn substitutions, |
| LookupConformanceFn conformances, |
| SubstOptions options=None) const; |
| |
| /// Replace references to substitutable types with error types. |
| Type substDependentTypesWithErrorTypes() const; |
| |
| bool isPrivateStdlibType(bool treatNonBuiltinProtocolsAsPublic = true) const; |
| |
| SWIFT_DEBUG_DUMP; |
| void dump(raw_ostream &os, unsigned indent = 0) const; |
| |
| void print(raw_ostream &OS, const PrintOptions &PO = PrintOptions()) const; |
| void print(ASTPrinter &Printer, const PrintOptions &PO) 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; |
| |
| /// Computes the join between two types. |
| /// |
| /// The join of two types is the most specific type that is a supertype of |
| /// both \c type1 and \c type2, e.g., the least upper bound in the type |
| /// lattice. For example, given a simple class hierarchy as follows: |
| /// |
| /// \code |
| /// class A { } |
| /// class B : A { } |
| /// class C : A { } |
| /// class D { } |
| /// \endcode |
| /// |
| /// The join of B and C is A, the join of A and B is A. |
| /// |
| /// The Any type is considered the common supertype by default when no |
| /// closer common supertype exists. |
| /// |
| /// In unsupported cases where we cannot yet compute an accurate join, |
| /// we return None. |
| /// |
| /// \returns the join of the two types, if there is a concrete type |
| /// that can express the join, or Any if the only join would be a |
| /// more-general existential type, or None if we cannot yet compute a |
| /// correct join but one better than Any may exist. |
| static Optional<Type> join(Type first, Type second); |
| |
| private: |
| // Direct comparison is disabled for types, because they may not be canonical. |
| void operator==(Type T) const = delete; |
| void operator!=(Type T) const = delete; |
| }; |
| |
| /// Extract the source location from a given type. |
| SourceLoc extractNearestSourceLoc(Type ty); |
| |
| /// CanType - This is a Type that is statically known to be canonical. To get |
| /// one of these, use Type->getCanonicalType(). Since all CanType's can be used |
| /// as 'Type' (they just don't have sugar) we derive from Type. |
| class CanType : public Type { |
| bool isActuallyCanonicalOrNull() const; |
| |
| static bool isReferenceTypeImpl(CanType type, const GenericSignatureImpl *sig, |
| bool functionsCount); |
| static bool isExistentialTypeImpl(CanType type); |
| static bool isAnyExistentialTypeImpl(CanType type); |
| static bool isObjCExistentialTypeImpl(CanType type); |
| static bool isTypeErasedGenericClassTypeImpl(CanType type); |
| static CanType getOptionalObjectTypeImpl(CanType type); |
| static CanType getReferenceStorageReferentImpl(CanType type); |
| static CanType getWithoutSpecifierTypeImpl(CanType type); |
| |
| public: |
| explicit CanType(TypeBase *P = 0) : Type(P) { |
| assert(isActuallyCanonicalOrNull() && |
| "Forming a CanType out of a non-canonical type!"); |
| } |
| explicit CanType(Type T) : Type(T) { |
| assert(isActuallyCanonicalOrNull() && |
| "Forming a CanType out of a non-canonical type!"); |
| } |
| |
| void visit(llvm::function_ref<void (CanType)> fn) const { |
| findIf([&fn](Type t) -> bool { |
| fn(CanType(t)); |
| return false; |
| }); |
| } |
| |
| bool findIf(llvm::function_ref<bool (CanType)> fn) const { |
| return Type::findIf([&fn](Type t) { |
| return fn(CanType(t)); |
| }); |
| } |
| |
| // Provide a few optimized accessors that are really type-class queries. |
| |
| /// Do values of this type have reference semantics? |
| /// |
| /// This includes isAnyClassReferenceType(), as well as function types. |
| bool hasReferenceSemantics() const { |
| return isReferenceTypeImpl(*this, |
| /*signature*/ nullptr, |
| /*functions count*/ true); |
| } |
| |
| /// Are variables of this type permitted to have |
| /// ownership attributes? |
| /// |
| /// This includes: |
| /// - class types, generic or not |
| /// - archetypes with class or class protocol bounds |
| /// - existentials with class or class protocol bounds |
| /// But not: |
| /// - function types |
| bool allowsOwnership(const GenericSignatureImpl *sig) const { |
| return isReferenceTypeImpl(*this, sig, |
| /*functions count*/ false); |
| } |
| |
| /// Are values of this type essentially just class references, |
| /// possibly with some extra metadata? |
| /// |
| /// - any of the builtin reference types |
| /// - a class type |
| /// - a bound generic class type |
| /// - a class-bounded archetype type |
| /// - a class-bounded type parameter |
| /// - a class-bounded existential type |
| /// - a dynamic Self type |
| bool isAnyClassReferenceType() const { |
| return isReferenceTypeImpl(*this, |
| /*signature*/ nullptr, |
| /*functions count*/ false); |
| } |
| |
| /// Is this type existential? |
| bool isExistentialType() const { |
| return isExistentialTypeImpl(*this); |
| } |
| |
| /// Is this type an existential or an existential metatype? |
| bool isAnyExistentialType() const { |
| return isAnyExistentialTypeImpl(*this); |
| } |
| |
| /// Break an existential down into a set of constraints. |
| ExistentialLayout getExistentialLayout(); |
| |
| /// Is this an ObjC-compatible existential type? |
| bool isObjCExistentialType() const { |
| return isObjCExistentialTypeImpl(*this); |
| } |
| |
| // Is this an ObjC generic class. |
| bool isTypeErasedGenericClassType() const { |
| return isTypeErasedGenericClassTypeImpl(*this); |
| } |
| |
| ClassDecl *getClassOrBoundGenericClass() const; // in Types.h |
| StructDecl *getStructOrBoundGenericStruct() const; // in Types.h |
| EnumDecl *getEnumOrBoundGenericEnum() const; // in Types.h |
| NominalTypeDecl *getNominalOrBoundGenericNominal() const; // in Types.h |
| CanType getNominalParent() const; // in Types.h |
| NominalTypeDecl *getAnyNominal() const; |
| GenericTypeDecl *getAnyGeneric() const; |
| |
| CanType getOptionalObjectType() const { |
| return getOptionalObjectTypeImpl(*this); |
| } |
| |
| CanType getReferenceStorageReferent() const { |
| return getReferenceStorageReferentImpl(*this); |
| } |
| |
| CanType getWithoutSpecifierType() const { |
| return getWithoutSpecifierTypeImpl(*this); |
| } |
| |
| // Direct comparison is allowed for CanTypes - they are known canonical. |
| bool operator==(CanType T) const { return getPointer() == T.getPointer(); } |
| bool operator!=(CanType T) const { return !operator==(T); } |
| |
| friend llvm::hash_code hash_value(CanType T) { |
| return llvm::hash_value(T.getPointer()); |
| } |
| |
| bool operator<(CanType T) const { return getPointer() < T.getPointer(); } |
| }; |
| |
| template <class Proxied> class CanTypeWrapper; |
| |
| // Define a database of CanType wrapper classes for ease of metaprogramming. |
| // By definition, this maps 'FOO' to 'CanFOO'. |
| template <class Proxied> struct CanTypeWrapperTraits; |
| template <> struct CanTypeWrapperTraits<Type> { typedef CanType type; }; |
| |
| // A wrapper which preserves the fact that a type is canonical. |
| // |
| // Intended to be used as follows: |
| // DEFINE_LEAF_CAN_TYPE_WRAPPER(BuiltinNativeObject, BuiltinType) |
| // or |
| // BEGIN_CAN_TYPE_WRAPPER(MetatypeType, Type) |
| // PROXY_CAN_TYPE_SIMPLE_GETTER(getInstanceType) |
| // END_CAN_TYPE_WRAPPER(MetatypeType, Type) |
| #define BEGIN_CAN_TYPE_WRAPPER(TYPE, BASE) \ |
| typedef CanTypeWrapper<TYPE> Can##TYPE; \ |
| template <> \ |
| class CanTypeWrapper<TYPE> : public Can##BASE { \ |
| public: \ |
| explicit CanTypeWrapper(TYPE *theType = nullptr) \ |
| : Can##BASE(theType) {} \ |
| \ |
| TYPE *getPointer() const { \ |
| return static_cast<TYPE*>(Type::getPointer()); \ |
| } \ |
| TYPE *operator->() const { \ |
| assert(getPointer() && "Cannot dereference a null " #TYPE); \ |
| return getPointer(); \ |
| } \ |
| operator TYPE *() const { return getPointer(); } \ |
| explicit operator bool() const { return getPointer() != nullptr; } |
| |
| #define PROXY_CAN_TYPE_SIMPLE_GETTER(METHOD) \ |
| CanType METHOD() const { return CanType(getPointer()->METHOD()); } |
| |
| #define END_CAN_TYPE_WRAPPER(TYPE, BASE) \ |
| }; \ |
| template <> struct CanTypeWrapperTraits<TYPE> { \ |
| typedef Can##TYPE type; \ |
| }; |
| |
| #define DEFINE_EMPTY_CAN_TYPE_WRAPPER(TYPE, BASE) \ |
| BEGIN_CAN_TYPE_WRAPPER(TYPE, BASE) \ |
| END_CAN_TYPE_WRAPPER(TYPE, BASE) |
| |
| // Disallow direct uses of isa/cast/dyn_cast on Type to eliminate a |
| // certain class of bugs. |
| template <class X> inline bool |
| isa(const Type&) = delete; // Use TypeBase::is instead. |
| template <class X> inline typename llvm::cast_retty<X, Type>::ret_type |
| cast(const Type&) = delete; // Use TypeBase::castTo instead. |
| template <class X> inline typename llvm::cast_retty<X, Type>::ret_type |
| dyn_cast(const Type&) = delete; // Use TypeBase::getAs instead. |
| template <class X> inline typename llvm::cast_retty<X, Type>::ret_type |
| dyn_cast_or_null(const Type&) = delete; |
| |
| // Permit direct uses of isa/cast/dyn_cast on CanType and preserve |
| // canonicality. |
| template <class X> inline bool isa(CanType type) { |
| return isa<X>(type.getPointer()); |
| } |
| template <class X> inline CanTypeWrapper<X> cast(CanType type) { |
| return CanTypeWrapper<X>(cast<X>(type.getPointer())); |
| } |
| template <class X> inline CanTypeWrapper<X> cast_or_null(CanType type) { |
| return CanTypeWrapper<X>(cast_or_null<X>(type.getPointer())); |
| } |
| template <class X> inline CanTypeWrapper<X> dyn_cast(CanType type) { |
| auto Ty = type.getPointer(); |
| SWIFT_ASSUME(Ty != nullptr); |
| return CanTypeWrapper<X>(dyn_cast<X>(Ty)); |
| } |
| template <class X> inline CanTypeWrapper<X> dyn_cast_or_null(CanType type) { |
| return CanTypeWrapper<X>(dyn_cast_or_null<X>(type.getPointer())); |
| } |
| |
| // Permit direct uses of isa/cast/dyn_cast on CanTypeWrapper<T> and |
| // preserve canonicality. |
| template <class X, class P> |
| inline bool isa(CanTypeWrapper<P> type) { |
| return isa<X>(type.getPointer()); |
| } |
| template <class X, class P> |
| inline CanTypeWrapper<X> cast(CanTypeWrapper<P> type) { |
| return CanTypeWrapper<X>(cast<X>(type.getPointer())); |
| } |
| template <class X, class P> |
| inline CanTypeWrapper<X> dyn_cast(CanTypeWrapper<P> type) { |
| auto Ty = type.getPointer(); |
| SWIFT_ASSUME(Ty != nullptr); |
| return CanTypeWrapper<X>(dyn_cast<X>(Ty)); |
| } |
| template <class X, class P> |
| inline CanTypeWrapper<X> dyn_cast_or_null(CanTypeWrapper<P> type) { |
| return CanTypeWrapper<X>(dyn_cast_or_null<X>(type.getPointer())); |
| } |
| |
| template <typename T> |
| inline T *staticCastHelper(const Type &Ty) { |
| // The constructor of the ArrayRef<Type> must guarantee this invariant. |
| // XXX -- We use reinterpret_cast instead of static_cast so that files |
| // can avoid including Types.h if they want to. |
| return reinterpret_cast<T*>(Ty.getPointer()); |
| } |
| /// TypeArrayView allows arrays of 'Type' to have a static type. |
| template <typename T> |
| using TypeArrayView = ArrayRefView<Type, T*, staticCastHelper, |
| /*AllowOrigAccess*/true>; |
| } // end namespace swift |
| |
| namespace llvm { |
| static inline raw_ostream & |
| operator<<(raw_ostream &OS, swift::Type Ty) { |
| Ty.print(OS); |
| return OS; |
| } |
| |
| // A Type casts like a TypeBase*. |
| template<> struct simplify_type<const ::swift::Type> { |
| typedef ::swift::TypeBase *SimpleType; |
| static SimpleType getSimplifiedValue(const ::swift::Type &Val) { |
| return Val.getPointer(); |
| } |
| }; |
| template<> struct simplify_type< ::swift::Type> |
| : public simplify_type<const ::swift::Type> {}; |
| |
| // Type hashes just like pointers. |
| template<> struct DenseMapInfo<swift::Type> { |
| static swift::Type getEmptyKey() { |
| return llvm::DenseMapInfo<swift::TypeBase*>::getEmptyKey(); |
| } |
| static swift::Type getTombstoneKey() { |
| return llvm::DenseMapInfo<swift::TypeBase*>::getTombstoneKey(); |
| } |
| static unsigned getHashValue(swift::Type Val) { |
| return DenseMapInfo<swift::TypeBase*>::getHashValue(Val.getPointer()); |
| } |
| static bool isEqual(swift::Type LHS, swift::Type RHS) { |
| return LHS.getPointer() == RHS.getPointer(); |
| } |
| }; |
| template<> struct DenseMapInfo<swift::CanType> |
| : public DenseMapInfo<swift::Type> { |
| static swift::CanType getEmptyKey() { |
| return swift::CanType(llvm::DenseMapInfo<swift:: |
| TypeBase*>::getEmptyKey()); |
| } |
| static swift::CanType getTombstoneKey() { |
| return swift::CanType(llvm::DenseMapInfo<swift:: |
| TypeBase*>::getTombstoneKey()); |
| } |
| }; |
| |
| // A Type is "pointer like". |
| template<> |
| struct PointerLikeTypeTraits<swift::Type> { |
| public: |
| static inline void *getAsVoidPointer(swift::Type I) { |
| return (void*)I.getPointer(); |
| } |
| static inline swift::Type getFromVoidPointer(void *P) { |
| return (swift::TypeBase*)P; |
| } |
| enum { NumLowBitsAvailable = swift::TypeAlignInBits }; |
| }; |
| |
| template<> |
| struct PointerLikeTypeTraits<swift::CanType> : |
| public PointerLikeTypeTraits<swift::Type> { |
| public: |
| static inline swift::CanType getFromVoidPointer(void *P) { |
| return swift::CanType((swift::TypeBase*)P); |
| } |
| }; |
| } // end namespace llvm |
| |
| #endif |