blob: ac2dc5e2857f9e865cf34990eb9a01afa0d67f80 [file] [log] [blame]
//===--- TypeCheckRequests.cpp - Type Checking Requests ------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/DiagnosticsCommon.h"
#include "swift/AST/DiagnosticsSema.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/PropertyWrappers.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/AST/TypeLoc.h"
#include "swift/AST/TypeRepr.h"
#include "swift/AST/Types.h"
#include "swift/Subsystems.h"
using namespace swift;
namespace swift {
// Implement the type checker type zone (zone 10).
#define SWIFT_TYPEID_ZONE TypeChecker
#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
#include "swift/Basic/ImplementTypeIDZone.h"
#undef SWIFT_TYPEID_ZONE
#undef SWIFT_TYPEID_HEADER
}
void swift::simple_display(
llvm::raw_ostream &out,
const llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> &value) {
if (auto type = value.dyn_cast<const TypeDecl *>()) {
type->dumpRef(out);
return;
}
auto ext = value.get<const ExtensionDecl *>();
simple_display(out, ext);
}
void swift::simple_display(llvm::raw_ostream &out,
const TypeResolutionStage &value) {
switch (value) {
case TypeResolutionStage::Structural:
out << "structural";
break;
case TypeResolutionStage::Interface:
out << "interface";
break;
case TypeResolutionStage::Contextual:
out << "contextual";
break;
}
}
void swift::simple_display(llvm::raw_ostream &out, Type type) {
if (type)
type.print(out);
else
out << "null";
}
void swift::simple_display(llvm::raw_ostream &out, const TypeRepr *TyR) {
if (TyR)
TyR->print(out);
else
out << "null";
}
void swift::simple_display(llvm::raw_ostream &out, const TypeLoc source) {
out << "(";
simple_display(out, source.getType());
out << ", ";
simple_display(out, source.getTypeRepr());
out << ")";
}
//----------------------------------------------------------------------------//
// Inherited type computation.
//----------------------------------------------------------------------------//
SourceLoc InheritedTypeRequest::getNearestLoc() const {
const auto &storage = getStorage();
auto &typeLoc = getInheritedTypeLocAtIndex(std::get<0>(storage),
std::get<1>(storage));
return typeLoc.getLoc();
}
bool InheritedTypeRequest::isCached() const {
return std::get<2>(getStorage()) == TypeResolutionStage::Interface;
}
Optional<Type> InheritedTypeRequest::getCachedResult() const {
const auto &storage = getStorage();
auto &typeLoc = getInheritedTypeLocAtIndex(std::get<0>(storage),
std::get<1>(storage));
if (typeLoc.wasValidated())
return typeLoc.getType();
return None;
}
void InheritedTypeRequest::cacheResult(Type value) const {
const auto &storage = getStorage();
auto &typeLoc = getInheritedTypeLocAtIndex(std::get<0>(storage),
std::get<1>(storage));
const_cast<TypeLoc &>(typeLoc).setType(value);
}
//----------------------------------------------------------------------------//
// Superclass computation.
//----------------------------------------------------------------------------//
void SuperclassTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
// FIXME: Improve this diagnostic.
auto nominalDecl = std::get<0>(getStorage());
diags.diagnose(nominalDecl, diag::circular_class_inheritance,
nominalDecl->getName());
}
bool SuperclassTypeRequest::isCached() const {
return std::get<1>(getStorage()) == TypeResolutionStage::Interface;
}
Optional<Type> SuperclassTypeRequest::getCachedResult() const {
auto nominalDecl = std::get<0>(getStorage());
if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
if (classDecl->LazySemanticInfo.SuperclassType.getInt())
return classDecl->LazySemanticInfo.SuperclassType.getPointer();
if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
if (protocolDecl->LazySemanticInfo.SuperclassType.getInt())
return protocolDecl->LazySemanticInfo.SuperclassType.getPointer();
return None;
}
void SuperclassTypeRequest::cacheResult(Type value) const {
auto nominalDecl = std::get<0>(getStorage());
if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
classDecl->LazySemanticInfo.SuperclassType.setPointerAndInt(value, true);
if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
protocolDecl->LazySemanticInfo.SuperclassType.setPointerAndInt(value, true);
}
void SuperclassTypeRequest::writeDependencySink(
evaluator::DependencyCollector &tracker, Type value) const {
if (!value)
return;
// FIXME: This is compatible with the existing name tracking scheme, but
// ignoring this name when we fail to look up a class is bogus.
ClassDecl *Super = value->getClassOrBoundGenericClass();
if (!Super)
return;
tracker.addPotentialMember(Super);
}
//----------------------------------------------------------------------------//
// Enum raw type computation.
//----------------------------------------------------------------------------//
void EnumRawTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
// FIXME: Improve this diagnostic.
auto enumDecl = std::get<0>(getStorage());
diags.diagnose(enumDecl, diag::circular_enum_inheritance, enumDecl->getName());
}
void EnumRawTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
auto *decl = std::get<0>(getStorage());
diags.diagnose(decl, diag::kind_declname_declared_here,
decl->getDescriptiveKind(), decl->getName());
}
//----------------------------------------------------------------------------//
// isObjC computation.
//----------------------------------------------------------------------------//
Optional<bool> IsObjCRequest::getCachedResult() const {
auto decl = std::get<0>(getStorage());
if (decl->LazySemanticInfo.isObjCComputed)
return decl->LazySemanticInfo.isObjC;
return None;
}
void IsObjCRequest::cacheResult(bool value) const {
auto decl = std::get<0>(getStorage());
decl->setIsObjC(value);
}
//----------------------------------------------------------------------------//
// requiresClass computation.
//----------------------------------------------------------------------------//
void ProtocolRequiresClassRequest::diagnoseCycle(DiagnosticEngine &diags) const {
auto decl = std::get<0>(getStorage());
diags.diagnose(decl, diag::circular_protocol_def, decl->getName());
}
void ProtocolRequiresClassRequest::noteCycleStep(DiagnosticEngine &diags) const {
auto requirement = std::get<0>(getStorage());
diags.diagnose(requirement, diag::kind_declname_declared_here,
DescriptiveDeclKind::Protocol,
requirement->getName());
}
Optional<bool> ProtocolRequiresClassRequest::getCachedResult() const {
auto decl = std::get<0>(getStorage());
return decl->getCachedRequiresClass();
}
void ProtocolRequiresClassRequest::cacheResult(bool value) const {
auto decl = std::get<0>(getStorage());
decl->setCachedRequiresClass(value);
}
//----------------------------------------------------------------------------//
// existentialConformsToSelf computation.
//----------------------------------------------------------------------------//
void ExistentialConformsToSelfRequest::diagnoseCycle(DiagnosticEngine &diags) const {
auto decl = std::get<0>(getStorage());
diags.diagnose(decl, diag::circular_protocol_def, decl->getName());
}
void ExistentialConformsToSelfRequest::noteCycleStep(DiagnosticEngine &diags) const {
auto requirement = std::get<0>(getStorage());
diags.diagnose(requirement, diag::kind_declname_declared_here,
DescriptiveDeclKind::Protocol, requirement->getName());
}
Optional<bool> ExistentialConformsToSelfRequest::getCachedResult() const {
auto decl = std::get<0>(getStorage());
return decl->getCachedExistentialConformsToSelf();
}
void ExistentialConformsToSelfRequest::cacheResult(bool value) const {
auto decl = std::get<0>(getStorage());
decl->setCachedExistentialConformsToSelf(value);
}
//----------------------------------------------------------------------------//
// existentialTypeSupported computation.
//----------------------------------------------------------------------------//
void ExistentialTypeSupportedRequest::diagnoseCycle(DiagnosticEngine &diags) const {
auto decl = std::get<0>(getStorage());
diags.diagnose(decl, diag::circular_protocol_def, decl->getName());
}
void ExistentialTypeSupportedRequest::noteCycleStep(DiagnosticEngine &diags) const {
auto requirement = std::get<0>(getStorage());
diags.diagnose(requirement, diag::kind_declname_declared_here,
DescriptiveDeclKind::Protocol, requirement->getName());
}
Optional<bool> ExistentialTypeSupportedRequest::getCachedResult() const {
auto decl = std::get<0>(getStorage());
return decl->getCachedExistentialTypeSupported();
}
void ExistentialTypeSupportedRequest::cacheResult(bool value) const {
auto decl = std::get<0>(getStorage());
decl->setCachedExistentialTypeSupported(value);
}
//----------------------------------------------------------------------------//
// isFinal computation.
//----------------------------------------------------------------------------//
Optional<bool> IsFinalRequest::getCachedResult() const {
auto decl = std::get<0>(getStorage());
if (decl->LazySemanticInfo.isFinalComputed)
return decl->LazySemanticInfo.isFinal;
return None;
}
void IsFinalRequest::cacheResult(bool value) const {
auto decl = std::get<0>(getStorage());
decl->LazySemanticInfo.isFinalComputed = true;
decl->LazySemanticInfo.isFinal = value;
// Add an attribute for printing
if (value && !decl->getAttrs().hasAttribute<FinalAttr>())
decl->getAttrs().add(new (decl->getASTContext()) FinalAttr(/*Implicit=*/true));
}
//----------------------------------------------------------------------------//
// isDynamic computation.
//----------------------------------------------------------------------------//
Optional<bool> IsDynamicRequest::getCachedResult() const {
auto decl = std::get<0>(getStorage());
if (decl->LazySemanticInfo.isDynamicComputed)
return decl->LazySemanticInfo.isDynamic;
return None;
}
void IsDynamicRequest::cacheResult(bool value) const {
auto decl = std::get<0>(getStorage());
decl->setIsDynamic(value);
// Add an attribute for printing
if (value && !decl->getAttrs().hasAttribute<DynamicAttr>())
decl->getAttrs().add(new (decl->getASTContext()) DynamicAttr(/*Implicit=*/true));
}
//----------------------------------------------------------------------------//
// RequirementSignatureRequest computation.
//----------------------------------------------------------------------------//
Optional<ArrayRef<Requirement>> RequirementSignatureRequest::getCachedResult() const {
auto proto = std::get<0>(getStorage());
if (proto->isRequirementSignatureComputed())
return proto->getCachedRequirementSignature();
return None;
}
void RequirementSignatureRequest::cacheResult(ArrayRef<Requirement> value) const {
auto proto = std::get<0>(getStorage());
proto->setRequirementSignature(value);
}
//----------------------------------------------------------------------------//
// Requirement computation.
//----------------------------------------------------------------------------//
WhereClauseOwner::WhereClauseOwner(GenericContext *genCtx): dc(genCtx) {
if (const auto whereClause = genCtx->getTrailingWhereClause())
source = whereClause;
else
source = genCtx->getGenericParams();
}
WhereClauseOwner::WhereClauseOwner(AssociatedTypeDecl *atd)
: dc(atd->getInnermostDeclContext()),
source(atd->getTrailingWhereClause()) {}
SourceLoc WhereClauseOwner::getLoc() const {
if (auto where = source.dyn_cast<TrailingWhereClause *>())
return where->getWhereLoc();
if (auto attr = source.dyn_cast<SpecializeAttr *>())
return attr->getLocation();
// SWIFT_ENABLE_TENSORFLOW
if (auto attr = source.dyn_cast<DifferentiableAttr *>())
return attr->getLocation();
return source.get<GenericParamList *>()->getWhereLoc();
}
void swift::simple_display(llvm::raw_ostream &out,
const WhereClauseOwner &owner) {
if (owner.source.is<TrailingWhereClause *>()) {
simple_display(out, owner.dc->getAsDecl());
} else if (owner.source.is<SpecializeAttr *>()) {
out << "@_specialize";
} else {
out << "(SIL generic parameter list)";
}
}
SourceLoc RequirementRequest::getNearestLoc() const {
auto owner = std::get<0>(getStorage());
return owner.getLoc();
}
void RequirementRequest::noteCycleStep(DiagnosticEngine &diags) const {
// For now, the GSB does a better job of describing the exact structure of
// the cycle.
//
// FIXME: We should consider merging the circularity handling the GSB does
// into this request. See rdar://55263708
}
MutableArrayRef<RequirementRepr> WhereClauseOwner::getRequirements() const {
if (const auto genericParams = source.dyn_cast<GenericParamList *>()) {
return genericParams->getRequirements();
} else if (const auto attr = source.dyn_cast<SpecializeAttr *>()) {
if (auto whereClause = attr->getTrailingWhereClause())
return whereClause->getRequirements();
} else if (const auto attr = source.dyn_cast<DifferentiableAttr *>()) {
if (auto whereClause = attr->getWhereClause())
return whereClause->getRequirements();
} else if (const auto whereClause = source.get<TrailingWhereClause *>()) {
return whereClause->getRequirements();
}
return { };
}
bool WhereClauseOwner::visitRequirements(
TypeResolutionStage stage,
llvm::function_ref<bool(Requirement, RequirementRepr *)> callback)
const && {
auto &evaluator = dc->getASTContext().evaluator;
auto requirements = getRequirements();
for (unsigned index : indices(requirements)) {
// Resolve to a requirement.
auto req = evaluator(RequirementRequest{*this, index, stage});
if (req) {
// Invoke the callback. If it returns true, we're done.
if (callback(*req, &requirements[index]))
return true;
continue;
}
llvm::handleAllErrors(
req.takeError(), [](const CyclicalRequestError<RequirementRequest> &E) {
// cycle detected
});
}
return false;
}
RequirementRepr &RequirementRequest::getRequirement() const {
auto owner = std::get<0>(getStorage());
auto index = std::get<1>(getStorage());
return owner.getRequirements()[index];
}
bool RequirementRequest::isCached() const {
return std::get<2>(getStorage()) == TypeResolutionStage::Interface;
}
//----------------------------------------------------------------------------//
// DefaultTypeRequest.
//----------------------------------------------------------------------------//
void swift::simple_display(llvm::raw_ostream &out,
const KnownProtocolKind kind) {
out << getProtocolName(kind);
}
//----------------------------------------------------------------------------//
// DefaultTypeRequest caching.
//----------------------------------------------------------------------------//
Optional<Type> DefaultTypeRequest::getCachedResult() const {
auto *DC = std::get<1>(getStorage());
auto knownProtocolKind = std::get<0>(getStorage());
const auto &cachedType = DC->getASTContext().getDefaultTypeRequestCache(
DC->getParentSourceFile(), knownProtocolKind);
return cachedType ? Optional<Type>(cachedType) : None;
}
void DefaultTypeRequest::cacheResult(Type value) const {
auto *DC = std::get<1>(getStorage());
auto knownProtocolKind = std::get<0>(getStorage());
auto &cacheEntry = DC->getASTContext().getDefaultTypeRequestCache(
DC->getParentSourceFile(), knownProtocolKind);
cacheEntry = value;
}
bool PropertyWrapperTypeInfoRequest::isCached() const {
auto nominal = std::get<0>(getStorage());
return nominal->getAttrs().hasAttribute<PropertyWrapperAttr>();;
}
bool AttachedPropertyWrappersRequest::isCached() const {
auto var = std::get<0>(getStorage());
return !var->getAttrs().isEmpty();
}
bool AttachedPropertyWrapperTypeRequest::isCached() const {
auto var = std::get<0>(getStorage());
return !var->getAttrs().isEmpty();
}
bool PropertyWrapperBackingPropertyTypeRequest::isCached() const {
auto var = std::get<0>(getStorage());
return !var->getAttrs().isEmpty();
}
bool PropertyWrapperBackingPropertyInfoRequest::isCached() const {
auto var = std::get<0>(getStorage());
return !var->getAttrs().isEmpty();
}
bool PropertyWrapperMutabilityRequest::isCached() const {
auto var = std::get<0>(getStorage());
return !var->getAttrs().isEmpty();
}
bool PropertyWrapperLValuenessRequest::isCached() const {
auto var = std::get<0>(getStorage());
return !var->getAttrs().isEmpty();
}
void swift::simple_display(
llvm::raw_ostream &out, const PropertyWrapperTypeInfo &propertyWrapper) {
out << "{ ";
if (propertyWrapper.valueVar)
out << propertyWrapper.valueVar->printRef();
else
out << "null";
out << " }";
}
void swift::simple_display(
llvm::raw_ostream &out,
const PropertyWrapperBackingPropertyInfo &backingInfo) {
out << "{ ";
if (backingInfo.backingVar)
backingInfo.backingVar->dumpRef(out);
out << " }";
}
void swift::simple_display(
llvm::raw_ostream &out, const CtorInitializerKind initKind) {
out << "{ ";
switch (initKind) {
case CtorInitializerKind::Designated:
out << "designated"; break;
case CtorInitializerKind::Convenience:
out << "convenience"; break;
case CtorInitializerKind::ConvenienceFactory:
out << "convenience_factory"; break;
case CtorInitializerKind::Factory:
out << "factory"; break;
}
out << " }";
}
void swift::simple_display(llvm::raw_ostream &os, PropertyWrapperMutability m) {
static const char *names[] =
{"is nonmutating", "is mutating", "doesn't exist"};
os << "getter " << names[m.Getter] << ", setter " << names[m.Setter];
}
void swift::simple_display(llvm::raw_ostream &out, PropertyWrapperLValueness l) {
out << "is lvalue for get: {";
simple_display(out, l.isLValueForGetAccess);
out << "}, is lvalue for set: {";
simple_display(out, l.isLValueForSetAccess);
out << "}";
}
void swift::simple_display(llvm::raw_ostream &out,
ResilienceExpansion value) {
switch (value) {
case ResilienceExpansion::Minimal:
out << "minimal";
break;
case ResilienceExpansion::Maximal:
out << "maximal";
break;
}
}
void swift::simple_display(llvm::raw_ostream &out,
FragileFunctionKind value) {
switch (value.kind) {
case FragileFunctionKind::Transparent:
out << "transparent";
break;
case FragileFunctionKind::Inlinable:
out << "inlinable";
break;
case FragileFunctionKind::AlwaysEmitIntoClient:
out << "alwaysEmitIntoClient";
break;
case FragileFunctionKind::DefaultArgument:
out << "defaultArgument";
break;
case FragileFunctionKind::PropertyInitializer:
out << "propertyInitializer";
break;
case FragileFunctionKind::None:
out << "none";
break;
}
out << ", allowUsableFromInline: "
<< (value.allowUsableFromInline ? "true" : "false");
}
//----------------------------------------------------------------------------//
// ResultBuilder-related requests.
//----------------------------------------------------------------------------//
bool AttachedResultBuilderRequest::isCached() const {
// Only needs to be cached if there are any custom attributes.
auto var = std::get<0>(getStorage());
return var->getAttrs().hasAttribute<CustomAttr>();
}
//----------------------------------------------------------------------------//
// SelfAccessKindRequest computation.
//----------------------------------------------------------------------------//
Optional<SelfAccessKind> SelfAccessKindRequest::getCachedResult() const {
auto *funcDecl = std::get<0>(getStorage());
return funcDecl->getCachedSelfAccessKind();
}
void SelfAccessKindRequest::cacheResult(SelfAccessKind value) const {
auto *funcDecl = std::get<0>(getStorage());
funcDecl->setSelfAccessKind(value);
}
//----------------------------------------------------------------------------//
// IsGetterMutatingRequest computation.
//----------------------------------------------------------------------------//
Optional<bool> IsGetterMutatingRequest::getCachedResult() const {
auto *storage = std::get<0>(getStorage());
if (storage->LazySemanticInfo.IsGetterMutatingComputed)
return storage->LazySemanticInfo.IsGetterMutating;
return None;
}
void IsGetterMutatingRequest::cacheResult(bool value) const {
auto *storage = std::get<0>(getStorage());
storage->setIsGetterMutating(value);
}
//----------------------------------------------------------------------------//
// IsSetterMutatingRequest computation.
//----------------------------------------------------------------------------//
Optional<bool> IsSetterMutatingRequest::getCachedResult() const {
auto *storage = std::get<0>(getStorage());
if (storage->LazySemanticInfo.IsSetterMutatingComputed)
return storage->LazySemanticInfo.IsSetterMutating;
return None;
}
void IsSetterMutatingRequest::cacheResult(bool value) const {
auto *storage = std::get<0>(getStorage());
storage->setIsSetterMutating(value);
}
//----------------------------------------------------------------------------//
// OpaqueReadOwnershipRequest computation.
//----------------------------------------------------------------------------//
Optional<OpaqueReadOwnership>
OpaqueReadOwnershipRequest::getCachedResult() const {
auto *storage = std::get<0>(getStorage());
if (storage->LazySemanticInfo.OpaqueReadOwnershipComputed)
return OpaqueReadOwnership(storage->LazySemanticInfo.OpaqueReadOwnership);
return None;
}
void OpaqueReadOwnershipRequest::cacheResult(OpaqueReadOwnership value) const {
auto *storage = std::get<0>(getStorage());
storage->setOpaqueReadOwnership(value);
}
//----------------------------------------------------------------------------//
// StorageImplInfoRequest computation.
//----------------------------------------------------------------------------//
Optional<StorageImplInfo>
StorageImplInfoRequest::getCachedResult() const {
auto *storage = std::get<0>(getStorage());
if (storage->LazySemanticInfo.ImplInfoComputed)
return storage->ImplInfo;
return None;
}
void StorageImplInfoRequest::cacheResult(StorageImplInfo value) const {
auto *storage = std::get<0>(getStorage());
storage->setImplInfo(value);
}
//----------------------------------------------------------------------------//
// RequiresOpaqueAccessorsRequest computation.
//----------------------------------------------------------------------------//
Optional<bool>
RequiresOpaqueAccessorsRequest::getCachedResult() const {
auto *storage = std::get<0>(getStorage());
if (storage->LazySemanticInfo.RequiresOpaqueAccessorsComputed)
return storage->LazySemanticInfo.RequiresOpaqueAccessors;
return None;
}
void RequiresOpaqueAccessorsRequest::cacheResult(bool value) const {
auto *storage = std::get<0>(getStorage());
storage->LazySemanticInfo.RequiresOpaqueAccessorsComputed = 1;
storage->LazySemanticInfo.RequiresOpaqueAccessors = value;
}
//----------------------------------------------------------------------------//
// RequiresOpaqueModifyCoroutineRequest computation.
//----------------------------------------------------------------------------//
Optional<bool>
RequiresOpaqueModifyCoroutineRequest::getCachedResult() const {
auto *storage = std::get<0>(getStorage());
if (storage->LazySemanticInfo.RequiresOpaqueModifyCoroutineComputed)
return storage->LazySemanticInfo.RequiresOpaqueModifyCoroutine;
return None;
}
void RequiresOpaqueModifyCoroutineRequest::cacheResult(bool value) const {
auto *storage = std::get<0>(getStorage());
storage->LazySemanticInfo.RequiresOpaqueModifyCoroutineComputed = 1;
storage->LazySemanticInfo.RequiresOpaqueModifyCoroutine = value;
}
//----------------------------------------------------------------------------//
// IsAccessorTransparentRequest computation.
//----------------------------------------------------------------------------//
Optional<bool>
IsAccessorTransparentRequest::getCachedResult() const {
auto *accessor = std::get<0>(getStorage());
return accessor->getCachedIsTransparent();
}
void IsAccessorTransparentRequest::cacheResult(bool value) const {
auto *accessor = std::get<0>(getStorage());
accessor->setIsTransparent(value);
// For interface printing, API diff, etc.
if (value) {
auto &attrs = accessor->getAttrs();
if (!attrs.hasAttribute<TransparentAttr>()) {
auto &ctx = accessor->getASTContext();
attrs.add(new (ctx) TransparentAttr(/*IsImplicit=*/true));
}
}
}
//----------------------------------------------------------------------------//
// SynthesizeAccessorRequest computation.
//----------------------------------------------------------------------------//
Optional<AccessorDecl *>
SynthesizeAccessorRequest::getCachedResult() const {
auto *storage = std::get<0>(getStorage());
auto kind = std::get<1>(getStorage());
auto *accessor = storage->getAccessor(kind);
if (accessor)
return accessor;
return None;
}
void SynthesizeAccessorRequest::cacheResult(AccessorDecl *accessor) const {
auto *storage = std::get<0>(getStorage());
auto kind = std::get<1>(getStorage());
storage->setSynthesizedAccessor(kind, accessor);
}
//----------------------------------------------------------------------------//
// IsImplicitlyUnwrappedOptionalRequest computation.
//----------------------------------------------------------------------------//
Optional<bool>
IsImplicitlyUnwrappedOptionalRequest::getCachedResult() const {
auto *decl = std::get<0>(getStorage());
if (decl->LazySemanticInfo.isIUOComputed)
return decl->LazySemanticInfo.isIUO;
return None;
}
void IsImplicitlyUnwrappedOptionalRequest::cacheResult(bool value) const {
auto *decl = std::get<0>(getStorage());
decl->setImplicitlyUnwrappedOptional(value);
}
//----------------------------------------------------------------------------//
// GenericSignatureRequest computation.
//----------------------------------------------------------------------------//
Optional<GenericSignature> GenericSignatureRequest::getCachedResult() const {
auto *GC = std::get<0>(getStorage());
if (GC->GenericSigAndBit.getInt()) {
return GC->GenericSigAndBit.getPointer();
}
return None;
}
void GenericSignatureRequest::cacheResult(GenericSignature value) const {
auto *GC = std::get<0>(getStorage());
GC->GenericSigAndBit.setPointerAndInt(value, true);
}
//----------------------------------------------------------------------------//
// InferredGenericSignatureRequest computation.
//----------------------------------------------------------------------------//
void InferredGenericSignatureRequest::noteCycleStep(DiagnosticEngine &d) const {
// For now, the GSB does a better job of describing the exact structure of
// the cycle.
//
// FIXME: We should consider merging the circularity handling the GSB does
// into this request. See rdar://55263708
}
//----------------------------------------------------------------------------//
// UnderlyingTypeRequest computation.
//----------------------------------------------------------------------------//
Optional<Type>
UnderlyingTypeRequest::getCachedResult() const {
auto *typeAlias = std::get<0>(getStorage());
if (auto type = typeAlias->UnderlyingTy.getType())
return type;
return None;
}
void UnderlyingTypeRequest::cacheResult(Type value) const {
auto *typeAlias = std::get<0>(getStorage());
typeAlias->UnderlyingTy.setType(value);
}
void UnderlyingTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
auto aliasDecl = std::get<0>(getStorage());
diags.diagnose(aliasDecl, diag::recursive_decl_reference,
aliasDecl->getDescriptiveKind(),
aliasDecl->getName());
}
//----------------------------------------------------------------------------//
// EnumRawValuesRequest computation.
//----------------------------------------------------------------------------//
bool EnumRawValuesRequest::isCached() const {
return std::get<1>(getStorage()) == TypeResolutionStage::Interface;
}
Optional<evaluator::SideEffect> EnumRawValuesRequest::getCachedResult() const {
auto *ED = std::get<0>(getStorage());
if (ED->SemanticFlags.contains(EnumDecl::HasFixedRawValuesAndTypes))
return std::make_tuple<>();
return None;
}
void EnumRawValuesRequest::cacheResult(evaluator::SideEffect) const {
auto *ED = std::get<0>(getStorage());
ED->SemanticFlags |= OptionSet<EnumDecl::SemanticInfoFlags>{
EnumDecl::HasFixedRawValues | EnumDecl::HasFixedRawValuesAndTypes};
}
void EnumRawValuesRequest::diagnoseCycle(DiagnosticEngine &diags) const {
// This request computes the raw type, and so participates in cycles involving
// it. For now, the raw type provides a rich enough circularity diagnostic
// that we can silence ourselves.
}
void EnumRawValuesRequest::noteCycleStep(DiagnosticEngine &diags) const {
}
//----------------------------------------------------------------------------//
// IsStaticRequest computation.
//----------------------------------------------------------------------------//
Optional<bool> IsStaticRequest::getCachedResult() const {
auto *FD = std::get<0>(getStorage());
return FD->getCachedIsStatic();
}
void IsStaticRequest::cacheResult(bool result) const {
auto *FD = std::get<0>(getStorage());
FD->setStatic(result);
}
//----------------------------------------------------------------------------//
// NeedsNewVTableEntryRequest computation.
//----------------------------------------------------------------------------//
Optional<bool> NeedsNewVTableEntryRequest::getCachedResult() const {
auto *decl = std::get<0>(getStorage());
if (decl->LazySemanticInfo.NeedsNewVTableEntryComputed)
return decl->LazySemanticInfo.NeedsNewVTableEntry;
return None;
}
void NeedsNewVTableEntryRequest::cacheResult(bool value) const {
auto *decl = std::get<0>(getStorage());
decl->LazySemanticInfo.NeedsNewVTableEntryComputed = true;
decl->LazySemanticInfo.NeedsNewVTableEntry = value;
}
//----------------------------------------------------------------------------//
// ParamSpecifierRequest computation.
//----------------------------------------------------------------------------//
Optional<ParamSpecifier> ParamSpecifierRequest::getCachedResult() const {
auto *decl = std::get<0>(getStorage());
return decl->getCachedSpecifier();
}
void ParamSpecifierRequest::cacheResult(ParamSpecifier specifier) const {
auto *decl = std::get<0>(getStorage());
decl->setSpecifier(specifier);
}
//----------------------------------------------------------------------------//
// ResultTypeRequest computation.
//----------------------------------------------------------------------------//
Optional<Type> ResultTypeRequest::getCachedResult() const {
Type type;
auto *const decl = std::get<0>(getStorage());
if (const auto *const funcDecl = dyn_cast<FuncDecl>(decl)) {
type = funcDecl->FnRetType.getType();
} else {
type = cast<SubscriptDecl>(decl)->ElementTy.getType();
}
if (type.isNull())
return None;
return type;
}
void ResultTypeRequest::cacheResult(Type type) const {
auto *const decl = std::get<0>(getStorage());
if (auto *const funcDecl = dyn_cast<FuncDecl>(decl)) {
funcDecl->FnRetType.setType(type);
} else {
cast<SubscriptDecl>(decl)->ElementTy.setType(type);
}
}
//----------------------------------------------------------------------------//
// PatternBindingEntryRequest computation.
//----------------------------------------------------------------------------//
Optional<const PatternBindingEntry *>
PatternBindingEntryRequest::getCachedResult() const {
auto *PBD = std::get<0>(getStorage());
auto idx = std::get<1>(getStorage());
if (!PBD->getPatternList()[idx].isFullyValidated()) {
return None;
}
return &PBD->getPatternList()[idx];
}
void PatternBindingEntryRequest::cacheResult(
const PatternBindingEntry *value) const {
auto *PBD = std::get<0>(getStorage());
auto idx = std::get<1>(getStorage());
PBD->getMutablePatternList()[idx].setFullyValidated();
}
//----------------------------------------------------------------------------//
// NamingPatternRequest computation.
//----------------------------------------------------------------------------//
Optional<NamedPattern *> NamingPatternRequest::getCachedResult() const {
auto *VD = std::get<0>(getStorage());
if (auto *Pat = VD->NamingPattern) {
return Pat;
}
return None;
}
void NamingPatternRequest::cacheResult(NamedPattern *value) const {
auto *VD = std::get<0>(getStorage());
VD->NamingPattern = value;
}
//----------------------------------------------------------------------------//
// InterfaceTypeRequest computation.
//----------------------------------------------------------------------------//
Optional<Type> InterfaceTypeRequest::getCachedResult() const {
auto *decl = std::get<0>(getStorage());
if (auto Ty = decl->TypeAndAccess.getPointer()) {
return Ty;
}
return None;
}
void InterfaceTypeRequest::cacheResult(Type type) const {
auto *decl = std::get<0>(getStorage());
if (type) {
assert(!type->hasTypeVariable() && "Type variable in interface type");
assert(!type->hasHole() && "Type hole in interface type");
assert(!type->is<InOutType>() && "Interface type must be materializable");
assert(!type->hasArchetype() && "Archetype in interface type");
}
decl->TypeAndAccess.setPointer(type);
}
//----------------------------------------------------------------------------//
// ValidatePrecedenceGroupRequest computation.
//----------------------------------------------------------------------------//
SourceLoc ValidatePrecedenceGroupRequest::getNearestLoc() const {
auto &desc = std::get<0>(getStorage());
return desc.getLoc();
}
void ValidatePrecedenceGroupRequest::diagnoseCycle(
DiagnosticEngine &diags) const {
auto &desc = std::get<0>(getStorage());
if (auto pathDir = desc.pathDirection) {
diags.diagnose(desc.nameLoc, diag::precedence_group_cycle, (bool)*pathDir);
} else {
diags.diagnose(desc.nameLoc, diag::circular_reference);
}
}
void ValidatePrecedenceGroupRequest::noteCycleStep(
DiagnosticEngine &diag) const {
auto &desc = std::get<0>(getStorage());
diag.diagnose(desc.nameLoc,
diag::circular_reference_through_precedence_group, desc.ident);
}
SourceLoc PrecedenceGroupDescriptor::getLoc() const {
return nameLoc;
}
void swift::simple_display(llvm::raw_ostream &out,
const PrecedenceGroupDescriptor &desc) {
out << "precedence group " << desc.ident << " at ";
desc.nameLoc.print(out, desc.dc->getASTContext().SourceMgr);
}
//----------------------------------------------------------------------------//
// InheritsSuperclassInitializersRequest computation.
//----------------------------------------------------------------------------//
Optional<bool> InheritsSuperclassInitializersRequest::getCachedResult() const {
auto *decl = std::get<0>(getStorage());
return decl->getCachedInheritsSuperclassInitializers();
}
void InheritsSuperclassInitializersRequest::cacheResult(bool value) const {
auto *decl = std::get<0>(getStorage());
decl->setInheritsSuperclassInitializers(value);
}
//----------------------------------------------------------------------------//
// ResolveImplicitMemberRequest computation.
//----------------------------------------------------------------------------//
void swift::simple_display(llvm::raw_ostream &out,
ImplicitMemberAction action) {
switch (action) {
case ImplicitMemberAction::ResolveImplicitInit:
out << "resolve implicit initializer";
break;
case ImplicitMemberAction::ResolveCodingKeys:
out << "resolve CodingKeys";
break;
case ImplicitMemberAction::ResolveEncodable:
out << "resolve Encodable.encode(to:)";
break;
case ImplicitMemberAction::ResolveDecodable:
out << "resolve Decodable.init(from:)";
break;
}
}
//----------------------------------------------------------------------------//
// TypeWitnessRequest computation.
//----------------------------------------------------------------------------//
Optional<TypeWitnessAndDecl> TypeWitnessRequest::getCachedResult() const {
auto *conformance = std::get<0>(getStorage());
auto *requirement = std::get<1>(getStorage());
if (conformance->TypeWitnesses.count(requirement) == 0) {
return None;
}
return conformance->TypeWitnesses[requirement];
}
void TypeWitnessRequest::cacheResult(TypeWitnessAndDecl typeWitAndDecl) const {
// FIXME: Refactor this to be the thing that warms the cache.
}
//----------------------------------------------------------------------------//
// WitnessRequest computation.
//----------------------------------------------------------------------------//
Optional<Witness> ValueWitnessRequest::getCachedResult() const {
auto *conformance = std::get<0>(getStorage());
auto *requirement = std::get<1>(getStorage());
if (conformance->Mapping.count(requirement) == 0) {
return None;
}
return conformance->Mapping[requirement];
}
void ValueWitnessRequest::cacheResult(Witness type) const {
// FIXME: Refactor this to be the thing that warms the cache.
}
//----------------------------------------------------------------------------//
// PreCheckResultBuilderRequest computation.
//----------------------------------------------------------------------------//
void swift::simple_display(llvm::raw_ostream &out,
ResultBuilderBodyPreCheck value) {
switch (value) {
case ResultBuilderBodyPreCheck::Okay:
out << "okay";
break;
case ResultBuilderBodyPreCheck::HasReturnStmt:
out << "has return statement";
break;
case ResultBuilderBodyPreCheck::Error:
out << "error";
break;
}
}
//----------------------------------------------------------------------------//
// HasCircularInheritedProtocolsRequest computation.
//----------------------------------------------------------------------------//
void HasCircularInheritedProtocolsRequest::diagnoseCycle(
DiagnosticEngine &diags) const {
auto *decl = std::get<0>(getStorage());
diags.diagnose(decl, diag::circular_protocol_def, decl->getName());
}
void HasCircularInheritedProtocolsRequest::noteCycleStep(
DiagnosticEngine &diags) const {
auto *decl = std::get<0>(getStorage());
diags.diagnose(decl, diag::kind_declname_declared_here,
decl->getDescriptiveKind(), decl->getName());
}
//----------------------------------------------------------------------------//
// HasCircularRawValueRequest computation.
//----------------------------------------------------------------------------//
void HasCircularRawValueRequest::diagnoseCycle(DiagnosticEngine &diags) const {
auto *decl = std::get<0>(getStorage());
diags.diagnose(decl, diag::circular_enum_inheritance, decl->getName());
}
void HasCircularRawValueRequest::noteCycleStep(DiagnosticEngine &diags) const {
auto *decl = std::get<0>(getStorage());
diags.diagnose(decl, diag::kind_declname_declared_here,
decl->getDescriptiveKind(), decl->getName());
}
//----------------------------------------------------------------------------//
// DefaultArgumentInitContextRequest computation.
//----------------------------------------------------------------------------//
Optional<Initializer *>
DefaultArgumentInitContextRequest::getCachedResult() const {
auto *param = std::get<0>(getStorage());
return param->getCachedDefaultArgumentInitContext();
}
void DefaultArgumentInitContextRequest::cacheResult(Initializer *init) const {
auto *param = std::get<0>(getStorage());
param->setDefaultArgumentInitContext(init);
}
//----------------------------------------------------------------------------//
// DefaultArgumentExprRequest computation.
//----------------------------------------------------------------------------//
Optional<Expr *> DefaultArgumentExprRequest::getCachedResult() const {
auto *param = std::get<0>(getStorage());
auto *defaultInfo = param->DefaultValueAndFlags.getPointer();
if (!defaultInfo)
return None;
if (!defaultInfo->InitContextAndIsTypeChecked.getInt())
return None;
return defaultInfo->DefaultArg.get<Expr *>();
}
void DefaultArgumentExprRequest::cacheResult(Expr *expr) const {
auto *param = std::get<0>(getStorage());
param->setDefaultExpr(expr, /*isTypeChecked*/ true);
}
//----------------------------------------------------------------------------//
// CallerSideDefaultArgExprRequest computation.
//----------------------------------------------------------------------------//
Optional<Expr *> CallerSideDefaultArgExprRequest::getCachedResult() const {
auto *defaultExpr = std::get<0>(getStorage());
auto storage = defaultExpr->ContextOrCallerSideExpr;
assert(!storage.isNull());
if (auto *expr = storage.dyn_cast<Expr *>())
return expr;
return None;
}
void CallerSideDefaultArgExprRequest::cacheResult(Expr *expr) const {
auto *defaultExpr = std::get<0>(getStorage());
defaultExpr->ContextOrCallerSideExpr = expr;
}
//----------------------------------------------------------------------------//
// DifferentiableAttributeTypeCheckRequest computation.
//----------------------------------------------------------------------------//
Optional<IndexSubset *>
DifferentiableAttributeTypeCheckRequest::getCachedResult() const {
auto *attr = std::get<0>(getStorage());
if (attr->hasBeenTypeChecked())
return attr->ParameterIndicesAndBit.getPointer();
return None;
}
void DifferentiableAttributeTypeCheckRequest::cacheResult(
IndexSubset *parameterIndices) const {
auto *attr = std::get<0>(getStorage());
attr->ParameterIndicesAndBit.setPointerAndInt(parameterIndices, true);
}
//----------------------------------------------------------------------------//
// CheckRedeclarationRequest computation.
//----------------------------------------------------------------------------//
Optional<evaluator::SideEffect>
CheckRedeclarationRequest::getCachedResult() const {
if (!std::get<0>(getStorage())->alreadyCheckedRedeclaration())
return None;
return std::make_tuple<>();
}
void CheckRedeclarationRequest::cacheResult(evaluator::SideEffect) const {
std::get<0>(getStorage())->setCheckedRedeclaration();
}
evaluator::DependencySource CheckRedeclarationRequest::readDependencySource(
const evaluator::DependencyRecorder &eval) const {
auto *currentDC = std::get<0>(getStorage())->getDeclContext();
return currentDC->getParentSourceFile();
}
void CheckRedeclarationRequest::writeDependencySink(
evaluator::DependencyCollector &tracker, evaluator::SideEffect) const {
auto *current = std::get<0>(getStorage());
if (!current->hasName())
return;
DeclContext *currentDC = current->getDeclContext();
SourceFile *currentFile = currentDC->getParentSourceFile();
if (!currentFile || currentDC->isLocalContext())
return;
if (currentDC->isTypeContext()) {
if (auto nominal = currentDC->getSelfNominalTypeDecl()) {
tracker.addUsedMember(nominal, current->getBaseName());
}
} else {
tracker.addTopLevelName(current->getBaseName());
}
}
//----------------------------------------------------------------------------//
// LookupAllConformancesInContextRequest computation.
//----------------------------------------------------------------------------//
void LookupAllConformancesInContextRequest::writeDependencySink(
evaluator::DependencyCollector &tracker,
ProtocolConformanceLookupResult conformances) const {
for (auto conformance : conformances) {
tracker.addPotentialMember(conformance->getProtocol());
}
}
//----------------------------------------------------------------------------//
// ResolveTypeEraserTypeRequest computation.
//----------------------------------------------------------------------------//
Optional<Type> ResolveTypeEraserTypeRequest::getCachedResult() const {
auto *TyExpr = std::get<1>(getStorage())->TypeEraserExpr;
if (!TyExpr || !TyExpr->getType()) {
return None;
}
return TyExpr->getInstanceType();
}
void ResolveTypeEraserTypeRequest::cacheResult(Type value) const {
assert(value && "Resolved type erasure type to null type!");
auto *attr = std::get<1>(getStorage());
if (attr->TypeEraserExpr) {
attr->TypeEraserExpr->setType(MetatypeType::get(value));
} else {
attr->TypeEraserExpr = TypeExpr::createImplicit(value,
value->getASTContext());
}
}
//----------------------------------------------------------------------------//
// TypeCheckSourceFileRequest computation.
//----------------------------------------------------------------------------//
evaluator::DependencySource TypeCheckSourceFileRequest::readDependencySource(
const evaluator::DependencyRecorder &e) const {
return std::get<0>(getStorage());
}
Optional<evaluator::SideEffect>
TypeCheckSourceFileRequest::getCachedResult() const {
auto *SF = std::get<0>(getStorage());
if (SF->ASTStage == SourceFile::TypeChecked)
return std::make_tuple<>();
return None;
}
void TypeCheckSourceFileRequest::cacheResult(evaluator::SideEffect) const {
auto *SF = std::get<0>(getStorage());
// Verify that we've checked types correctly.
SF->ASTStage = SourceFile::TypeChecked;
{
auto &Ctx = SF->getASTContext();
FrontendStatsTracer tracer(Ctx.Stats, "AST verification");
// Verify the SourceFile.
swift::verify(*SF);
}
}
//----------------------------------------------------------------------------//
// TypeCheckFunctionBodyRequest computation.
//----------------------------------------------------------------------------//
Optional<BraceStmt *> TypeCheckFunctionBodyRequest::getCachedResult() const {
using BodyKind = AbstractFunctionDecl::BodyKind;
auto *afd = std::get<0>(getStorage());
switch (afd->getBodyKind()) {
case BodyKind::Deserialized:
case BodyKind::MemberwiseInitializer:
case BodyKind::None:
case BodyKind::Skipped:
// These cases don't have any body available.
return nullptr;
case BodyKind::TypeChecked:
return afd->Body;
case BodyKind::Synthesize:
case BodyKind::Parsed:
case BodyKind::Unparsed:
return None;
}
llvm_unreachable("Unhandled BodyKind in switch");
}
void TypeCheckFunctionBodyRequest::cacheResult(BraceStmt *body) const {
auto *afd = std::get<0>(getStorage());
afd->setBody(body, AbstractFunctionDecl::BodyKind::TypeChecked);
}
evaluator::DependencySource
TypeCheckFunctionBodyRequest::readDependencySource(
const evaluator::DependencyRecorder &e) const {
return std::get<0>(getStorage())->getParentSourceFile();
}
//----------------------------------------------------------------------------//
// ModuleImplicitImportsRequest computation.
//----------------------------------------------------------------------------//
void swift::simple_display(llvm::raw_ostream &out,
const ImportedModule &module) {
out << "import of ";
if (!module.accessPath.empty()) {
module.accessPath.print(out);
out << " in ";
}
simple_display(out, module.importedModule);
}
void swift::simple_display(llvm::raw_ostream &out,
const UnloadedImportedModule &module) {
out << "import of ";
if (!module.getAccessPath().empty()) {
module.getAccessPath().print(out);
out << " in ";
}
out << "unloaded ";
module.getModulePath().print(out);
}
void swift::simple_display(llvm::raw_ostream &out,
const AttributedImport<std::tuple<>> &import) {
out << " [";
if (import.options.contains(ImportFlags::Exported))
out << " exported";
if (import.options.contains(ImportFlags::Testable))
out << " testable";
if (import.options.contains(ImportFlags::ImplementationOnly))
out << " implementation-only";
if (import.options.contains(ImportFlags::PrivateImport))
out << " private(" << import.sourceFileArg << ")";
if (import.options.contains(ImportFlags::SPIAccessControl)) {
out << " spi(";
llvm::interleaveComma(import.spiGroups, out, [&out](Identifier name) {
simple_display(out, name);
});
out << ")";
}
out << " ]";
}
void swift::simple_display(llvm::raw_ostream &out,
const ImplicitImportList &importList) {
llvm::interleaveComma(importList.imports, out,
[&](const auto &import) {
simple_display(out, import);
});
if (!importList.imports.empty() && !importList.unloadedImports.empty())
out << ", ";
llvm::interleaveComma(importList.unloadedImports, out,
[&](const auto &import) {
simple_display(out, import);
});
}
//----------------------------------------------------------------------------//
// ResolveTypeRequest computation.
//----------------------------------------------------------------------------//
void ResolveTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
auto *repr = std::get<1>(getStorage());
diags.diagnose(repr->getLoc(), diag::circular_type_resolution_note, repr);
}
void swift::simple_display(llvm::raw_ostream &out,
const TypeResolution *resolution) {
out << "while resolving type ";
}
SourceLoc swift::extractNearestSourceLoc(const TypeRepr *repr) {
if (!repr)
return SourceLoc();
return repr->getLoc();
}
//----------------------------------------------------------------------------//
// CustomAttrTypeRequest computation.
//----------------------------------------------------------------------------//
void swift::simple_display(llvm::raw_ostream &out, CustomAttrTypeKind value) {
switch (value) {
case CustomAttrTypeKind::NonGeneric:
out << "non-generic";
return;
case CustomAttrTypeKind::PropertyWrapper:
out << "property-wrapper";
return;
case CustomAttrTypeKind::GlobalActor:
out << "global-actor";
return;
}
llvm_unreachable("bad kind");
}
Optional<Type> CustomAttrTypeRequest::getCachedResult() const {
auto *attr = std::get<0>(getStorage());
if (auto ty = attr->getType()) {
return ty;
}
return None;
}
void CustomAttrTypeRequest::cacheResult(Type value) const {
auto *attr = std::get<0>(getStorage());
attr->setType(value);
}
bool ActorIsolation::requiresSubstitution() const {
switch (kind) {
case ActorInstance:
case Independent:
case IndependentUnsafe:
case Unspecified:
return false;
case GlobalActor:
return getGlobalActor()->hasTypeParameter();
}
llvm_unreachable("unhandled actor isolation kind!");
}
ActorIsolation ActorIsolation::subst(SubstitutionMap subs) const {
switch (kind) {
case ActorInstance:
case Independent:
case IndependentUnsafe:
case Unspecified:
return *this;
case GlobalActor:
return forGlobalActor(getGlobalActor().subst(subs));
}
llvm_unreachable("unhandled actor isolation kind!");
}
void swift::simple_display(
llvm::raw_ostream &out, const ActorIsolation &state) {
switch (state) {
case ActorIsolation::ActorInstance:
out << "actor-isolated to instance of " << state.getActor()->getName();
break;
case ActorIsolation::Independent:
out << "actor-independent";
break;
case ActorIsolation::IndependentUnsafe:
out << "actor-independent (unsafe)";
break;
case ActorIsolation::Unspecified:
out << "unspecified actor isolation";
break;
case ActorIsolation::GlobalActor:
out << "actor-isolated to global actor "
<< state.getGlobalActor().getString();
break;
}
}
bool swift::areTypesEqual(Type type1, Type type2) {
if (!type1 || !type2)
return !type1 && !type2;
return type1->isEqual(type2);
}
void swift::simple_display(
llvm::raw_ostream &out, BodyInitKind initKind) {
switch (initKind) {
case BodyInitKind::None: out << "none"; return;
case BodyInitKind::Delegating: out << "delegating"; return;
case BodyInitKind::Chained: out << "chained"; return;
case BodyInitKind::ImplicitChained: out << "implicit_chained"; return;
}
llvm_unreachable("Bad body init kind");
}
void swift::simple_display(
llvm::raw_ostream &out, BodyInitKindAndExpr initKindAndExpr) {
simple_display(out, initKindAndExpr.initKind);
out << " ";
simple_display(out, initKindAndExpr.initExpr);
}