blob: a44404dfad5534d25af897cff112eb8d02ba8766 [file] [log] [blame]
//===--- 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 &param) : Param(param) {}
public:
static CanParam getFromParam(const Param &param) { return CanParam(param); }
CanType getOldType() const { return CanType(Param::getOldType()); }
CanType getPlainType() const { return CanType(Param::getPlainType()); }
CanType getParameterType() const {
return CanType(Param::getParameterType(/*forCanonical*/ true));
}
};
using 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,