| //===--- Type.cpp - Swift Language Type ASTs ------------------------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See http://swift.org/LICENSE.txt for license information |
| // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements the Type class and subclasses. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "swift/AST/ArchetypeBuilder.h" |
| #include "swift/AST/Types.h" |
| #include "swift/AST/TypeVisitor.h" |
| #include "swift/AST/TypeWalker.h" |
| #include "swift/AST/Decl.h" |
| #include "swift/AST/AST.h" |
| #include "swift/AST/LazyResolver.h" |
| #include "swift/AST/Module.h" |
| #include "swift/AST/TypeLoc.h" |
| #include "llvm/ADT/APFloat.h" |
| #include "llvm/ADT/SmallPtrSet.h" |
| #include "llvm/ADT/SmallString.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include <algorithm> |
| #include <functional> |
| #include <iterator> |
| using namespace swift; |
| using llvm::Fixnum; |
| |
| bool TypeLoc::isError() const { |
| assert(wasValidated() && "Type not yet validated"); |
| return getType()->is<ErrorType>(); |
| } |
| |
| SourceRange TypeLoc::getSourceRange() const { |
| if (TyR) |
| return TyR->getSourceRange(); |
| return SourceRange(); |
| } |
| |
| // Only allow allocation of Types using the allocator in ASTContext. |
| void *TypeBase::operator new(size_t bytes, const ASTContext &ctx, |
| AllocationArena arena, unsigned alignment) { |
| return ctx.Allocate(bytes, alignment, arena); |
| } |
| |
| bool CanType::isActuallyCanonicalOrNull() const { |
| return getPointer() == 0 || |
| getPointer() == llvm::DenseMapInfo<TypeBase*>::getTombstoneKey() || |
| getPointer()->isCanonical(); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Various Type Methods. |
| //===----------------------------------------------------------------------===// |
| |
| /// isEqual - Return true if these two types are equal, ignoring sugar. |
| bool TypeBase::isEqual(Type Other) { |
| return getCanonicalType() == Other.getPointer()->getCanonicalType(); |
| } |
| |
| /// hasReferenceSemantics - Does this type have reference semantics? |
| bool TypeBase::hasReferenceSemantics() { |
| return getCanonicalType().hasReferenceSemantics(); |
| } |
| |
| bool TypeBase::isAnyClassReferenceType() { |
| return getCanonicalType().isAnyClassReferenceType(); |
| } |
| |
| bool CanType::isReferenceTypeImpl(CanType type, bool functionsCount) { |
| switch (type->getKind()) { |
| #define SUGARED_TYPE(id, parent) case TypeKind::id: |
| #define TYPE(id, parent) |
| #include "swift/AST/TypeNodes.def" |
| llvm_unreachable("sugared canonical type?"); |
| |
| // These types are always class references. |
| case TypeKind::BuiltinUnknownObject: |
| case TypeKind::BuiltinNativeObject: |
| case TypeKind::BuiltinBridgeObject: |
| case TypeKind::Class: |
| case TypeKind::BoundGenericClass: |
| case TypeKind::SILBox: |
| return true; |
| |
| // For Self types, recur on the underlying type. |
| case TypeKind::DynamicSelf: |
| return isReferenceTypeImpl(cast<DynamicSelfType>(type).getSelfType(), |
| functionsCount); |
| |
| // Archetypes and existentials are only class references if class-bounded. |
| case TypeKind::Archetype: |
| return cast<ArchetypeType>(type)->requiresClass(); |
| case TypeKind::Protocol: |
| return cast<ProtocolType>(type)->requiresClass(); |
| case TypeKind::ProtocolComposition: |
| return cast<ProtocolCompositionType>(type)->requiresClass(); |
| |
| case TypeKind::UnboundGeneric: |
| return isa<ClassDecl>(cast<UnboundGenericType>(type)->getDecl()); |
| |
| // Functions have reference semantics, but are not class references. |
| case TypeKind::Function: |
| case TypeKind::PolymorphicFunction: |
| case TypeKind::GenericFunction: |
| case TypeKind::SILFunction: |
| return functionsCount; |
| |
| // Nothing else is statically just a class reference. |
| case TypeKind::SILBlockStorage: |
| case TypeKind::Error: |
| case TypeKind::Unresolved: |
| case TypeKind::BuiltinInteger: |
| case TypeKind::BuiltinFloat: |
| case TypeKind::BuiltinRawPointer: |
| case TypeKind::BuiltinUnsafeValueBuffer: |
| case TypeKind::BuiltinVector: |
| case TypeKind::Tuple: |
| case TypeKind::Enum: |
| case TypeKind::Struct: |
| case TypeKind::Metatype: |
| case TypeKind::ExistentialMetatype: |
| case TypeKind::Module: |
| case TypeKind::LValue: |
| case TypeKind::InOut: |
| case TypeKind::TypeVariable: |
| case TypeKind::BoundGenericEnum: |
| case TypeKind::BoundGenericStruct: |
| case TypeKind::UnownedStorage: |
| case TypeKind::UnmanagedStorage: |
| case TypeKind::WeakStorage: |
| return false; |
| |
| case TypeKind::GenericTypeParam: |
| case TypeKind::DependentMember: |
| llvm_unreachable("Dependent types can't answer reference-semantics query"); |
| } |
| |
| llvm_unreachable("Unhandled type kind!"); |
| } |
| |
| /// hasOwnership - Are variables of this type permitted to have |
| /// ownership attributes? |
| /// |
| /// This includes: |
| /// - class types, generic or not |
| /// - archetypes with class or class protocol bounds |
| /// - existentials with class or class protocol bounds |
| /// But not: |
| /// - function types |
| bool TypeBase::allowsOwnership() { |
| return getCanonicalType().isAnyClassReferenceType(); |
| } |
| |
| bool TypeBase::isAnyExistentialType(SmallVectorImpl<ProtocolDecl*> &protocols) { |
| return getCanonicalType().isAnyExistentialType(protocols); |
| } |
| |
| bool CanType::isAnyExistentialTypeImpl(CanType type, |
| SmallVectorImpl<ProtocolDecl*> &protocols) { |
| if (auto metatype = dyn_cast<ExistentialMetatypeType>(type)) { |
| metatype.getInstanceType().getAnyExistentialTypeProtocols(protocols); |
| return true; |
| } |
| return isExistentialTypeImpl(type, protocols); |
| } |
| |
| bool TypeBase::isExistentialType(SmallVectorImpl<ProtocolDecl *> &protocols) { |
| return getCanonicalType().isExistentialType(protocols); |
| } |
| |
| bool CanType::isExistentialTypeImpl(CanType type, |
| SmallVectorImpl<ProtocolDecl*> &protocols) { |
| if (auto proto = dyn_cast<ProtocolType>(type)) { |
| proto.getAnyExistentialTypeProtocols(protocols); |
| return true; |
| } |
| |
| if (auto comp = dyn_cast<ProtocolCompositionType>(type)) { |
| comp.getAnyExistentialTypeProtocols(protocols); |
| return true; |
| } |
| |
| assert(!type.isExistentialType()); |
| return false; |
| } |
| |
| void TypeBase::getAnyExistentialTypeProtocols( |
| SmallVectorImpl<ProtocolDecl*> &protocols) { |
| getCanonicalType().getAnyExistentialTypeProtocols(protocols); |
| } |
| |
| void CanType::getAnyExistentialTypeProtocolsImpl(CanType type, |
| SmallVectorImpl<ProtocolDecl*> &protocols) { |
| if (auto proto = dyn_cast<ProtocolType>(type)) { |
| proto.getAnyExistentialTypeProtocols(protocols); |
| } else if (auto comp = dyn_cast<ProtocolCompositionType>(type)) { |
| comp.getAnyExistentialTypeProtocols(protocols); |
| } else if (auto metatype = dyn_cast<ExistentialMetatypeType>(type)) { |
| metatype.getAnyExistentialTypeProtocols(protocols); |
| } else { |
| llvm_unreachable("type was not any kind of existential type!"); |
| } |
| } |
| |
| bool TypeBase::isObjCExistentialType() { |
| return getCanonicalType().isObjCExistentialType(); |
| } |
| |
| bool CanType::isObjCExistentialTypeImpl(CanType type) { |
| if (!type.isExistentialType()) return false; |
| |
| SmallVector<ProtocolDecl *, 4> protocols; |
| type.getAnyExistentialTypeProtocols(protocols); |
| |
| // Must have at least one protocol to be class-bounded. |
| if (protocols.empty()) |
| return false; |
| |
| // Any non-AnyObject, non-@objc protocol makes this no longer ObjC-compatible. |
| for (auto proto : protocols) { |
| if (proto->isSpecificProtocol(KnownProtocolKind::AnyObject)) |
| continue; |
| if (proto->isObjC()) |
| continue; |
| |
| return false; |
| } |
| return true; |
| } |
| |
| bool TypeBase::isSpecialized() { |
| CanType CT = getCanonicalType(); |
| if (CT.getPointer() != this) |
| return CT->isSpecialized(); |
| |
| return CT.findIf([](Type type) -> bool { |
| return isa<BoundGenericType>(type.getPointer()); |
| }); |
| } |
| |
| ArrayRef<Type> TypeBase::getAllGenericArgs(SmallVectorImpl<Type> &scratch) { |
| Type type(this); |
| SmallVector<ArrayRef<Type>, 2> allGenericArgs; |
| |
| while (type) { |
| // Gather generic arguments from a bound generic type. |
| if (auto bound = type->getAs<BoundGenericType>()) { |
| allGenericArgs.push_back(bound->getGenericArgs()); |
| |
| // Continue up to the parent. |
| type = bound->getParent(); |
| continue; |
| } |
| |
| // Use the generic type parameter types for an unbound generic type. |
| if (auto unbound = type->getAs<UnboundGenericType>()) { |
| auto genericSig = unbound->getDecl()->getGenericSignature(); |
| auto genericParams = genericSig->getInnermostGenericParams(); |
| allGenericArgs.push_back( |
| llvm::makeArrayRef((const Type *)genericParams.data(), |
| genericParams.size())); |
| |
| // Continue up to the parent. |
| type = unbound->getParent(); |
| continue; |
| } |
| |
| // For a protocol type, use its Self parameter. |
| if (auto protoType = type->getAs<ProtocolType>()) { |
| auto proto = protoType->getDecl(); |
| allGenericArgs.push_back( |
| llvm::makeArrayRef( |
| proto->getProtocolSelf()->getDeclaredInterfaceType())); |
| |
| // Continue up to the parent. |
| type = protoType->getParent(); |
| continue; |
| } |
| |
| // Look through non-generic nominal types. |
| if (auto nominal = type->getAs<NominalType>()) { |
| type = nominal->getParent(); |
| continue; |
| } |
| |
| break; |
| } |
| |
| // Trivial case: no generic arguments. |
| if (allGenericArgs.empty()) |
| return { }; |
| |
| // Common case: a single set of generic arguments, for which we need no |
| // allocation. |
| if (allGenericArgs.size() == 1) |
| return allGenericArgs.front(); |
| |
| // General case: concatenate all of the generic argument lists together. |
| scratch.clear(); |
| for (auto args : reversed(allGenericArgs)) |
| scratch.append(args.begin(), args.end()); |
| return scratch; |
| } |
| |
| ArrayRef<Substitution> |
| TypeBase::gatherAllSubstitutions(Module *module, |
| SmallVectorImpl<Substitution> &scratchSpace, |
| LazyResolver *resolver, |
| DeclContext *gpContext) { |
| Type type(this); |
| SmallVector<ArrayRef<Substitution>, 2> allSubstitutions; |
| scratchSpace.clear(); |
| |
| while (type) { |
| // Record the substitutions in a bound generic type. |
| if (auto boundGeneric = type->getAs<BoundGenericType>()) { |
| allSubstitutions.push_back(boundGeneric->getSubstitutions(module, |
| resolver, |
| gpContext)); |
| type = boundGeneric->getParent(); |
| if (gpContext) |
| gpContext = gpContext->getParent(); |
| continue; |
| } |
| |
| // Skip to the parent of a nominal type. |
| if (auto nominal = type->getAs<NominalType>()) { |
| type = nominal->getParent(); |
| if (gpContext) |
| gpContext = gpContext->getParent(); |
| continue; |
| } |
| |
| llvm_unreachable("Not a nominal or bound generic type"); |
| } |
| |
| // If there are no substitutions, return an empty array. |
| if (allSubstitutions.empty()) |
| return { }; |
| |
| // If there is only one list of substitutions, return it. There's no |
| // need to copy it. |
| if (allSubstitutions.size() == 1) |
| return allSubstitutions.front(); |
| |
| for (auto substitutions : allSubstitutions) |
| scratchSpace.append(substitutions.begin(), substitutions.end()); |
| return scratchSpace; |
| } |
| |
| ArrayRef<Substitution> TypeBase::gatherAllSubstitutions(Module *module, |
| LazyResolver *resolver, |
| DeclContext *gpContext){ |
| SmallVector<Substitution, 4> scratchSpace; |
| auto subs = gatherAllSubstitutions(module, scratchSpace, resolver, |
| gpContext); |
| if (scratchSpace.empty()) |
| return subs; |
| |
| return getASTContext().AllocateCopy(subs); |
| } |
| |
| |
| bool TypeBase::isUnspecializedGeneric() { |
| CanType CT = getCanonicalType(); |
| if (CT.getPointer() != this) |
| return CT->isUnspecializedGeneric(); |
| |
| switch (getKind()) { |
| #define SUGARED_TYPE(id, parent) case TypeKind::id: |
| #define TYPE(id, parent) |
| #include "swift/AST/TypeNodes.def" |
| return false; |
| |
| case TypeKind::Error: |
| case TypeKind::Unresolved: |
| case TypeKind::TypeVariable: |
| llvm_unreachable("querying invalid type"); |
| |
| case TypeKind::UnboundGeneric: |
| return true; |
| |
| case TypeKind::BoundGenericClass: |
| case TypeKind::BoundGenericEnum: |
| case TypeKind::BoundGenericStruct: |
| return true; |
| |
| case TypeKind::Function: |
| case TypeKind::PolymorphicFunction: { |
| auto funcTy = cast<AnyFunctionType>(this); |
| return funcTy->getInput()->isUnspecializedGeneric() || |
| funcTy->getResult()->isUnspecializedGeneric(); |
| } |
| |
| case TypeKind::GenericFunction: |
| return true; |
| |
| case TypeKind::Class: |
| case TypeKind::Struct: |
| case TypeKind::Enum: |
| if (auto parentTy = cast<NominalType>(this)->getParent()) |
| return parentTy->isUnspecializedGeneric(); |
| return false; |
| |
| case TypeKind::ExistentialMetatype: |
| case TypeKind::Metatype: |
| return cast<AnyMetatypeType>(this)->getInstanceType() |
| ->isUnspecializedGeneric(); |
| |
| case TypeKind::UnownedStorage: |
| case TypeKind::UnmanagedStorage: |
| case TypeKind::WeakStorage: |
| return cast<ReferenceStorageType>(this)->getReferentType() |
| ->isUnspecializedGeneric(); |
| |
| case TypeKind::LValue: |
| return cast<LValueType>(this)->getObjectType()->isUnspecializedGeneric(); |
| case TypeKind::InOut: |
| return cast<InOutType>(this)->getObjectType()->isUnspecializedGeneric(); |
| |
| case TypeKind::Tuple: { |
| auto tupleTy = cast<TupleType>(this); |
| for (auto &Elt : tupleTy->getElements()) |
| if (Elt.getType()->isUnspecializedGeneric()) |
| return true; |
| |
| return false; |
| } |
| |
| case TypeKind::Archetype: |
| case TypeKind::BuiltinFloat: |
| case TypeKind::BuiltinInteger: |
| case TypeKind::BuiltinUnknownObject: |
| case TypeKind::BuiltinNativeObject: |
| case TypeKind::BuiltinBridgeObject: |
| case TypeKind::BuiltinRawPointer: |
| case TypeKind::BuiltinUnsafeValueBuffer: |
| case TypeKind::BuiltinVector: |
| case TypeKind::Module: |
| case TypeKind::DynamicSelf: |
| case TypeKind::Protocol: |
| case TypeKind::ProtocolComposition: |
| case TypeKind::SILFunction: |
| return false; |
| |
| case TypeKind::GenericTypeParam: |
| case TypeKind::DependentMember: |
| return false; |
| |
| case TypeKind::SILBlockStorage: |
| return cast<SILBlockStorageType>(this)->getCaptureType() |
| ->isUnspecializedGeneric(); |
| case TypeKind::SILBox: |
| return cast<SILBoxType>(this)->getBoxedType() |
| ->isUnspecializedGeneric(); |
| } |
| llvm_unreachable("bad TypeKind"); |
| } |
| |
| bool TypeBase::hasOpenedExistential(ArchetypeType *opened) { |
| assert(opened->getOpenedExistentialType() && |
| "not an opened existential type"); |
| |
| if (!hasOpenedExistential()) |
| return false; |
| |
| return getCanonicalType().findIf([&](Type type) -> bool { |
| return opened == dyn_cast<ArchetypeType>(type.getPointer()); |
| }); |
| } |
| |
| void TypeBase::getOpenedExistentials( |
| SmallVectorImpl<ArchetypeType *> &opened) { |
| if (!hasOpenedExistential()) |
| return; |
| |
| SmallPtrSet<ArchetypeType *, 4> known; |
| getCanonicalType().findIf([&](Type type) -> bool { |
| auto archetype = dyn_cast<ArchetypeType>(type.getPointer()); |
| if (!archetype) |
| return false; |
| |
| if (!archetype->getOpenedExistentialType()) |
| return false; |
| |
| if (known.insert(archetype).second) |
| opened.push_back(archetype); |
| |
| return false; |
| }); |
| } |
| |
| Type TypeBase::eraseOpenedExistential(Module *module, |
| ArchetypeType *opened) { |
| assert(opened->getOpenedExistentialType() && |
| "Not an opened existential type?"); |
| |
| if (!hasOpenedExistential()) |
| return Type(this); |
| |
| TypeSubstitutionMap substitutions; |
| substitutions[opened] = opened->getOpenedExistentialType(); |
| return Type(this).subst(module, substitutions, None); |
| } |
| |
| void |
| TypeBase::getTypeVariables(SmallVectorImpl<TypeVariableType *> &typeVariables) { |
| // If we know we don't have any type variables, we're done. |
| if (hasTypeVariable()) { |
| // Use Type::findIf() to walk the types, finding type variables along the |
| // way. |
| getCanonicalType().findIf([&](Type type) -> bool { |
| if (auto tv = dyn_cast<TypeVariableType>(type.getPointer())) { |
| typeVariables.push_back(tv); |
| } |
| |
| return false; |
| }); |
| assert(!typeVariables.empty() && "Did not find type variables!"); |
| } |
| } |
| |
| static bool isLegalSILType(CanType type) { |
| if (!type->isMaterializable()) return false; |
| if (isa<AnyFunctionType>(type)) return false; |
| if (auto meta = dyn_cast<AnyMetatypeType>(type)) |
| return meta->hasRepresentation(); |
| if (auto tupleType = dyn_cast<TupleType>(type)) { |
| for (auto eltType : tupleType.getElementTypes()) { |
| if (!isLegalSILType(eltType)) return false; |
| } |
| return true; |
| } |
| return true; |
| } |
| |
| bool TypeBase::isLegalSILType() { |
| return ::isLegalSILType(getCanonicalType()); |
| } |
| |
| bool TypeBase::isVoid() { |
| return isEqual(getASTContext().TheEmptyTupleType); |
| } |
| |
| bool TypeBase::isAssignableType() { |
| if (isLValueType()) return true; |
| if (auto tuple = getAs<TupleType>()) { |
| for (auto eltType : tuple->getElementTypes()) { |
| if (!eltType->isAssignableType()) |
| return false; |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| namespace { |
| class GetRValueTypeVisitor : public TypeVisitor<GetRValueTypeVisitor, Type> { |
| public: |
| Type visitLValueType(LValueType *lvt) { |
| // Look through lvalue types. |
| assert(!lvt->getObjectType()->isLValueType() |
| && "unexpected nested lvalue"); |
| return lvt->getObjectType(); |
| } |
| |
| Type visitTupleType(TupleType *tt) { |
| // Look through lvalues in tuples. |
| SmallVector<TupleTypeElt, 4> elts; |
| for (auto &elt : tt->getElements()) { |
| elts.push_back(elt.getWithType(visit(elt.getType()))); |
| } |
| return TupleType::get(elts, tt->getASTContext()); |
| } |
| |
| Type visitParenType(ParenType *pt) { |
| return ParenType::get(pt->getASTContext(), visit(pt->getUnderlyingType())); |
| } |
| |
| Type visitType(TypeBase *t) { |
| // Other types should not structurally contain lvalues. |
| assert(!t->isLValueType() |
| && "unexpected structural lvalue"); |
| return t; |
| } |
| }; |
| } // end anonymous namespace |
| |
| Type TypeBase::getRValueType() { |
| // If the type is not an lvalue, this is a no-op. |
| if (!isLValueType()) |
| return this; |
| |
| return GetRValueTypeVisitor().visit(this); |
| } |
| |
| Type TypeBase::getOptionalObjectType() { |
| if (auto boundTy = getAs<BoundGenericEnumType>()) |
| if (boundTy->getDecl()->classifyAsOptionalType() == OTK_Optional) |
| return boundTy->getGenericArgs()[0]; |
| return Type(); |
| } |
| |
| Type TypeBase::getImplicitlyUnwrappedOptionalObjectType() { |
| if (auto boundTy = getAs<BoundGenericEnumType>()) |
| if (boundTy->getDecl()->classifyAsOptionalType() == OTK_ImplicitlyUnwrappedOptional) |
| return boundTy->getGenericArgs()[0]; |
| return Type(); |
| } |
| |
| Type TypeBase::getAnyOptionalObjectType(OptionalTypeKind &kind) { |
| if (auto boundTy = getAs<BoundGenericEnumType>()) |
| if ((kind = boundTy->getDecl()->classifyAsOptionalType())) |
| return boundTy->getGenericArgs()[0]; |
| kind = OTK_None; |
| return Type(); |
| } |
| |
| CanType CanType::getAnyOptionalObjectTypeImpl(CanType type, |
| OptionalTypeKind &kind) { |
| if (auto boundTy = dyn_cast<BoundGenericEnumType>(type)) |
| if ((kind = boundTy->getDecl()->classifyAsOptionalType())) |
| return boundTy.getGenericArgs()[0]; |
| kind = OTK_None; |
| return CanType(); |
| } |
| |
| Type TypeBase::getAnyPointerElementType(PointerTypeKind &PTK) { |
| if (auto boundTy = getAs<BoundGenericType>()) { |
| auto &C = getASTContext(); |
| if (boundTy->getDecl() == C.getUnsafeMutablePointerDecl()) { |
| PTK = PTK_UnsafeMutablePointer; |
| } else if (boundTy->getDecl() == C.getUnsafePointerDecl()) { |
| PTK = PTK_UnsafePointer; |
| } else if ( |
| boundTy->getDecl() == C.getAutoreleasingUnsafeMutablePointerDecl() |
| ) { |
| PTK = PTK_AutoreleasingUnsafeMutablePointer; |
| } else { |
| return Type(); |
| } |
| return boundTy->getGenericArgs()[0]; |
| } |
| return Type(); |
| } |
| |
| Type TypeBase::lookThroughAllAnyOptionalTypes() { |
| Type type(this); |
| while (auto objType = type->getAnyOptionalObjectType()) |
| type = objType; |
| |
| return type; |
| } |
| |
| Type TypeBase::lookThroughAllAnyOptionalTypes(SmallVectorImpl<Type> &optionals){ |
| Type type(this); |
| while (auto objType = type->getAnyOptionalObjectType()) { |
| optionals.push_back(type); |
| type = objType; |
| } |
| |
| return type; |
| } |
| |
| ClassDecl *CanType::getClassBoundImpl(CanType type) { |
| if (auto classTy = dyn_cast<ClassType>(type)) |
| return classTy->getDecl(); |
| |
| if (auto boundTy = dyn_cast<BoundGenericClassType>(type)) |
| return boundTy->getDecl(); |
| |
| if (auto archetypeTy = dyn_cast<ArchetypeType>(type)) { |
| assert(archetypeTy->requiresClass()); |
| if (Type supertype = archetypeTy->getSuperclass()) { |
| return supertype->getClassOrBoundGenericClass(); |
| } |
| return nullptr; |
| } |
| |
| llvm_unreachable("class has no class bound!"); |
| } |
| |
| bool TypeBase::isAnyObject() { |
| if (auto proto = getAs<ProtocolType>()) |
| return proto->getDecl()->isSpecificProtocol(KnownProtocolKind::AnyObject); |
| |
| return false; |
| } |
| |
| bool TypeBase::isEmptyExistentialComposition() { |
| if (auto emtType = ExistentialMetatypeType::get(this)) { |
| if (auto pcType = emtType->getInstanceType()-> |
| getAs<ProtocolCompositionType>()) { |
| return pcType->getProtocols().empty(); |
| } |
| } |
| |
| return false; |
| } |
| |
| static Type getStrippedType(const ASTContext &context, Type type, |
| bool stripLabels, bool stripDefaultArgs) { |
| return type.transform([&](Type type) -> Type { |
| auto *tuple = dyn_cast<TupleType>(type.getPointer()); |
| if (!tuple) |
| return type; |
| |
| SmallVector<TupleTypeElt, 4> elements; |
| bool anyChanged = false; |
| unsigned idx = 0; |
| for (const auto &elt : tuple->getElements()) { |
| Type eltTy = getStrippedType(context, elt.getType(), |
| stripLabels, stripDefaultArgs); |
| if (anyChanged || eltTy.getPointer() != elt.getType().getPointer() || |
| (elt.hasInit() && stripDefaultArgs) || |
| (elt.hasName() && stripLabels)) { |
| if (!anyChanged) { |
| elements.reserve(tuple->getNumElements()); |
| for (unsigned i = 0; i != idx; ++i) { |
| const TupleTypeElt &elt = tuple->getElement(i); |
| Identifier newName = stripLabels? Identifier() : elt.getName(); |
| DefaultArgumentKind newDefArg |
| = stripDefaultArgs? DefaultArgumentKind::None |
| : elt.getDefaultArgKind(); |
| elements.push_back(TupleTypeElt(elt.getType(), newName, newDefArg, |
| elt.isVararg())); |
| } |
| anyChanged = true; |
| } |
| |
| Identifier newName = stripLabels? Identifier() : elt.getName(); |
| DefaultArgumentKind newDefArg |
| = stripDefaultArgs? DefaultArgumentKind::None |
| : elt.getDefaultArgKind(); |
| elements.push_back(TupleTypeElt(eltTy, newName, newDefArg, |
| elt.isVararg())); |
| } |
| ++idx; |
| } |
| |
| if (!anyChanged) |
| return type; |
| |
| // An unlabeled 1-element tuple type is represented as a parenthesized |
| // type. |
| if (elements.size() == 1 && !elements[0].isVararg() && |
| !elements[0].hasName()) |
| return ParenType::get(context, elements[0].getType()); |
| |
| return TupleType::get(elements, context); |
| }); |
| } |
| |
| Type TypeBase::getUnlabeledType(ASTContext &Context) { |
| return getStrippedType(Context, Type(this), /*labels=*/true, |
| /*defaultArgs=*/true); |
| } |
| |
| Type TypeBase::getRelabeledType(ASTContext &ctx, |
| ArrayRef<Identifier> labels) { |
| if (auto tupleTy = dyn_cast<TupleType>(this)) { |
| assert(labels.size() == tupleTy->getNumElements() && |
| "Wrong number of labels"); |
| SmallVector<TupleTypeElt, 4> elements; |
| unsigned i = 0; |
| bool anyChanged = false; |
| for (const auto &elt : tupleTy->getElements()) { |
| if (elt.getName() != labels[i]) |
| anyChanged = true; |
| |
| elements.push_back(TupleTypeElt(elt.getType(), labels[i], |
| elt.getDefaultArgKind(), elt.isVararg())); |
| ++i; |
| } |
| |
| if (!anyChanged) |
| return this; |
| |
| return TupleType::get(elements, ctx); |
| } |
| |
| // If there is no label, the type is unchanged. |
| if (labels[0].empty()) |
| return this; |
| |
| // Create a one-element tuple to capture the label. |
| TupleTypeElt elt(this, labels[0]); |
| return TupleType::get(elt, ctx); |
| } |
| |
| Type TypeBase::getWithoutDefaultArgs(const ASTContext &Context) { |
| return getStrippedType(Context, Type(this), /*labels=*/false, |
| /*defaultArgs=*/true); |
| } |
| |
| Type TypeBase::getWithoutParens() { |
| Type Ty = this; |
| while (auto ParenTy = dyn_cast<ParenType>(Ty.getPointer())) |
| Ty = ParenTy->getUnderlyingType(); |
| return Ty; |
| } |
| |
| Type TypeBase::replaceCovariantResultType(Type newResultType, |
| unsigned uncurryLevel, |
| bool preserveOptionality) { |
| if (uncurryLevel == 0) { |
| if (preserveOptionality) { |
| assert(!newResultType->getAnyOptionalObjectType()); |
| OptionalTypeKind resultOTK; |
| if (getAnyOptionalObjectType(resultOTK)) |
| return OptionalType::get(resultOTK, newResultType); |
| } |
| |
| return newResultType; |
| } |
| |
| // Determine the input and result types of this function. |
| auto fnType = this->castTo<AnyFunctionType>(); |
| Type inputType = fnType->getInput(); |
| Type resultType = |
| fnType->getResult()->replaceCovariantResultType(newResultType, |
| uncurryLevel - 1, |
| preserveOptionality); |
| |
| // Produce the resulting function type. |
| if (auto genericFn = dyn_cast<GenericFunctionType>(fnType)) { |
| return GenericFunctionType::get(genericFn->getGenericSignature(), |
| inputType, resultType, |
| fnType->getExtInfo()); |
| } |
| |
| if (auto polyFn = dyn_cast<PolymorphicFunctionType>(fnType)) { |
| return PolymorphicFunctionType::get(inputType, resultType, |
| &polyFn->getGenericParams(), |
| fnType->getExtInfo()); |
| } |
| |
| return FunctionType::get(inputType, resultType, fnType->getExtInfo()); |
| } |
| |
| /// Rebuilds the given 'self' type using the given object type as the |
| /// replacement for the object type of self. |
| static Type rebuildSelfTypeWithObjectType(Type selfTy, Type objectTy) { |
| auto existingObjectTy = selfTy->getRValueInstanceType(); |
| return selfTy.transform([=](Type type) -> Type { |
| if (type->isEqual(existingObjectTy)) |
| return objectTy; |
| return type; |
| }); |
| } |
| |
| /// Returns a new function type exactly like this one but with the self |
| /// parameter replaced. Only makes sense for members of types. |
| Type TypeBase::replaceSelfParameterType(Type newSelf) { |
| auto fnTy = castTo<AnyFunctionType>(); |
| Type input = rebuildSelfTypeWithObjectType(fnTy->getInput(), newSelf); |
| |
| if (auto genericFnTy = getAs<GenericFunctionType>()) { |
| return GenericFunctionType::get(genericFnTy->getGenericSignature(), |
| input, |
| fnTy->getResult(), |
| fnTy->getExtInfo()); |
| } |
| |
| if (auto polyFnTy = getAs<PolymorphicFunctionType>()) { |
| return PolymorphicFunctionType::get(input, |
| fnTy->getResult(), |
| &polyFnTy->getGenericParams()); |
| } |
| |
| return FunctionType::get(input, |
| fnTy->getResult(), |
| fnTy->getExtInfo()); |
| } |
| |
| Type TypeBase::getWithoutNoReturn(unsigned UncurryLevel) { |
| if (UncurryLevel == 0) |
| return this; |
| |
| auto *FnType = this->castTo<AnyFunctionType>(); |
| Type InputType = FnType->getInput(); |
| Type ResultType = FnType->getResult()->getWithoutNoReturn(UncurryLevel - 1); |
| auto TheExtInfo = FnType->getExtInfo().withIsNoReturn(false); |
| if (auto *GFT = dyn_cast<GenericFunctionType>(FnType)) { |
| return GenericFunctionType::get(GFT->getGenericSignature(), |
| InputType, ResultType, |
| TheExtInfo); |
| } |
| if (auto *PFT = dyn_cast<PolymorphicFunctionType>(FnType)) { |
| return PolymorphicFunctionType::get(InputType, ResultType, |
| &PFT->getGenericParams(), |
| TheExtInfo); |
| } |
| return FunctionType::get(InputType, ResultType, TheExtInfo); |
| } |
| |
| /// Retrieve the object type for a 'self' parameter, digging into one-element |
| /// tuples, inout types, and metatypes. |
| Type TypeBase::getRValueInstanceType() { |
| Type type = this; |
| |
| // Look through argument list tuples. |
| if (auto tupleTy = type->getAs<TupleType>()) { |
| if (tupleTy->getNumElements() == 1 && !tupleTy->getElement(0).isVararg()) |
| type = tupleTy->getElementType(0); |
| } |
| |
| if (auto metaTy = type->getAs<AnyMetatypeType>()) |
| return metaTy->getInstanceType(); |
| |
| // For mutable value type methods, we need to dig through inout types. |
| return type->getInOutObjectType(); |
| } |
| |
| TypeDecl *TypeBase::getDirectlyReferencedTypeDecl() const { |
| if (auto module = dyn_cast<ModuleType>(this)) |
| return module->getModule(); |
| |
| if (auto nominal = dyn_cast<NominalType>(this)) |
| return nominal->getDecl(); |
| |
| if (auto bound = dyn_cast<BoundGenericType>(this)) |
| return bound->getDecl(); |
| |
| if (auto unbound = dyn_cast<UnboundGenericType>(this)) |
| return unbound->getDecl(); |
| |
| if (auto alias = dyn_cast<NameAliasType>(this)) |
| return alias->getDecl(); |
| |
| if (auto gp = dyn_cast<GenericTypeParamType>(this)) |
| return gp->getDecl(); |
| |
| if (auto depMem = dyn_cast<DependentMemberType>(this)) |
| return depMem->getAssocType(); |
| |
| if (auto archetype = dyn_cast<ArchetypeType>(this)) { |
| if (auto proto = archetype->getSelfProtocol()) |
| return proto->getProtocolSelf(); |
| |
| if (auto assoc = archetype->getAssocType()) |
| return assoc; |
| |
| return nullptr; |
| } |
| |
| return nullptr; |
| } |
| |
| StringRef TypeBase::getInferredDefaultArgString() { |
| if (auto structDecl = getStructOrBoundGenericStruct()) { |
| if (structDecl->getClangDecl()) { |
| for (auto attr : structDecl->getAttrs()) { |
| if (auto synthesizedProto = dyn_cast<SynthesizedProtocolAttr>(attr)) { |
| if (synthesizedProto->getProtocolKind() |
| == KnownProtocolKind::OptionSetType) |
| return "[]"; |
| } |
| } |
| } |
| } |
| |
| return "nil"; |
| } |
| |
| /// \brief Collect the protocols in the existential type T into the given |
| /// vector. |
| static void addProtocols(Type T, SmallVectorImpl<ProtocolDecl *> &Protocols) { |
| if (auto Proto = T->getAs<ProtocolType>()) { |
| Protocols.push_back(Proto->getDecl()); |
| } else if (auto PC = T->getAs<ProtocolCompositionType>()) { |
| for (auto P : PC->getProtocols()) |
| addProtocols(P, Protocols); |
| } |
| } |
| |
| /// \brief Add the protocol (or protocols) in the type T to the stack of |
| /// protocols, checking whether any of the protocols had already been seen and |
| /// zapping those in the original list that we find again. |
| static void addMinimumProtocols(Type T, |
| SmallVectorImpl<ProtocolDecl *> &Protocols, |
| llvm::SmallDenseMap<ProtocolDecl *, unsigned> &Known, |
| llvm::SmallPtrSet<ProtocolDecl *, 16> &Visited, |
| SmallVector<ProtocolDecl *, 16> &Stack, |
| bool &ZappedAny) { |
| if (auto Proto = T->getAs<ProtocolType>()) { |
| auto KnownPos = Known.find(Proto->getDecl()); |
| if (KnownPos != Known.end()) { |
| // We've come across a protocol that is in our original list. Zap it. |
| Protocols[KnownPos->second] = nullptr; |
| ZappedAny = true; |
| } |
| |
| if (Visited.insert(Proto->getDecl()).second) { |
| Stack.push_back(Proto->getDecl()); |
| for (auto Inherited : Proto->getDecl()->getInheritedProtocols(nullptr)) |
| addMinimumProtocols(Inherited->getDeclaredType(), Protocols, Known, |
| Visited, Stack, ZappedAny); |
| } |
| return; |
| } |
| |
| if (auto PC = T->getAs<ProtocolCompositionType>()) { |
| for (auto C : PC->getProtocols()) { |
| addMinimumProtocols(C, Protocols, Known, Visited, Stack, ZappedAny); |
| } |
| } |
| } |
| |
| /// \brief Compare two protocols to establish an ordering between them. |
| int ProtocolType::compareProtocols(ProtocolDecl * const* PP1, |
| ProtocolDecl * const* PP2) { |
| auto *P1 = *PP1; |
| auto *P2 = *PP2; |
| Module *M1 = P1->getParentModule(); |
| Module *M2 = P2->getParentModule(); |
| |
| // Try ordering based on module name, first. |
| if (int result = M1->getName().str().compare(M2->getName().str())) |
| return result; |
| |
| // Order based on protocol name. |
| return P1->getName().str().compare(P2->getName().str()); |
| } |
| |
| void ProtocolType::canonicalizeProtocols( |
| SmallVectorImpl<ProtocolDecl *> &protocols) { |
| llvm::SmallDenseMap<ProtocolDecl *, unsigned> known; |
| llvm::SmallPtrSet<ProtocolDecl *, 16> visited; |
| SmallVector<ProtocolDecl *, 16> stack; |
| bool zappedAny = false; |
| |
| // Seed the stack with the protocol declarations in the original list. |
| // Zap any obvious duplicates along the way. |
| for (unsigned I = 0, N = protocols.size(); I != N; ++I) { |
| // Check whether we've seen this protocol before. |
| auto knownPos = known.find(protocols[I]); |
| |
| // If we have not seen this protocol before, record its index. |
| if (knownPos == known.end()) { |
| known[protocols[I]] = I; |
| stack.push_back(protocols[I]); |
| continue; |
| } |
| |
| // We have seen this protocol before; zap this occurrence. |
| protocols[I] = 0; |
| zappedAny = true; |
| } |
| |
| // Walk the inheritance hierarchies of all of the protocols. If we run into |
| // one of the known protocols, zap it from the original list. |
| while (!stack.empty()) { |
| ProtocolDecl *Current = stack.back(); |
| stack.pop_back(); |
| |
| // Add the protocols we inherited. |
| for (auto Inherited : Current->getInheritedProtocols(nullptr)) { |
| addMinimumProtocols(Inherited->getDeclaredType(), protocols, known, |
| visited, stack, zappedAny); |
| } |
| } |
| |
| if (zappedAny) |
| protocols.erase(std::remove(protocols.begin(), protocols.end(), nullptr), |
| protocols.end()); |
| |
| // Sort the set of protocols by module + name, to give a stable |
| // ordering. |
| llvm::array_pod_sort(protocols.begin(), protocols.end(), compareProtocols); |
| } |
| |
| /// getCanonicalType - Return the canonical version of this type, which has |
| /// sugar from all levels stripped off. |
| CanType TypeBase::getCanonicalType() { |
| // If the type is itself canonical, return it. |
| if (isCanonical()) |
| return CanType(this); |
| // If the canonical type was already computed, just return what we have. |
| if (TypeBase *CT = CanonicalType.get<TypeBase*>()) |
| return CanType(CT); |
| |
| // Otherwise, compute and cache it. |
| TypeBase *Result = 0; |
| switch (getKind()) { |
| #define ALWAYS_CANONICAL_TYPE(id, parent) case TypeKind::id: |
| #define TYPE(id, parent) |
| #include "swift/AST/TypeNodes.def" |
| case TypeKind::Error: |
| case TypeKind::Unresolved: |
| case TypeKind::TypeVariable: |
| llvm_unreachable("these types are always canonical"); |
| |
| #define SUGARED_TYPE(id, parent) \ |
| case TypeKind::id: \ |
| Result = cast<id##Type>(this)-> \ |
| getSinglyDesugaredType()->getCanonicalType().getPointer(); \ |
| break; |
| #define TYPE(id, parent) |
| #include "swift/AST/TypeNodes.def" |
| |
| case TypeKind::Enum: |
| case TypeKind::Struct: |
| case TypeKind::Class: { |
| auto nominalTy = cast<NominalType>(this); |
| auto parentTy = nominalTy->getParent()->getCanonicalType(); |
| Result = NominalType::get(nominalTy->getDecl(), parentTy, |
| parentTy->getASTContext()); |
| break; |
| } |
| |
| case TypeKind::Tuple: { |
| TupleType *TT = cast<TupleType>(this); |
| assert(TT->getNumElements() != 0 && "Empty tuples are always canonical"); |
| |
| SmallVector<TupleTypeElt, 8> CanElts; |
| CanElts.reserve(TT->getNumElements()); |
| for (const TupleTypeElt &field : TT->getElements()) { |
| assert(!field.getType().isNull() && |
| "Cannot get canonical type of un-typechecked TupleType!"); |
| CanElts.push_back(TupleTypeElt(field.getType()->getCanonicalType(), |
| field.getName(), |
| field.getDefaultArgKind(), |
| field.isVararg())); |
| } |
| |
| const ASTContext &C = CanElts[0].getType()->getASTContext(); |
| Result = TupleType::get(CanElts, C)->castTo<TupleType>(); |
| break; |
| } |
| |
| case TypeKind::GenericTypeParam: { |
| GenericTypeParamType *gp = cast<GenericTypeParamType>(this); |
| auto gpDecl = gp->getDecl(); |
| |
| Result = GenericTypeParamType::get(gpDecl->getDepth(), gpDecl->getIndex(), |
| gpDecl->getASTContext()); |
| break; |
| } |
| |
| case TypeKind::DependentMember: { |
| auto dependent = cast<DependentMemberType>(this); |
| auto base = dependent->getBase()->getCanonicalType(); |
| const ASTContext &ctx = base->getASTContext(); |
| if (auto assocType = dependent->getAssocType()) |
| Result = DependentMemberType::get(base, assocType, ctx); |
| else |
| Result = DependentMemberType::get(base, dependent->getName(), ctx); |
| break; |
| } |
| |
| case TypeKind::UnownedStorage: |
| case TypeKind::UnmanagedStorage: |
| case TypeKind::WeakStorage: { |
| auto ref = cast<ReferenceStorageType>(this); |
| Type referentType = ref->getReferentType()->getCanonicalType(); |
| Result = ReferenceStorageType::get(referentType, ref->getOwnership(), |
| referentType->getASTContext()); |
| break; |
| } |
| case TypeKind::LValue: |
| Result = LValueType::get(getRValueType()->getCanonicalType()); |
| break; |
| case TypeKind::InOut: |
| Result = InOutType::get(getInOutObjectType()->getCanonicalType()); |
| break; |
| case TypeKind::PolymorphicFunction: { |
| PolymorphicFunctionType *FT = cast<PolymorphicFunctionType>(this); |
| Type In = FT->getInput()->getCanonicalType(); |
| Type Out = FT->getResult()->getCanonicalType(); |
| Result = PolymorphicFunctionType::get(In, Out, &FT->getGenericParams(), |
| FT->getExtInfo()); |
| break; |
| } |
| case TypeKind::GenericFunction: { |
| GenericFunctionType *function = cast<GenericFunctionType>(this); |
| |
| // Canonicalize the signature. |
| GenericSignature *sig = function->getGenericSignature() |
| ->getCanonicalSignature(); |
| |
| // Canonicalize generic parameters. |
| SmallVector<GenericTypeParamType *, 4> genericParams; |
| for (auto param : function->getGenericParams()) { |
| auto newParam = param->getCanonicalType()->castTo<GenericTypeParamType>(); |
| genericParams.push_back(newParam); |
| } |
| |
| // Transform requirements. |
| SmallVector<Requirement, 4> requirements; |
| for (const auto &req : function->getRequirements()) { |
| auto firstType = req.getFirstType()->getCanonicalType(); |
| auto secondType = req.getSecondType(); |
| if (secondType) |
| secondType = secondType->getCanonicalType(); |
| requirements.push_back(Requirement(req.getKind(), firstType, secondType)); |
| } |
| |
| // Transform input type. |
| auto inputTy = function->getInput()->getCanonicalType(); |
| auto resultTy = function->getResult()->getCanonicalType(); |
| |
| Result = GenericFunctionType::get(sig, inputTy, resultTy, |
| function->getExtInfo()); |
| break; |
| } |
| |
| case TypeKind::SILBlockStorage: |
| case TypeKind::SILBox: |
| case TypeKind::SILFunction: |
| llvm_unreachable("SIL-only types are always canonical!"); |
| |
| case TypeKind::Function: { |
| FunctionType *FT = cast<FunctionType>(this); |
| Type In = FT->getInput()->getCanonicalType(); |
| Type Out = FT->getResult()->getCanonicalType(); |
| Result = FunctionType::get(In, Out, FT->getExtInfo()); |
| break; |
| } |
| case TypeKind::ProtocolComposition: { |
| SmallVector<Type, 4> CanProtos; |
| for (Type t : cast<ProtocolCompositionType>(this)->getProtocols()) |
| CanProtos.push_back(t->getCanonicalType()); |
| assert(!CanProtos.empty() && "Non-canonical empty composition?"); |
| const ASTContext &C = CanProtos[0]->getASTContext(); |
| Type Composition = ProtocolCompositionType::get(C, CanProtos); |
| Result = Composition.getPointer(); |
| break; |
| } |
| case TypeKind::ExistentialMetatype: { |
| auto metatype = cast<ExistentialMetatypeType>(this); |
| auto instanceType = metatype->getInstanceType()->getCanonicalType(); |
| if (metatype->hasRepresentation()) |
| Result = ExistentialMetatypeType::get(instanceType, |
| metatype->getRepresentation()); |
| else |
| Result = ExistentialMetatypeType::get(instanceType); |
| break; |
| } |
| case TypeKind::Metatype: { |
| MetatypeType *MT = cast<MetatypeType>(this); |
| Type InstanceTy = MT->getInstanceType()->getCanonicalType(); |
| if (MT->hasRepresentation()) |
| Result = MetatypeType::get(InstanceTy, MT->getRepresentation()); |
| else |
| Result = MetatypeType::get(InstanceTy); |
| break; |
| } |
| case TypeKind::DynamicSelf: { |
| DynamicSelfType *DST = cast<DynamicSelfType>(this); |
| Type SelfTy = DST->getSelfType()->getCanonicalType(); |
| Result = DynamicSelfType::get(SelfTy, SelfTy->getASTContext()); |
| break; |
| } |
| case TypeKind::UnboundGeneric: { |
| auto unbound = cast<UnboundGenericType>(this); |
| Type parentTy = unbound->getParent()->getCanonicalType(); |
| Result = UnboundGenericType::get(unbound->getDecl(), parentTy, |
| parentTy->getASTContext()); |
| break; |
| } |
| case TypeKind::BoundGenericClass: |
| case TypeKind::BoundGenericEnum: |
| case TypeKind::BoundGenericStruct: { |
| BoundGenericType *BGT = cast<BoundGenericType>(this); |
| Type parentTy; |
| if (BGT->getParent()) |
| parentTy = BGT->getParent()->getCanonicalType(); |
| SmallVector<Type, 4> CanGenericArgs; |
| for (Type Arg : BGT->getGenericArgs()) |
| CanGenericArgs.push_back(Arg->getCanonicalType()); |
| Result = BoundGenericType::get(BGT->getDecl(), parentTy, CanGenericArgs); |
| break; |
| } |
| } |
| |
| |
| // Cache the canonical type for future queries. |
| assert(Result && "Case not implemented!"); |
| CanonicalType = Result; |
| return CanType(Result); |
| } |
| |
| |
| TypeBase *TypeBase::getDesugaredType() { |
| switch (getKind()) { |
| #define ALWAYS_CANONICAL_TYPE(id, parent) case TypeKind::id: |
| #define UNCHECKED_TYPE(id, parent) case TypeKind::id: |
| #define TYPE(id, parent) |
| #include "swift/AST/TypeNodes.def" |
| case TypeKind::Tuple: |
| case TypeKind::Function: |
| case TypeKind::PolymorphicFunction: |
| case TypeKind::GenericFunction: |
| case TypeKind::SILBlockStorage: |
| case TypeKind::SILBox: |
| case TypeKind::SILFunction: |
| case TypeKind::LValue: |
| case TypeKind::InOut: |
| case TypeKind::ProtocolComposition: |
| case TypeKind::ExistentialMetatype: |
| case TypeKind::Metatype: |
| case TypeKind::BoundGenericClass: |
| case TypeKind::BoundGenericEnum: |
| case TypeKind::BoundGenericStruct: |
| case TypeKind::Enum: |
| case TypeKind::Struct: |
| case TypeKind::Class: |
| case TypeKind::GenericTypeParam: |
| case TypeKind::DependentMember: |
| case TypeKind::UnownedStorage: |
| case TypeKind::UnmanagedStorage: |
| case TypeKind::WeakStorage: |
| case TypeKind::DynamicSelf: |
| // None of these types have sugar at the outer level. |
| return this; |
| #define SUGARED_TYPE(ID, PARENT) \ |
| case TypeKind::ID: \ |
| return cast<ID##Type>(this)->getSinglyDesugaredType()->getDesugaredType(); |
| #define TYPE(id, parent) |
| #include "swift/AST/TypeNodes.def" |
| } |
| |
| llvm_unreachable("Unknown type kind"); |
| } |
| |
| TypeBase *ParenType::getSinglyDesugaredType() { |
| return getUnderlyingType().getPointer(); |
| } |
| |
| TypeBase *NameAliasType::getSinglyDesugaredType() { |
| return getDecl()->getUnderlyingType().getPointer(); |
| } |
| |
| TypeBase *SyntaxSugarType::getSinglyDesugaredType() { |
| return getImplementationType().getPointer(); |
| } |
| |
| Type SyntaxSugarType::getImplementationType() { |
| if (ImplOrContext.is<Type>()) |
| return ImplOrContext.get<Type>(); |
| |
| // Find the generic type that implements this syntactic sugar type. |
| auto &ctx = *ImplOrContext.get<const ASTContext *>(); |
| NominalTypeDecl *implDecl; |
| |
| if (isa<ArraySliceType>(this)) { |
| implDecl = ctx.getArrayDecl(); |
| assert(implDecl && "Array type has not been set yet"); |
| } else if (isa<OptionalType>(this)) { |
| implDecl = ctx.getOptionalDecl(); |
| assert(implDecl && "Optional type has not been set yet"); |
| } else if (isa<ImplicitlyUnwrappedOptionalType>(this)) { |
| implDecl = ctx.getImplicitlyUnwrappedOptionalDecl(); |
| assert(implDecl && "Optional type has not been set yet"); |
| } else { |
| llvm_unreachable("Unhandled syntax sugar type"); |
| } |
| |
| // Record the implementation type. |
| ImplOrContext = BoundGenericType::get(implDecl, Type(), Base); |
| return ImplOrContext.get<Type>(); |
| } |
| |
| TypeBase *DictionaryType::getSinglyDesugaredType() { |
| return getImplementationType().getPointer(); |
| } |
| |
| Type DictionaryType::getImplementationType() { |
| if (ImplOrContext.is<Type>()) |
| return ImplOrContext.get<Type>(); |
| |
| // Find the generic type that implements this syntactic sugar type. |
| auto &ctx = *ImplOrContext.get<const ASTContext *>(); |
| NominalTypeDecl *implDecl = ctx.getDictionaryDecl(); |
| assert(implDecl && "Dictionary type has not been set yet"); |
| |
| // Record the implementation type. |
| ImplOrContext = BoundGenericType::get(implDecl, Type(), { Key, Value }); |
| return ImplOrContext.get<Type>(); |
| } |
| |
| TypeBase *SubstitutedType::getSinglyDesugaredType() { |
| return getReplacementType().getPointer(); |
| } |
| |
| unsigned GenericTypeParamType::getDepth() const { |
| if (auto param = getDecl()) { |
| return param->getDepth(); |
| } |
| |
| auto fixedNum = ParamOrDepthIndex.get<Fixnum<31>>(); |
| return fixedNum >> 16; |
| } |
| |
| unsigned GenericTypeParamType::getIndex() const { |
| if (auto param = getDecl()) { |
| return param->getIndex(); |
| } |
| |
| auto fixedNum = ParamOrDepthIndex.get<Fixnum<31>>(); |
| return fixedNum & 0xFFFF; |
| } |
| |
| Identifier GenericTypeParamType::getName() const { |
| // Use the declaration name if we still have that sugar. |
| if (auto decl = getDecl()) |
| return decl->getName(); |
| |
| // Otherwise, we're canonical. Produce an anonymous '<tau>_n_n' name. |
| assert(isCanonical()); |
| // getASTContext() doesn't actually mutate an already-canonical type. |
| auto &C = const_cast<GenericTypeParamType*>(this)->getASTContext(); |
| auto &names = C.CanonicalGenericTypeParamTypeNames; |
| unsigned depthIndex = ParamOrDepthIndex.get<Fixnum<31>>(); |
| auto cached = names.find(depthIndex); |
| if (cached != names.end()) |
| return cached->second; |
| |
| llvm::SmallString<10> nameBuf; |
| llvm::raw_svector_ostream os(nameBuf); |
| |
| static const char *tau = u8"\u03C4_"; |
| |
| os << tau << getDepth() << '_' << getIndex(); |
| Identifier name = C.getIdentifier(os.str()); |
| names.insert({depthIndex, name}); |
| return name; |
| } |
| |
| TypeBase *AssociatedTypeType::getSinglyDesugaredType() { |
| return getDecl()->getArchetype(); |
| } |
| |
| const llvm::fltSemantics &BuiltinFloatType::getAPFloatSemantics() const { |
| switch (getFPKind()) { |
| case BuiltinFloatType::IEEE16: return APFloat::IEEEhalf; |
| case BuiltinFloatType::IEEE32: return APFloat::IEEEsingle; |
| case BuiltinFloatType::IEEE64: return APFloat::IEEEdouble; |
| case BuiltinFloatType::IEEE80: return APFloat::x87DoubleExtended; |
| case BuiltinFloatType::IEEE128: return APFloat::IEEEquad; |
| case BuiltinFloatType::PPC128: return APFloat::PPCDoubleDouble; |
| } |
| llvm::report_fatal_error("Unknown FP semantics"); |
| } |
| |
| bool TypeBase::isSpelledLike(Type other) { |
| TypeBase *me = this; |
| TypeBase *them = other.getPointer(); |
| |
| if (me == them) |
| return true; |
| |
| if (me->getKind() != them->getKind()) |
| return false; |
| |
| switch (me->getKind()) { |
| #define ALWAYS_CANONICAL_TYPE(id, parent) case TypeKind::id: |
| #define UNCHECKED_TYPE(id, parent) case TypeKind::id: |
| #define TYPE(id, parent) |
| #include "swift/AST/TypeNodes.def" |
| case TypeKind::Enum: |
| case TypeKind::Struct: |
| case TypeKind::Class: |
| case TypeKind::NameAlias: |
| case TypeKind::Substituted: |
| case TypeKind::AssociatedType: |
| case TypeKind::GenericTypeParam: |
| case TypeKind::DependentMember: |
| case TypeKind::DynamicSelf: |
| return false; |
| |
| case TypeKind::BoundGenericClass: |
| case TypeKind::BoundGenericEnum: |
| case TypeKind::BoundGenericStruct: { |
| auto bgMe = cast<BoundGenericType>(me); |
| auto bgThem = cast<BoundGenericType>(them); |
| if (bgMe->getDecl() != bgThem->getDecl()) |
| return false; |
| if (bgMe->getGenericArgs().size() != bgThem->getGenericArgs().size()) |
| return false; |
| for (size_t i = 0, sz = bgMe->getGenericArgs().size(); i < sz; ++i) |
| if (!bgMe->getGenericArgs()[i]->isSpelledLike(bgThem->getGenericArgs()[i])) |
| return false; |
| return true; |
| } |
| |
| case TypeKind::Tuple: { |
| auto tMe = cast<TupleType>(me); |
| auto tThem = cast<TupleType>(them); |
| if (tMe->getNumElements() != tThem->getNumElements()) |
| return false; |
| for (size_t i = 0, sz = tMe->getNumElements(); i < sz; ++i) { |
| auto &myField = tMe->getElement(i), &theirField = tThem->getElement(i); |
| if (myField.hasInit() != theirField.hasInit()) |
| return false; |
| |
| if (myField.getName() != theirField.getName()) |
| return false; |
| |
| if (myField.isVararg() != theirField.isVararg()) |
| return false; |
| if (!myField.getType()->isSpelledLike(theirField.getType())) |
| return false; |
| } |
| return true; |
| } |
| |
| case TypeKind::SILFunction: |
| case TypeKind::SILBlockStorage: |
| case TypeKind::SILBox: |
| case TypeKind::PolymorphicFunction: |
| case TypeKind::GenericFunction: { |
| // Polymorphic function types should never be explicitly spelled. |
| return false; |
| } |
| |
| // TODO: change this to is same ExtInfo. |
| case TypeKind::Function: { |
| auto fMe = cast<FunctionType>(me); |
| auto fThem = cast<FunctionType>(them); |
| if (fMe->isAutoClosure() != fThem->isAutoClosure()) |
| return false; |
| if (fMe->getRepresentation() != fThem->getRepresentation()) |
| return false; |
| if (fMe->isNoReturn() != fThem->isNoReturn()) |
| return false; |
| if (!fMe->getInput()->isSpelledLike(fThem->getInput())) |
| return false; |
| if (!fMe->getResult()->isSpelledLike(fThem->getResult())) |
| return false; |
| return true; |
| } |
| |
| case TypeKind::LValue: { |
| auto lMe = cast<LValueType>(me); |
| auto lThem = cast<LValueType>(them); |
| return lMe->getObjectType()->isSpelledLike(lThem->getObjectType()); |
| } |
| case TypeKind::InOut: { |
| auto lMe = cast<InOutType>(me); |
| auto lThem = cast<InOutType>(them); |
| return lMe->getObjectType()->isSpelledLike(lThem->getObjectType()); |
| } |
| case TypeKind::ProtocolComposition: { |
| auto pMe = cast<ProtocolCompositionType>(me); |
| auto pThem = cast<ProtocolCompositionType>(them); |
| if (pMe->getProtocols().size() != pThem->getProtocols().size()) |
| return false; |
| for (size_t i = 0, sz = pMe->getProtocols().size(); i < sz; ++i) |
| if (!pMe->getProtocols()[i]->isSpelledLike(pThem->getProtocols()[i])) |
| return false; |
| return true; |
| } |
| case TypeKind::ExistentialMetatype: { |
| auto mMe = cast<ExistentialMetatypeType>(me); |
| auto mThem = cast<ExistentialMetatypeType>(them); |
| return mMe->getInstanceType()->isSpelledLike(mThem->getInstanceType()); |
| } |
| case TypeKind::Metatype: { |
| auto mMe = cast<MetatypeType>(me); |
| auto mThem = cast<MetatypeType>(them); |
| return mMe->getInstanceType()->isSpelledLike(mThem->getInstanceType()); |
| } |
| case TypeKind::Paren: { |
| auto pMe = cast<ParenType>(me); |
| auto pThem = cast<ParenType>(them); |
| return pMe->getUnderlyingType()->isSpelledLike(pThem->getUnderlyingType()); |
| } |
| case TypeKind::ArraySlice: |
| case TypeKind::Optional: |
| case TypeKind::ImplicitlyUnwrappedOptional: { |
| auto aMe = cast<SyntaxSugarType>(me); |
| auto aThem = cast<SyntaxSugarType>(them); |
| return aMe->getBaseType()->isSpelledLike(aThem->getBaseType()); |
| } |
| case TypeKind::Dictionary: { |
| auto aMe = cast<DictionaryType>(me); |
| auto aThem = cast<DictionaryType>(them); |
| return aMe->getKeyType()->isSpelledLike(aThem->getKeyType()) && |
| aMe->getValueType()->isSpelledLike(aThem->getValueType()); |
| } |
| case TypeKind::UnownedStorage: |
| case TypeKind::UnmanagedStorage: |
| case TypeKind::WeakStorage: { |
| auto rMe = cast<ReferenceStorageType>(me); |
| auto rThem = cast<ReferenceStorageType>(them); |
| return rMe->getReferentType()->isSpelledLike(rThem->getReferentType()); |
| } |
| } |
| |
| llvm_unreachable("Unknown type kind"); |
| } |
| |
| Type TypeBase::getSuperclass(LazyResolver *resolver) { |
| Type specializedTy; |
| ClassDecl *classDecl; |
| if (auto classTy = getAs<ClassType>()) { |
| classDecl = classTy->getDecl(); |
| if (auto parentTy = classTy->getParent()) { |
| if (parentTy->isSpecialized()) |
| specializedTy = parentTy; |
| } |
| } else if (auto boundTy = getAs<BoundGenericType>()) { |
| classDecl = dyn_cast<ClassDecl>(boundTy->getDecl()); |
| specializedTy = this; |
| } else if (auto archetype = getAs<ArchetypeType>()) { |
| return archetype->getSuperclass(); |
| } else if (auto dynamicSelfTy = getAs<DynamicSelfType>()) { |
| return dynamicSelfTy->getSelfType(); |
| } else { |
| // No other types have superclasses. |
| return nullptr; |
| } |
| |
| Type superclassTy; |
| if (classDecl) |
| superclassTy = classDecl->getSuperclass(); |
| |
| if (!specializedTy || !superclassTy) |
| return superclassTy; |
| |
| // FIXME: Lame to rely on archetypes in the substitution below. |
| superclassTy = ArchetypeBuilder::mapTypeIntoContext(classDecl, superclassTy); |
| |
| // If the type is specialized, we need to gather all of the substitutions. |
| // We've already dealt with the top level, but continue gathering |
| // specializations from the parent types. |
| TypeSubstitutionMap substitutions; |
| while (specializedTy) { |
| if (auto nominalTy = specializedTy->getAs<NominalType>()) { |
| specializedTy = nominalTy->getParent(); |
| continue; |
| } |
| |
| // Introduce substitutions for each of the generic parameters/arguments. |
| auto boundTy = specializedTy->castTo<BoundGenericType>(); |
| auto gp = boundTy->getDecl()->getGenericParams()->getParams(); |
| for (unsigned i = 0, n = boundTy->getGenericArgs().size(); i != n; ++i) { |
| auto archetype = gp[i]->getArchetype(); |
| substitutions[archetype] = boundTy->getGenericArgs()[i]; |
| } |
| |
| specializedTy = boundTy->getParent(); |
| } |
| |
| // Perform substitutions into the base type. |
| Module *module = classDecl->getModuleContext(); |
| return superclassTy.subst(module, substitutions, None); |
| } |
| |
| bool TypeBase::isSuperclassOf(Type ty, LazyResolver *resolver) { |
| // For there to be a superclass relationship, we must be a superclass, and |
| // the potential subtype must be a class or superclass-bounded archetype. |
| if (!getClassOrBoundGenericClass() || !ty->mayHaveSuperclass()) |
| return false; |
| |
| do { |
| if (ty->isEqual(this)) |
| return true; |
| if (ty->getAnyNominal() && ty->getAnyNominal()->isInvalid()) |
| return false; |
| } while ((ty = ty->getSuperclass(resolver))); |
| return false; |
| } |
| |
| static bool isBridgeableObjectType(CanType type) { |
| // Metatypes aren't always trivially bridgeable unless they've been |
| // SIL-lowered to have an @objc representation. |
| if (auto metaTy = dyn_cast<AnyMetatypeType>(type)) { |
| if (!metaTy->hasRepresentation()) |
| return false; |
| |
| if (metaTy->getRepresentation() != MetatypeRepresentation::ObjC) |
| return false; |
| |
| if (auto metatype = dyn_cast<MetatypeType>(type)) { |
| CanType instanceType = metatype.getInstanceType(); |
| return instanceType->mayHaveSuperclass(); |
| } |
| |
| // @objc protocol metatypes. |
| if (auto metatype = dyn_cast<ExistentialMetatypeType>(type)) { |
| return metatype.getInstanceType()->isObjCExistentialType(); |
| } |
| } |
| |
| // Classes and class-constrained archetypes. |
| if (type->mayHaveSuperclass()) |
| return true; |
| |
| // Pure-ObjC existential types. |
| if (type.isObjCExistentialType()) { |
| return true; |
| } |
| |
| // Blocks. |
| if (auto fnType = dyn_cast<AnyFunctionType>(type)) { |
| return fnType->getRepresentation() |
| == AnyFunctionType::Representation::Block; |
| } else if (auto fnType = dyn_cast<SILFunctionType>(type)) { |
| return fnType->getRepresentation() |
| == SILFunctionType::Representation::Block; |
| } |
| |
| return false; |
| } |
| |
| static bool hasRetainablePointerRepresentation(CanType type) { |
| // Look through one level of Optional<> or ImplicitlyUnwrappedOptional<>. |
| if (auto objType = type.getAnyOptionalObjectType()) { |
| type = objType; |
| } |
| |
| return isBridgeableObjectType(type); |
| } |
| |
| bool TypeBase::hasRetainablePointerRepresentation() { |
| return ::hasRetainablePointerRepresentation(getCanonicalType()); |
| } |
| |
| bool TypeBase::isBridgeableObjectType() { |
| return ::isBridgeableObjectType(getCanonicalType()); |
| } |
| |
| bool TypeBase::isPotentiallyBridgedValueType() { |
| if (auto nominal = getAnyNominal()) { |
| return isa<StructDecl>(nominal) || isa<EnumDecl>(nominal); |
| } |
| |
| return false; |
| } |
| |
| /// Is t1 not just a subtype of t2, but one such that its values are |
| /// trivially convertible to values of the other? |
| static bool canOverride(CanType t1, CanType t2, |
| bool allowUnsafeParameterOverride, |
| bool isParameter, |
| bool insideOptional, |
| LazyResolver *resolver) { |
| if (t1 == t2) return true; |
| |
| // Scalar-to-tuple and tuple-to-tuple. |
| if (auto tuple2 = dyn_cast<TupleType>(t2)) { |
| // We only ever look into singleton tuples on the RHS if we're |
| // certain that the LHS isn't also a singleton tuple. |
| auto tuple1 = dyn_cast<TupleType>(t1); |
| if (!tuple1 || tuple1->getNumElements() != tuple2->getNumElements()) { |
| if (tuple2->getNumElements() == 1) |
| return canOverride(t1, tuple2.getElementType(0), |
| allowUnsafeParameterOverride, |
| isParameter, |
| /*insideOptional=*/false, |
| resolver); |
| return false; |
| } |
| |
| for (auto i : indices(tuple1.getElementTypes())) { |
| if (!canOverride(tuple1.getElementType(i), |
| tuple2.getElementType(i), |
| allowUnsafeParameterOverride, |
| isParameter, |
| /*insideOptional=*/false, |
| resolver)) |
| return false; |
| } |
| return true; |
| } |
| |
| // Function-to-function. (Polymorphic functions?) |
| if (auto fn2 = dyn_cast<FunctionType>(t2)) { |
| auto fn1 = dyn_cast<FunctionType>(t1); |
| if (!fn1) |
| return false; |
| |
| // Allow ExtInfos to differ in these ways: |
| // - the overriding type may be noreturn even if the base type isn't |
| // - the base type may be throwing even if the overriding type isn't |
| auto ext1 = fn1->getExtInfo(); |
| auto ext2 = fn2->getExtInfo(); |
| if (ext2.throws()) ext1 = ext1.withThrows(true); |
| if (ext1.isNoReturn()) ext2 = ext2.withIsNoReturn(true); |
| if (ext1 != ext2) |
| return false; |
| |
| // Inputs are contravariant, results are covariant. |
| return (canOverride(fn2.getInput(), fn1.getInput(), |
| allowUnsafeParameterOverride, |
| /*isParameter=*/true, |
| /*insideOptional=*/false, |
| resolver) && |
| canOverride(fn1.getResult(), fn2.getResult(), |
| allowUnsafeParameterOverride, |
| /*isParameter=*/false, |
| /*insideOptional=*/false, |
| resolver)); |
| } |
| |
| // Don't unwrap optionals directly inside other optionals. |
| if (!insideOptional) { |
| // Value-to-optional and optional-to-optional. |
| if (auto obj2 = t2.getAnyOptionalObjectType()) { |
| // Optional-to-optional. |
| if (auto obj1 = t1.getAnyOptionalObjectType()) { |
| // Allow T? and T! to freely override one another. |
| return canOverride(obj1, obj2, allowUnsafeParameterOverride, |
| /*isParameter=*/false, |
| /*insideOptional=*/true, |
| resolver); |
| } |
| |
| // Value-to-optional. |
| return canOverride(t1, obj2, allowUnsafeParameterOverride, |
| /*isParameter=*/false, |
| /*insideOptional=*/true, |
| resolver); |
| } |
| } |
| |
| // Allow T to override T! in certain cases. |
| if (allowUnsafeParameterOverride && isParameter && !insideOptional) { |
| if (auto obj1 = t1->getImplicitlyUnwrappedOptionalObjectType()) { |
| t1 = obj1->getCanonicalType(); |
| if (t1 == t2) return true; |
| } |
| } |
| |
| // Class-to-class. |
| return t2->isSuperclassOf(t1, resolver); |
| } |
| |
| bool TypeBase::canOverride(Type other, bool allowUnsafeParameterOverride, |
| LazyResolver *resolver) { |
| return ::canOverride(getCanonicalType(), other->getCanonicalType(), |
| allowUnsafeParameterOverride, |
| /*isParameter=*/false, |
| /*insideOptional=*/false, |
| resolver); |
| } |
| |
| /// hasAnyDefaultValues - Return true if any of our elements has a default |
| /// value. |
| bool TupleType::hasAnyDefaultValues() const { |
| for (const TupleTypeElt &Elt : Elements) |
| if (Elt.hasInit()) |
| return true; |
| return false; |
| } |
| |
| /// getNamedElementId - If this tuple has a field with the specified name, |
| /// return the field index, otherwise return -1. |
| int TupleType::getNamedElementId(Identifier I) const { |
| for (unsigned i = 0, e = Elements.size(); i != e; ++i) { |
| if (Elements[i].getName() == I) |
| return i; |
| } |
| |
| // Otherwise, name not found. |
| return -1; |
| } |
| |
| /// getElementForScalarInit - If a tuple of this type can be initialized with a |
| /// scalar, return the field number that the scalar is assigned to. If not, |
| /// return -1. |
| int TupleType::getElementForScalarInit() const { |
| if (Elements.empty()) return -1; |
| |
| int FieldWithoutDefault = -1; |
| for (unsigned i = 0, e = Elements.size(); i != e; ++i) { |
| // Ignore fields with a default value. |
| if (Elements[i].hasInit()) continue; |
| |
| // If we already saw a non-vararg field missing a default value, then we |
| // cannot assign a scalar to this tuple. |
| if (FieldWithoutDefault != -1) { |
| // Vararg fields are okay; they'll just end up being empty. |
| if (Elements[i].isVararg()) |
| continue; |
| |
| return -1; |
| } |
| |
| // Otherwise, remember this field number. |
| FieldWithoutDefault = i; |
| } |
| |
| // If all the elements have default values, the scalar initializes the first |
| // value in the tuple. |
| return FieldWithoutDefault == -1 ? 0 : FieldWithoutDefault; |
| } |
| |
| /// If this tuple has a varargs element to it, return the base type of the |
| /// varargs element (i.e., if it is "Int...", this returns Int, not [Int]). |
| /// Otherwise, this returns Type(). |
| Type TupleType::getVarArgsBaseType() const { |
| for (unsigned i = 0, e = Elements.size(); i != e; ++i) { |
| if (Elements[i].isVararg()) |
| return Elements[i].getVarargBaseTy(); |
| } |
| |
| return Type(); |
| } |
| |
| |
| CanArchetypeType ArchetypeType::getNew(const ASTContext &Ctx, |
| ArchetypeType *Parent, |
| AssocTypeOrProtocolType AssocTypeOrProto, |
| Identifier Name, |
| ArrayRef<Type> ConformsTo, |
| Type Superclass, |
| bool isRecursive) { |
| // Gather the set of protocol declarations to which this archetype conforms. |
| SmallVector<ProtocolDecl *, 4> ConformsToProtos; |
| for (auto P : ConformsTo) { |
| addProtocols(P, ConformsToProtos); |
| } |
| ProtocolType::canonicalizeProtocols(ConformsToProtos); |
| |
| auto arena = AllocationArena::Permanent; |
| return CanArchetypeType( |
| new (Ctx, arena) ArchetypeType(Ctx, Parent, AssocTypeOrProto, Name, |
| Ctx.AllocateCopy(ConformsToProtos), |
| Superclass, isRecursive)); |
| } |
| |
| CanArchetypeType |
| ArchetypeType::getNew(const ASTContext &Ctx, ArchetypeType *Parent, |
| AssocTypeOrProtocolType AssocTypeOrProto, |
| Identifier Name, |
| SmallVectorImpl<ProtocolDecl *> &ConformsTo, |
| Type Superclass, bool isRecursive) { |
| // Gather the set of protocol declarations to which this archetype conforms. |
| ProtocolType::canonicalizeProtocols(ConformsTo); |
| |
| auto arena = AllocationArena::Permanent; |
| return CanArchetypeType( |
| new (Ctx, arena) ArchetypeType(Ctx, Parent, AssocTypeOrProto, Name, |
| Ctx.AllocateCopy(ConformsTo), |
| Superclass, isRecursive)); |
| } |
| |
| bool ArchetypeType::requiresClass() const { |
| if (Superclass) |
| return true; |
| for (ProtocolDecl *conformed : getConformsTo()) |
| if (conformed->requiresClass()) |
| return true; |
| return false; |
| } |
| |
| void ArchetypeType::resolveNestedType( |
| std::pair<Identifier, NestedType> &nested) const { |
| auto &ctx = const_cast<ArchetypeType *>(this)->getASTContext(); |
| auto lazyArchetype = ctx.getLazyArchetype(this); |
| nested.second = lazyArchetype.second->getNestedType(nested.first, |
| *lazyArchetype.first) |
| ->getType(*lazyArchetype.first); |
| } |
| |
| namespace { |
| /// \brief Function object that orders archetypes by name. |
| struct OrderArchetypeByName { |
| using NestedType = ArchetypeType::NestedType; |
| bool operator()(std::pair<Identifier, NestedType> X, |
| std::pair<Identifier, NestedType> Y) const { |
| return X.first.str() < Y.first.str(); |
| } |
| |
| bool operator()(std::pair<Identifier, NestedType> X, |
| Identifier Y) const { |
| return X.first.str() < Y.str(); |
| } |
| |
| bool operator()(Identifier X, |
| std::pair<Identifier, NestedType> Y) const { |
| return X.str() < Y.first.str(); |
| } |
| |
| bool operator()(Identifier X, Identifier Y) const { |
| return X.str() < Y.str(); |
| } |
| }; |
| } |
| |
| ArchetypeType::NestedType ArchetypeType::getNestedType(Identifier Name) const { |
| auto Pos = std::lower_bound(NestedTypes.begin(), NestedTypes.end(), Name, |
| OrderArchetypeByName()); |
| if ((Pos == NestedTypes.end() || Pos->first != Name) && this->isRecursive) { |
| if (Name == this->getName()) { |
| NestedType rec = NestedType::forArchetype((ArchetypeType*)this); |
| |
| return rec; |
| } else { |
| auto conformances = this->getConformsTo(); |
| |
| for (auto conformance : conformances) { |
| auto conformanceType = conformance->getType().getPointer(); |
| |
| if (auto metatypeType = dyn_cast<MetatypeType>(conformanceType)) { |
| conformanceType = metatypeType->getInstanceType().getPointer(); |
| |
| if (auto protocolType = dyn_cast<ProtocolType>(conformanceType)) { |
| conformanceType = protocolType->getDecl()->getProtocolSelf() |
| ->getArchetype(); |
| } |
| } |
| |
| if (auto conformedArchetype = dyn_cast<ArchetypeType>(conformanceType)){ |
| return conformedArchetype->getNestedType(Name); |
| } |
| } |
| } |
| } |
| |
| if (Pos == NestedTypes.end() || Pos->first != Name) |
| return NestedType::forConcreteType( |
| ErrorType::get( |
| const_cast<ArchetypeType *>(this)->getASTContext())); |
| |
| // If the type is null, lazily resolve it. |
| if (!Pos->second) { |
| resolveNestedType(*Pos); |
| } |
| |
| return Pos->second; |
| } |
| |
| bool ArchetypeType::hasNestedType(Identifier Name) const { |
| auto Pos = std::lower_bound(NestedTypes.begin(), NestedTypes.end(), Name, |
| OrderArchetypeByName()); |
| return Pos != NestedTypes.end() && Pos->first == Name; |
| } |
| |
| ArrayRef<std::pair<Identifier, ArchetypeType::NestedType>> |
| ArchetypeType::getNestedTypes(bool resolveTypes) const { |
| if (resolveTypes) { |
| for (auto &nested : NestedTypes) { |
| if (!nested.second) |
| resolveNestedType(nested); |
| } |
| } |
| |
| return NestedTypes; |
| } |
| |
| void ArchetypeType::setNestedTypes( |
| ASTContext &Ctx, |
| MutableArrayRef<std::pair<Identifier, NestedType>> Nested) { |
| std::sort(Nested.begin(), Nested.end(), OrderArchetypeByName()); |
| NestedTypes = Ctx.AllocateCopy(Nested); |
| } |
| |
| static void collectFullName(const ArchetypeType *Archetype, |
| SmallVectorImpl<char> &Result) { |
| if (auto Parent = Archetype->getParent()) { |
| collectFullName(Parent, Result); |
| Result.push_back('.'); |
| } |
| Result.append(Archetype->getName().str().begin(), |
| Archetype->getName().str().end()); |
| } |
| |
| std::string ArchetypeType::getFullName() const { |
| llvm::SmallString<64> Result; |
| collectFullName(this, Result); |
| return Result.str().str(); |
| } |
| |
| void ProtocolCompositionType::Profile(llvm::FoldingSetNodeID &ID, |
| ArrayRef<Type> Protocols) { |
| for (auto P : Protocols) |
| ID.AddPointer(P.getPointer()); |
| } |
| |
| bool ProtocolType::requiresClass() const { |
| return getDecl()->requiresClass(); |
| } |
| |
| void ProtocolCompositionType::getAnyExistentialTypeProtocols( |
| SmallVectorImpl<ProtocolDecl *> &protos) { |
| // The canonical type for a protocol composition canonicalizes the |
| // order of the protocols. |
| auto canonical = cast<ProtocolCompositionType>(getCanonicalType()); |
| canonical.getAnyExistentialTypeProtocols(protos); |
| } |
| |
| bool ProtocolCompositionType::requiresClass() const { |
| for (Type t : getProtocols()) { |
| if (const ProtocolType *proto = t->getAs<ProtocolType>()) { |
| if (proto->requiresClass()) |
| return true; |
| } else { |
| if (t->castTo<ProtocolCompositionType>()->requiresClass()) |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| Type ProtocolCompositionType::get(const ASTContext &C, |
| ArrayRef<Type> ProtocolTypes) { |
| for (Type t : ProtocolTypes) { |
| if (!t->isCanonical()) |
| return build(C, ProtocolTypes); |
| } |
| |
| SmallVector<ProtocolDecl *, 4> Protocols; |
| for (Type t : ProtocolTypes) |
| addProtocols(t, Protocols); |
| |
| // Minimize the set of protocols composed together. |
| ProtocolType::canonicalizeProtocols(Protocols); |
| |
| // If one protocol remains, its nominal type is the canonical type. |
| if (Protocols.size() == 1) |
| return Protocols.front()->getDeclaredType(); |
| |
| // Form the set of canonical protocol types from the protocol |
| // declarations, and use that to buid the canonical composition type. |
| SmallVector<Type, 4> CanProtocolTypes; |
| std::transform(Protocols.begin(), Protocols.end(), |
| std::back_inserter(CanProtocolTypes), |
| [](ProtocolDecl *Proto) { |
| return Proto->getDeclaredType(); |
| }); |
| |
| return build(C, CanProtocolTypes); |
| } |
| |
| ArrayRef<GenericTypeParamDecl *> |
| PolymorphicFunctionType::getGenericParameters() const { |
| return Params->getParams(); |
| } |
| |
| FunctionType *PolymorphicFunctionType::substGenericArgs(Module *module, |
| ArrayRef<Type> args) { |
| TypeSubstitutionMap map; |
| for (auto ¶m : getGenericParams().getNestedGenericParams()) { |
| map.insert(std::make_pair(param->getArchetype(), args.front())); |
| args = args.slice(1); |
| } |
| |
| assert(args.empty() |
| && "number of args did not match number of generic params"); |
| |
| Type input = getInput().subst(module, map, SubstFlags::IgnoreMissing); |
| Type result = getResult().subst(module, map, SubstFlags::IgnoreMissing); |
| return FunctionType::get(input, result, getExtInfo()); |
| } |
| |
| TypeSubstitutionMap |
| GenericParamList::getSubstitutionMap(ArrayRef<swift::Substitution> Subs) const { |
| TypeSubstitutionMap map; |
| |
| for (auto arch : getAllNestedArchetypes()) { |
| auto sub = Subs.front(); |
| Subs = Subs.slice(1); |
| |
| map.insert({arch, sub.getReplacement()}); |
| } |
| |
| assert(Subs.empty() && "did not use all substitutions?!"); |
| return map; |
| } |
| |
| FunctionType *PolymorphicFunctionType::substGenericArgs(Module *module, |
| ArrayRef<Substitution> subs) { |
| TypeSubstitutionMap map |
| = getGenericParams().getSubstitutionMap(subs); |
| |
| Type input = getInput().subst(module, map, SubstFlags::IgnoreMissing); |
| Type result = getResult().subst(module, map, SubstFlags::IgnoreMissing); |
| return FunctionType::get(input, result, getExtInfo()); |
| } |
| |
| FunctionType * |
| GenericFunctionType::substGenericArgs(Module *M, ArrayRef<Type> args) const { |
| auto params = getGenericParams(); |
| assert(args.size() == params.size()); |
| |
| TypeSubstitutionMap subs; |
| for (size_t i = 0, e = args.size(); i != e; ++i) { |
| subs.insert(std::make_pair(params[i], args[i])); |
| } |
| |
| Type input = getInput().subst(M, subs, SubstFlags::IgnoreMissing); |
| Type result = getResult().subst(M, subs, SubstFlags::IgnoreMissing); |
| return FunctionType::get(input, result, getExtInfo()); |
| } |
| |
| AnyFunctionType * |
| GenericFunctionType::partialSubstGenericArgs(Module *M, ArrayRef<Type> args) |
| const { |
| auto params = getGenericParams(); |
| |
| // If we're fully applying the generic params, fall through to |
| // substGenericArgs. |
| if (args.size() == params.size()) |
| return substGenericArgs(M, args); |
| |
| assert(args.size() < params.size()); |
| |
| TypeSubstitutionMap subs; |
| for (size_t i = 0, e = args.size(); i != e; ++i) { |
| subs.insert(std::make_pair(params[i], args[i])); |
| } |
| |
| // Get the slice of the generic parameters and requirements we haven't |
| // applied. |
| auto appliedParams = params.slice(0, args.size()); |
| auto unappliedParams = params.slice(args.size()); |
| |
| // Drop requirements rooted in the applied generic parameters. |
| SmallVector<Requirement, 4> unappliedReqts; |
| |
| auto rootType = [](Type t) -> TypeBase* { |
| while (auto dmt = t->getAs<DependentMemberType>()) { |
| t = dmt->getBase(); |
| } |
| return t.getPointer(); |
| }; |
| |
| auto rootedInAppliedParam = [&](Type t) -> bool { |
| return std::find(appliedParams.begin(), appliedParams.end(), rootType(t)) |
| != appliedParams.end(); |
| }; |
| |
| for (auto &reqt : getRequirements()) { |
| switch (reqt.getKind()) { |
| case RequirementKind::Conformance: |
| case RequirementKind::WitnessMarker: |
| // Substituting the parameter eliminates conformance constraints rooted |
| // in the parameter. |
| if (rootedInAppliedParam(reqt.getFirstType())) |
| continue; |
| break; |
| |
| case RequirementKind::SameType: { |
| // Same-type constraints are eliminated if both sides of the constraint |
| // are rooted in substituted parameters. |
| if (rootedInAppliedParam(reqt.getFirstType()) |
| && rootedInAppliedParam(reqt.getSecondType())) |
| continue; |
| |
| // Otherwise, substitute the constrained types. |
| unappliedReqts.push_back( |
| Requirement(RequirementKind::SameType, |
| reqt.getFirstType().subst(M, subs, |
| SubstFlags::IgnoreMissing), |
| reqt.getSecondType().subst(M, subs, |
| SubstFlags::IgnoreMissing))); |
| continue; |
| } |
| } |
| unappliedReqts.push_back(reqt); |
| } |
| |
| GenericSignature *sig = GenericSignature::get(unappliedParams, |
| unappliedReqts); |
| |
| Type input = getInput().subst(M, subs, SubstFlags::IgnoreMissing); |
| Type result = getResult().subst(M, subs, SubstFlags::IgnoreMissing); |
| return GenericFunctionType::get(sig, input, result, getExtInfo()); |
| } |
| |
| FunctionType * |
| GenericFunctionType::substGenericArgs(Module *M, ArrayRef<Substitution> args) { |
| auto params = getGenericParams(); |
| (void)params; |
| |
| TypeSubstitutionMap subs |
| = getGenericSignature()->getSubstitutionMap(args); |
| |
| Type input = getInput().subst(M, subs, SubstFlags::IgnoreMissing); |
| Type result = getResult().subst(M, subs, SubstFlags::IgnoreMissing); |
| return FunctionType::get(input, result, getExtInfo()); |
| } |
| |
| static Type getMemberForBaseType(Module *module, |
| Type substBase, |
| AssociatedTypeDecl *assocType, |
| Identifier name, |
| SubstOptions options) { |
| // Error recovery path. |
| if (substBase->isOpenedExistential()) |
| return ErrorType::get(module->getASTContext()); |
| |
| // If the parent is an archetype, extract the child archetype with the |
| // given name. |
| if (auto archetypeParent = substBase->getAs<ArchetypeType>()) { |
| if (!archetypeParent->hasNestedType(name) && |
| archetypeParent->getParent()->isSelfDerived()) { |
| return archetypeParent->getParent()->getNestedTypeValue(name); |
| } |
| |
| return archetypeParent->getNestedTypeValue(name); |
| } |
| |
| // If the parent is a type variable, retrieve its member type |
| // variable. |
| if (auto typeVarParent = substBase->getAs<TypeVariableType>()) { |
| assert(assocType && "Missing associated type"); |
| return substBase->getASTContext().getTypeVariableMemberType(typeVarParent, |
| assocType); |
| } |
| |
| // Retrieve the member type with the given name. |
| |
| // Tuples don't have member types. |
| if (substBase->is<TupleType>()) { |
| return Type(); |
| } |
| |
| // If the parent is dependent, create a dependent member type. |
| if (substBase->isTypeParameter()) { |
| if (assocType) |
| return DependentMemberType::get(substBase, assocType, |
| substBase->getASTContext()); |
| else |
| return DependentMemberType::get(substBase, name, |
| substBase->getASTContext()); |
| } |
| |
| // If we know the associated type, look in the witness table. |
| LazyResolver *resolver = substBase->getASTContext().getLazyResolver(); |
| if (assocType) { |
| auto proto = assocType->getProtocol(); |
| // FIXME: Introduce substituted type node here? |
| auto conformance = module->lookupConformance(substBase, proto, resolver); |
| switch (conformance.getInt()) { |
| case ConformanceKind::DoesNotConform: |
| case ConformanceKind::UncheckedConforms: |
| return Type(); |
| |
| case ConformanceKind::Conforms: |
| // If we have an unsatisfied type witness while we're checking the |
| // conformances we're supposed to skip this conformance's unsatisfied type |
| // witnesses, and we have an unsatisfied type witness, return |
| // "missing". |
| assert(conformance.getPointer()); |
| if (conformance.getPointer()->getRootNormalConformance()->getState() |
| == ProtocolConformanceState::CheckingTypeWitnesses && |
| !conformance.getPointer()->hasTypeWitness(assocType, nullptr)) |
| return Type(); |
| |
| return conformance.getPointer()->getTypeWitness(assocType, resolver) |
| .getReplacement(); |
| } |
| } |
| |
| // FIXME: This is a fallback. We want the above, conformance-based |
| // result to be the only viable path. |
| if (resolver) { |
| if (Type memberType = resolver->resolveMemberType(module, substBase, name)){ |
| return memberType; |
| } |
| } |
| |
| return Type(); |
| } |
| |
| Type DependentMemberType::substBaseType(Module *module, |
| Type substBase, |
| LazyResolver *resolver) { |
| if (substBase.getPointer() == getBase().getPointer() && |
| substBase->hasTypeParameter()) |
| return this; |
| |
| return getMemberForBaseType(module, substBase, getAssocType(), getName(), |
| None); |
| } |
| |
| Type Type::subst(Module *module, TypeSubstitutionMap &substitutions, |
| SubstOptions options) const { |
| /// Return the original type or a null type, depending on the 'ignoreMissing' |
| /// flag. |
| auto failed = [&](Type t){ |
| return options.contains(SubstFlags::IgnoreMissing) ? t : Type(); |
| }; |
| |
| return transform([&](Type type) -> Type { |
| assert(!isa<SILFunctionType>(type.getPointer()) && |
| "should not be doing AST type-substitution on a lowered SIL type;" |
| "use SILType::subst"); |
| |
| // We only substitute for substitutable types and dependent member types. |
| |
| // For dependent member types, we may need to look up the member if the |
| // base is resolved to a non-dependent type. |
| if (auto depMemTy = type->getAs<DependentMemberType>()) { |
| auto newBase = depMemTy->getBase().subst(module, substitutions, options); |
| if (!newBase) |
| return failed(type); |
| |
| if (Type r = getMemberForBaseType(module, newBase, |
| depMemTy->getAssocType(), |
| depMemTy->getName(), options)) |
| return r; |
| |
| return failed(type); |
| } |
| |
| auto substOrig = type->getAs<SubstitutableType>(); |
| if (!substOrig) |
| return type; |
| |
| // If we have a substitution for this type, use it. |
| auto key = substOrig->getCanonicalType()->castTo<SubstitutableType>(); |
| auto known = substitutions.find(key); |
| if (known != substitutions.end() && known->second) |
| return SubstitutedType::get(type, known->second, |
| module->getASTContext()); |
| |
| // If we don't have a substitution for this type and it doesn't have a |
| // parent, then we're not substituting it. |
| auto parent = substOrig->getParent(); |
| if (!parent) |
| return type; |
| |
| // Substitute into the parent type. |
| Type substParent = Type(parent).subst(module, substitutions, options); |
| if (!substParent) |
| return Type(); |
| |
| // If the parent didn't change, we won't change. |
| if (substParent.getPointer() == parent) |
| return type; |
| |
| // Get the associated type reference from a child archetype. |
| AssociatedTypeDecl *assocType = nullptr; |
| if (auto archetype = substOrig->getAs<ArchetypeType>()) { |
| assocType = archetype->getAssocType(); |
| } |
| |
| |
| if (Type r = getMemberForBaseType(module, substParent, assocType, |
| substOrig->getName(), options)) |
| return r; |
| return failed(type); |
| }); |
| } |
| |
| TypeSubstitutionMap TypeBase::getMemberSubstitutions(DeclContext *dc) { |
| |
| // Ignore lvalues in the base type. |
| Type baseTy(getRValueType()); |
| |
| // Look through the metatype; it has no bearing on the result. |
| if (auto metaBase = baseTy->getAs<AnyMetatypeType>()) { |
| baseTy = metaBase->getInstanceType()->getRValueType(); |
| } |
| |
| // The resulting set of substitutions. Always use this to ensure we |
| // don't miss out on NRVO anywhere. |
| TypeSubstitutionMap substitutions; |
| |
| // If the member is part of a protocol or extension thereof, we need |
| // to substitute in the type of Self. |
| if (dc->isProtocolOrProtocolExtensionContext()) { |
| // We only substitute into archetypes for now for protocols. |
| // FIXME: This seems like an odd restriction. Whatever is depending on |
| // this, shouldn't. |
| if (!baseTy->is<ArchetypeType>() && isa<ProtocolDecl>(dc)) |
| return substitutions; |
| |
| // FIXME: This feels painfully inefficient. We're creating a dense map |
| // for a single substitution. |
| substitutions[dc->getProtocolSelf()->getArchetype()] = baseTy; |
| substitutions[dc->getProtocolSelf()->getDeclaredType() |
| ->getCanonicalType()->castTo<GenericTypeParamType>()] |
| = baseTy; |
| return substitutions; |
| } |
| |
| // Extract the lazy resolver. |
| LazyResolver *resolver = dc->getASTContext().getLazyResolver(); |
| |
| // Find the superclass type with the context matching that of the member. |
| auto ownerNominal = dc->isNominalTypeOrNominalTypeExtensionContext(); |
| while (!baseTy->is<ErrorType>() && |
| baseTy->getAnyNominal() != ownerNominal) { |
| baseTy = baseTy->getSuperclass(resolver); |
| assert(baseTy && "Couldn't find appropriate context"); |
| } |
| |
| // If the base type isn't specialized, there's nothing to substitute. |
| if (!baseTy->isSpecialized()) |
| return substitutions; |
| |
| // Gather all of the substitutions for all levels of generic arguments. |
| GenericParamList *curGenericParams = dc->getGenericParamsOfContext(); |
| while (baseTy) { |
| // For a bound generic type, gather the generic parameter -> generic |
| // argument substitutions. |
| if (auto boundGeneric = baseTy->getAs<BoundGenericType>()) { |
| auto params = curGenericParams->getParams(); |
| auto args = boundGeneric->getGenericArgs(); |
| for (unsigned i = 0, n = args.size(); i != n; ++i) { |
| substitutions[params[i]->getDeclaredType()->getCanonicalType() |
| ->castTo<GenericTypeParamType>()] |
| = args[i]; |
| } |
| |
| // Continue looking into the parent. |
| baseTy = boundGeneric->getParent(); |
| curGenericParams = curGenericParams->getOuterParameters(); |
| continue; |
| } |
| |
| // Continue looking into the parent. |
| baseTy = baseTy->castTo<NominalType>()->getParent(); |
| } |
| |
| return substitutions; |
| } |
| |
| Type TypeBase::getTypeOfMember(Module *module, const ValueDecl *member, |
| LazyResolver *resolver, Type memberType) { |
| // If no member type was provided, use the member's type. |
| if (!memberType) |
| memberType = member->getInterfaceType(); |
| |
| return getTypeOfMember(module, memberType, member->getDeclContext()); |
| } |
| |
| Type TypeBase::getTypeOfMember(Module *module, Type memberType, |
| DeclContext *memberDC) { |
| // If the member is not part of a type, there's nothing to substitute. |
| if (!memberDC->isTypeContext()) |
| return memberType; |
| |
| // Compute the set of member substitutions to apply. |
| TypeSubstitutionMap substitutions = getMemberSubstitutions(memberDC); |
| if (substitutions.empty()) |
| return memberType; |
| |
| // Perform the substitutions. |
| return memberType.subst(module, substitutions, None); |
| } |
| |
| Identifier DependentMemberType::getName() const { |
| if (NameOrAssocType.is<Identifier>()) |
| return NameOrAssocType.get<Identifier>(); |
| |
| return NameOrAssocType.get<AssociatedTypeDecl *>()->getName(); |
| } |
| |
| static bool transformSILResult(SILResultInfo &result, bool &changed, |
| const std::function<Type(Type)> &fn) { |
| Type transType = result.getType().transform(fn); |
| if (!transType) return true; |
| |
| CanType canTransType = transType->getCanonicalType(); |
| if (canTransType != result.getType()) { |
| changed = true; |
| result = result.getWithType(canTransType); |
| } |
| return false; |
| } |
| |
| static bool transformSILParameter(SILParameterInfo ¶m, bool &changed, |
| const std::function<Type(Type)> &fn) { |
| Type transType = param.getType().transform(fn); |
| if (!transType) return true; |
| |
| CanType canTransType = transType->getCanonicalType(); |
| if (canTransType != param.getType()) { |
| changed = true; |
| param = param.getWithType(canTransType); |
| } |
| return false; |
| } |
| |
| Type Type::transform(const std::function<Type(Type)> &fn) const { |
| // Transform this type node. |
| Type transformed = fn(*this); |
| |
| // If the client changed the type, we're done. |
| if (!transformed || transformed.getPointer() != getPointer()) |
| return transformed; |
| |
| // Recursive into children of this type. |
| TypeBase *base = getPointer(); |
| switch (base->getKind()) { |
| #define ALWAYS_CANONICAL_TYPE(Id, Parent) \ |
| case TypeKind::Id: |
| #define TYPE(Id, Parent) |
| #include "swift/AST/TypeNodes.def" |
| case TypeKind::Error: |
| case TypeKind::Unresolved: |
| case TypeKind::TypeVariable: |
| case TypeKind::AssociatedType: |
| case TypeKind::GenericTypeParam: |
| return *this; |
| |
| case TypeKind::Enum: |
| case TypeKind::Struct: |
| case TypeKind::Class: { |
| auto nominalTy = cast<NominalType>(base); |
| if (auto parentTy = nominalTy->getParent()) { |
| parentTy = parentTy.transform(fn); |
| if (!parentTy) |
| return Type(); |
| |
| if (parentTy.getPointer() == nominalTy->getParent().getPointer()) |
| return *this; |
| |
| return NominalType::get(nominalTy->getDecl(), parentTy, |
| Ptr->getASTContext()); |
| } |
| |
| return *this; |
| } |
| |
| case TypeKind::SILBlockStorage: { |
| auto storageTy = cast<SILBlockStorageType>(base); |
| Type transCap = storageTy->getCaptureType().transform(fn); |
| if (!transCap) |
| return Type(); |
| CanType canTransCap = transCap->getCanonicalType(); |
| if (canTransCap != storageTy->getCaptureType()) |
| return SILBlockStorageType::get(canTransCap); |
| return storageTy; |
| } |
| |
| case TypeKind::SILBox: { |
| auto storageTy = cast<SILBoxType>(base); |
| Type transBoxed = storageTy->getBoxedType().transform(fn); |
| if (!transBoxed) |
| return Type(); |
| CanType canTransBoxed = transBoxed->getCanonicalType(); |
| if (canTransBoxed != storageTy->getBoxedType()) |
| return SILBoxType::get(canTransBoxed); |
| return storageTy; |
| } |
| |
| case TypeKind::SILFunction: { |
| auto fnTy = cast<SILFunctionType>(base); |
| bool changed = false; |
| |
| SILResultInfo transResult = fnTy->getResult(); |
| if (transformSILResult(transResult, changed, fn)) return Type(); |
| |
| SmallVector<SILParameterInfo, 8> transInterfaceParams; |
| for (SILParameterInfo param : fnTy->getParameters()) { |
| if (transformSILParameter(param, changed, fn)) return Type(); |
| transInterfaceParams.push_back(param); |
| } |
| |
| Optional<SILResultInfo> transErrorResult; |
| if (fnTy->hasErrorResult()) { |
| SILResultInfo result = fnTy->getErrorResult(); |
| if (transformSILResult(result, changed, fn)) return Type(); |
| transErrorResult = result; |
| } |
| |
| if (!changed) return *this; |
| |
| return SILFunctionType::get(fnTy->getGenericSignature(), |
| fnTy->getExtInfo(), |
| fnTy->getCalleeConvention(), |
| transInterfaceParams, |
| transResult, |
| transErrorResult, |
| Ptr->getASTContext()); |
| } |
| |
| case TypeKind::UnownedStorage: |
| case TypeKind::UnmanagedStorage: |
| case TypeKind::WeakStorage: { |
| auto storageTy = cast<ReferenceStorageType>(base); |
| Type refTy = storageTy->getReferentType(); |
| Type substRefTy = refTy.transform(fn); |
| if (!substRefTy) |
| return Type(); |
| |
| if (substRefTy.getPointer() == refTy.getPointer()) |
| return *this; |
| |
| return ReferenceStorageType::get(substRefTy, storageTy->getOwnership(), |
| Ptr->getASTContext()); |
| } |
| |
| case TypeKind::UnboundGeneric: { |
| auto unbound = cast<UnboundGenericType>(base); |
| Type substParentTy; |
| if (auto parentTy = unbound->getParent()) { |
| substParentTy = parentTy.transform(fn); |
| if (!substParentTy) |
| return Type(); |
| |
| if (substParentTy.getPointer() == parentTy.getPointer()) |
| return *this; |
| |
| return UnboundGenericType::get(unbound->getDecl(), substParentTy, |
| Ptr->getASTContext()); |
| } |
| |
| return *this; |
| } |
| |
| case TypeKind::BoundGenericClass: |
| case TypeKind::BoundGenericEnum: |
| case TypeKind::BoundGenericStruct: { |
| auto bound = cast<BoundGenericType>(base); |
| SmallVector<Type, 4> substArgs; |
| bool anyChanged = false; |
| Type substParentTy; |
| if (auto parentTy = bound->getParent()) { |
| substParentTy = parentTy.transform(fn); |
| if (!substParentTy) |
| return Type(); |
| |
| if (substParentTy.getPointer() != parentTy.getPointer()) |
| anyChanged = true; |
| } |
| |
| for (auto arg : bound->getGenericArgs()) { |
| Type substArg = arg.transform(fn); |
| if (!substArg) |
| return Type(); |
| substArgs.push_back(substArg); |
| if (substArg.getPointer() != arg.getPointer()) |
| anyChanged = true; |
| } |
| |
| if (!anyChanged) |
| return *this; |
| |
| return BoundGenericType::get(bound->getDecl(), substParentTy, substArgs); |
| } |
| |
| case TypeKind::ExistentialMetatype: { |
| auto meta = cast<ExistentialMetatypeType>(base); |
| auto instanceTy = meta->getInstanceType().transform(fn); |
| if (!instanceTy) |
| return Type(); |
| |
| if (instanceTy.getPointer() == meta->getInstanceType().getPointer()) |
| return *this; |
| |
| if (meta->hasRepresentation()) |
| return ExistentialMetatypeType::get(instanceTy, |
| meta->getRepresentation()); |
| return ExistentialMetatypeType::get(instanceTy); |
| } |
| |
| case TypeKind::Metatype: { |
| auto meta = cast<MetatypeType>(base); |
| auto instanceTy = meta->getInstanceType().transform(fn); |
| if (!instanceTy) |
| return Type(); |
| |
| if (instanceTy.getPointer() == meta->getInstanceType().getPointer()) |
| return *this; |
| |
| if (meta->hasRepresentation()) |
| return MetatypeType::get(instanceTy, meta->getRepresentation()); |
| return MetatypeType::get(instanceTy); |
| } |
| |
| case TypeKind::DynamicSelf: { |
| auto dynamicSelf = cast<DynamicSelfType>(base); |
| auto selfTy = dynamicSelf->getSelfType().transform(fn); |
| if (!selfTy) |
| return Type(); |
| |
| if (selfTy.getPointer() == dynamicSelf->getSelfType().getPointer()) |
| return *this; |
| |
| return DynamicSelfType::get(selfTy, selfTy->getASTContext()); |
| } |
| |
| case TypeKind::NameAlias: { |
| auto alias = cast<NameAliasType>(base); |
| auto underlyingTy = alias->getDecl()->getUnderlyingType().transform(fn); |
| if (!underlyingTy) |
| return Type(); |
| |
| if (underlyingTy.getPointer() == |
| alias->getDecl()->getUnderlyingType().getPointer()) |
| return *this; |
| |
| return SubstitutedType::get(*this, underlyingTy, Ptr->getASTContext()); |
| } |
| |
| case TypeKind::Paren: { |
| auto paren = cast<ParenType>(base); |
| Type underlying = paren->getUnderlyingType().transform(fn); |
| if (!underlying) |
| return Type(); |
| |
| if (underlying.getPointer() == paren->getUnderlyingType().getPointer()) |
| return *this; |
| |
| return ParenType::get(Ptr->getASTContext(), underlying); |
| } |
| |
| case TypeKind::Tuple: { |
| auto tuple = cast<TupleType>(base); |
| bool anyChanged = false; |
| SmallVector<TupleTypeElt, 4> elements; |
| unsigned Index = 0; |
| for (const auto &elt : tuple->getElements()) { |
| Type eltTy = elt.getType().transform(fn); |
| if (!eltTy) |
| return Type(); |
| |
| // If nothing has changed, just keep going. |
| if (!anyChanged && eltTy.getPointer() == elt.getType().getPointer()) { |
| ++Index; |
| continue; |
| } |
| |
| // If this is the first change we've seen, copy all of the previous |
| // elements. |
| if (!anyChanged) { |
| // Copy all of the previous elements. |
| for (unsigned I = 0; I != Index; ++I) { |
| const TupleTypeElt &FromElt =tuple->getElement(I); |
| elements.push_back(TupleTypeElt(FromElt.getType(), FromElt.getName(), |
| FromElt.getDefaultArgKind(), |
| FromElt.isVararg())); |
| } |
| |
| anyChanged = true; |
| } |
| |
| // Add the new tuple element, with the new type, no initializer, |
| elements.push_back(TupleTypeElt(eltTy, elt.getName(), |
| elt.getDefaultArgKind(), elt.isVararg())); |
| ++Index; |
| } |
| |
| if (!anyChanged) |
| return *this; |
| |
| return TupleType::get(elements, Ptr->getASTContext()); |
| } |
| |
| |
| case TypeKind::DependentMember: { |
| auto dependent = cast<DependentMemberType>(base); |
| auto dependentBase = dependent->getBase().transform(fn); |
| if (!dependentBase) |
| return Type(); |
| |
| if (dependentBase.getPointer() == dependent->getBase().getPointer()) |
| return *this; |
| |
| if (auto assocType = dependent->getAssocType()) |
| return DependentMemberType::get(dependentBase, assocType, |
| Ptr->getASTContext()); |
| |
| return DependentMemberType::get(dependentBase, dependent->getName(), |
| Ptr->getASTContext()); |
| } |
| |
| case TypeKind::Substituted: { |
| auto substAT = cast<SubstitutedType>(base); |
| auto substTy = substAT->getReplacementType().transform(fn); |
| if (!substTy) |
| return Type(); |
| |
| if (substTy.getPointer() == substAT->getReplacementType().getPointer()) |
| return *this; |
| |
| return SubstitutedType::get(substAT->getOriginal(), substTy, |
| Ptr->getASTContext()); |
| } |
| |
| case TypeKind::Function: |
| case TypeKind::PolymorphicFunction: { |
| auto function = cast<AnyFunctionType>(base); |
| auto inputTy = function->getInput().transform(fn); |
| if (!inputTy) |
| return Type(); |
| auto resultTy = function->getResult().transform(fn); |
| if (!resultTy) |
| return Type(); |
| |
| if (inputTy.getPointer() == function->getInput().getPointer() && |
| resultTy.getPointer() == function->getResult().getPointer()) |
| return *this; |
| |
| if (auto polyFn = dyn_cast<PolymorphicFunctionType>(function)) { |
| return PolymorphicFunctionType::get(inputTy, resultTy, |
| &polyFn->getGenericParams(), |
| function->getExtInfo()); |
| } |
| |
| return FunctionType::get(inputTy, resultTy, |
| function->getExtInfo()); |
| } |
| |
| case TypeKind::GenericFunction: { |
| GenericFunctionType *function = cast<GenericFunctionType>(base); |
| bool anyChanges = false; |
| |
| // Transform generic parameters. |
| SmallVector<GenericTypeParamType *, 4> genericParams; |
| for (auto param : function->getGenericParams()) { |
| Type paramTy = Type(param).transform(fn); |
| if (!paramTy) |
| return Type(); |
| |
| if (auto newParam = paramTy->getAs<GenericTypeParamType>()) { |
| if (newParam != param) |
| anyChanges = true; |
| |
| genericParams.push_back(newParam); |
| } else { |
| anyChanges = true; |
| } |
| } |
| |
| // Transform requirements. |
| SmallVector<Requirement, 4> requirements; |
| for (const auto &req : function->getRequirements()) { |
| auto firstType = req.getFirstType().transform(fn); |
| if (!firstType) |
| return Type(); |
| |
| Type secondType = req.getSecondType(); |
| if (secondType) { |
| secondType = secondType.transform(fn); |
| if (!secondType) |
| return Type(); |
| } |
| |
| if (firstType->hasTypeParameter() || |
| (secondType && secondType->hasTypeParameter())) { |
| if (firstType.getPointer() != req.getFirstType().getPointer() || |
| secondType.getPointer() != req.getSecondType().getPointer()) |
| anyChanges = true; |
| |
| requirements.push_back(Requirement(req.getKind(), firstType, |
| secondType)); |
| } else |
| anyChanges = true; |
| } |
| |
| auto sig = GenericSignature::get(genericParams, requirements); |
| |
| // Transform input type. |
| auto inputTy = function->getInput().transform(fn); |
| if (!inputTy) |
| return Type(); |
| |
| // Transform result type. |
| auto resultTy = function->getResult().transform(fn); |
| if (!resultTy) |
| return Type(); |
| |
| // Check whether anything changed. |
| if (!anyChanges && |
| inputTy.getPointer() == function->getInput().getPointer() && |
| resultTy.getPointer() == function->getResult().getPointer()) |
| return *this; |
| |
| // If no generic parameters remain, this is a non-generic function type. |
| if (genericParams.empty()) |
| return FunctionType::get(inputTy, resultTy, function->getExtInfo()); |
| |
| // Produce the new generic function type. |
| |
| return GenericFunctionType::get(sig, inputTy, resultTy, |
| function->getExtInfo()); |
| } |
| |
| case TypeKind::ArraySlice: { |
| auto slice = cast<ArraySliceType>(base); |
| auto baseTy = slice->getBaseType().transform(fn); |
| if (!baseTy) |
| return Type(); |
| |
| if (baseTy.getPointer() == slice->getBaseType().getPointer()) |
| return *this; |
| |
| return ArraySliceType::get(baseTy); |
| } |
| |
| case TypeKind::Optional: { |
| auto optional = cast<OptionalType>(base); |
| auto baseTy = optional->getBaseType().transform(fn); |
| if (!baseTy) |
| return Type(); |
| |
| if (baseTy.getPointer() == optional->getBaseType().getPointer()) |
| return *this; |
| |
| return OptionalType::get(baseTy); |
| } |
| |
| case TypeKind::ImplicitlyUnwrappedOptional: { |
| auto optional = cast<ImplicitlyUnwrappedOptionalType>(base); |
| auto baseTy = optional->getBaseType().transform(fn); |
| if (!baseTy) |
| return Type(); |
| |
| if (baseTy.getPointer() == optional->getBaseType().getPointer()) |
| return *this; |
| |
| return ImplicitlyUnwrappedOptionalType::get(baseTy); |
| } |
| |
| case TypeKind::Dictionary: { |
| auto dict = cast<DictionaryType>(base); |
| auto keyTy = dict->getKeyType().transform(fn); |
| if (!keyTy) |
| return Type(); |
| |
| auto valueTy = dict->getValueType().transform(fn); |
| if (!valueTy) |
| return Type(); |
| |
| if (keyTy.getPointer() == dict->getKeyType().getPointer() && |
| valueTy.getPointer() == dict->getValueType().getPointer()) |
| return *this; |
| |
| return DictionaryType::get(keyTy, valueTy); |
| } |
| |
| case TypeKind::LValue: { |
| auto lvalue = cast<LValueType>(base); |
| auto objectTy = lvalue->getObjectType().transform(fn); |
| if (!objectTy) return Type(); |
| |
| return objectTy.getPointer() == lvalue->getObjectType().getPointer() ? |
| *this : LValueType::get(objectTy); |
| } |
| |
| case TypeKind::InOut: { |
| auto inout = cast<InOutType>(base); |
| auto objectTy = inout->getObjectType().transform(fn); |
| if (!objectTy) return Type(); |
| |
| return objectTy.getPointer() == inout->getObjectType().getPointer() ? |
| *this : InOutType::get(objectTy); |
| } |
| |
| case TypeKind::ProtocolComposition: { |
| auto pc = cast<ProtocolCompositionType>(base); |
| SmallVector<Type, 4> protocols; |
| bool anyChanged = false; |
| unsigned index = 0; |
| for (auto proto : pc->getProtocols()) { |
| auto substProto = proto.transform(fn); |
| if (!substProto) |
| return Type(); |
| |
| if (anyChanged) { |
| protocols.push_back(substProto); |
| ++index; |
| continue; |
| } |
| |
| if (substProto.getPointer() != proto.getPointer()) { |
| anyChanged = true; |
| protocols.append(protocols.begin(), protocols.begin() + index); |
| protocols.push_back(substProto); |
| } |
| |
| ++index; |
| } |
| |
| if (!anyChanged) |
| return *this; |
| |
| return ProtocolCompositionType::get(Ptr->getASTContext(), protocols); |
| } |
| } |
| |
| llvm_unreachable("Unhandled type in transformation"); |
| } |
| |
| |
| bool Type::findIf(const std::function<bool(Type)> &pred) const { |
| class Walker : public TypeWalker { |
| const std::function<bool(Type)> &Pred; |
| public: |
| explicit Walker(const std::function<bool(Type)> &pred) : Pred(pred) {} |
| |
| virtual Action walkToTypePre(Type ty) override { |
| if (Pred(ty)) |
| return Action::Stop; |
| return Action::Continue; |
| } |
| }; |
| |
| return walk(Walker(pred)); |
| } |
| |
| TypeTraitResult TypeBase::canBeClass() { |
| // Any bridgeable object type can be a class. |
| if (isBridgeableObjectType()) |
| return TypeTraitResult::Is; |
| |
| CanType self = getCanonicalType(); |
| |
| // Dependent types might be bound to classes. |
| if (isa<SubstitutableType>(self)) |
| return TypeTraitResult::CanBe; |
| if (isa<DependentMemberType>(self)) |
| return TypeTraitResult::CanBe; |
| |
| return TypeTraitResult::IsNot; |
| } |
| |
| bool Type::isPrivateStdlibType() const { |
| Type Ty = *this; |
| if (!Ty) |
| return false; |
| |
| // A 'public' typealias can have an 'internal' type. |
| if (NameAliasType *NAT = dyn_cast<NameAliasType>(Ty.getPointer())) |
| return NAT->getDecl()->isPrivateStdlibDecl(); |
| |
| if (auto Paren = dyn_cast<ParenType>(Ty.getPointer())) |
| return Paren->getUnderlyingType().isPrivateStdlibType(); |
| |
| if (Type Unwrapped = Ty->getAnyOptionalObjectType()) |
| return Unwrapped.isPrivateStdlibType(); |
| |
| if (auto TyD = Ty->getAnyNominal()) |
| if (TyD->isPrivateStdlibDecl()) |
| return true; |
| |
| return false; |
| } |