| //===--- TypeCheckRequests.h - Type Checking Requests -----------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines type checking requests. |
| // |
| //===----------------------------------------------------------------------===// |
| #ifndef SWIFT_TYPE_CHECK_REQUESTS_H |
| #define SWIFT_TYPE_CHECK_REQUESTS_H |
| |
| #include "swift/AST/ASTTypeIDs.h" |
| #include "swift/AST/GenericSignature.h" |
| #include "swift/AST/Type.h" |
| #include "swift/AST/Evaluator.h" |
| #include "swift/AST/SimpleRequest.h" |
| #include "swift/AST/TypeResolutionStage.h" |
| #include "swift/Basic/AnyValue.h" |
| #include "swift/Basic/Statistic.h" |
| #include "llvm/ADT/Hashing.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/ADT/TinyPtrVector.h" |
| |
| namespace swift { |
| |
| class AbstractStorageDecl; |
| class AccessorDecl; |
| enum class AccessorKind; |
| class GenericParamList; |
| class PrecedenceGroupDecl; |
| struct PropertyWrapperBackingPropertyInfo; |
| struct PropertyWrapperMutability; |
| class RequirementRepr; |
| class SpecializeAttr; |
| class TypeAliasDecl; |
| struct TypeLoc; |
| class ValueDecl; |
| enum class OpaqueReadOwnership: uint8_t; |
| class StorageImplInfo; |
| |
| /// Display a nominal type or extension thereof. |
| void simple_display( |
| llvm::raw_ostream &out, |
| const llvm::PointerUnion<TypeDecl *, ExtensionDecl *> &value); |
| |
| /// Request the type from the ith entry in the inheritance clause for the |
| /// given declaration. |
| class InheritedTypeRequest : |
| public SimpleRequest<InheritedTypeRequest, |
| Type(llvm::PointerUnion<TypeDecl *, ExtensionDecl *>, |
| unsigned, |
| TypeResolutionStage), |
| CacheKind::SeparatelyCached> |
| { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<Type> |
| evaluate(Evaluator &evaluator, |
| llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl, |
| unsigned index, |
| TypeResolutionStage stage) const; |
| |
| public: |
| // Source location |
| SourceLoc getNearestLoc() const; |
| |
| // Caching |
| bool isCached() const; |
| Optional<Type> getCachedResult() const; |
| void cacheResult(Type value) const; |
| }; |
| |
| /// Request the superclass type for the given class. |
| class SuperclassTypeRequest : |
| public SimpleRequest<SuperclassTypeRequest, |
| Type(NominalTypeDecl *, TypeResolutionStage), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<Type> |
| evaluate(Evaluator &evaluator, NominalTypeDecl *classDecl, |
| TypeResolutionStage stage) const; |
| |
| public: |
| // Cycle handling |
| void diagnoseCycle(DiagnosticEngine &diags) const; |
| |
| // Separate caching. |
| bool isCached() const; |
| Optional<Type> getCachedResult() const; |
| void cacheResult(Type value) const; |
| }; |
| |
| /// Request the raw type of the given enum. |
| class EnumRawTypeRequest : |
| public SimpleRequest<EnumRawTypeRequest, |
| Type(EnumDecl *, TypeResolutionStage), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<Type> |
| evaluate(Evaluator &evaluator, EnumDecl *enumDecl, |
| TypeResolutionStage stage) const; |
| |
| public: |
| // Cycle handling |
| void diagnoseCycle(DiagnosticEngine &diags) const; |
| |
| // Separate caching. |
| bool isCached() const; |
| Optional<Type> getCachedResult() const; |
| void cacheResult(Type value) const; |
| }; |
| |
| /// Request to determine the set of declarations that were are overridden |
| /// by the given declaration. |
| class OverriddenDeclsRequest : |
| public SimpleRequest<OverriddenDeclsRequest, |
| llvm::TinyPtrVector<ValueDecl *>(ValueDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<llvm::TinyPtrVector<ValueDecl *>> |
| evaluate(Evaluator &evaluator, ValueDecl *decl) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<llvm::TinyPtrVector<ValueDecl *>> getCachedResult() const; |
| void cacheResult(llvm::TinyPtrVector<ValueDecl *> value) const; |
| }; |
| |
| /// Determine whether the given declaration is exposed to Objective-C. |
| class IsObjCRequest : |
| public SimpleRequest<IsObjCRequest, |
| bool(ValueDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> evaluate(Evaluator &evaluator, ValueDecl *decl) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| void simple_display(llvm::raw_ostream &out, CtorInitializerKind initKind); |
| |
| /// Computes the kind of initializer for a given \c ConstructorDecl |
| class InitKindRequest : |
| public SimpleRequest<InitKindRequest, |
| CtorInitializerKind(ConstructorDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<CtorInitializerKind> |
| evaluate(Evaluator &evaluator, ConstructorDecl *decl) const; |
| |
| public: |
| // Caching. |
| bool isCached() const { return true; } |
| }; |
| |
| /// Determine whether the given protocol declaration is class-bounded. |
| class ProtocolRequiresClassRequest : |
| public SimpleRequest<ProtocolRequiresClassRequest, |
| bool(ProtocolDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> evaluate(Evaluator &evaluator, ProtocolDecl *decl) const; |
| |
| public: |
| // Cycle handling. |
| void diagnoseCycle(DiagnosticEngine &diags) const; |
| void noteCycleStep(DiagnosticEngine &diags) const; |
| |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| /// Determine whether an existential conforming to a protocol can be matched |
| /// with a generic type parameter constrained to that protocol. |
| class ExistentialConformsToSelfRequest : |
| public SimpleRequest<ExistentialConformsToSelfRequest, |
| bool(ProtocolDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> evaluate(Evaluator &evaluator, ProtocolDecl *decl) const; |
| |
| public: |
| // Cycle handling. |
| void diagnoseCycle(DiagnosticEngine &diags) const; |
| void noteCycleStep(DiagnosticEngine &diags) const; |
| |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| /// Determine whether we are allowed to refer to an existential type conforming |
| /// to this protocol. |
| class ExistentialTypeSupportedRequest : |
| public SimpleRequest<ExistentialTypeSupportedRequest, |
| bool(ProtocolDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> evaluate(Evaluator &evaluator, ProtocolDecl *decl) const; |
| |
| public: |
| // Cycle handling. |
| void diagnoseCycle(DiagnosticEngine &diags) const; |
| void noteCycleStep(DiagnosticEngine &diags) const; |
| |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| /// Determine whether the given declaration is 'final'. |
| class IsFinalRequest : |
| public SimpleRequest<IsFinalRequest, |
| bool(ValueDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> evaluate(Evaluator &evaluator, ValueDecl *decl) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| /// Determine whether the given declaration is 'dynamic''. |
| class IsDynamicRequest : |
| public SimpleRequest<IsDynamicRequest, |
| bool(ValueDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> evaluate(Evaluator &evaluator, ValueDecl *decl) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| /// Compute the requirements that describe a protocol. |
| class RequirementSignatureRequest : |
| public SimpleRequest<RequirementSignatureRequest, |
| ArrayRef<Requirement>(ProtocolDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<ArrayRef<Requirement>> evaluate(Evaluator &evaluator, ProtocolDecl *proto) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<ArrayRef<Requirement>> getCachedResult() const; |
| void cacheResult(ArrayRef<Requirement> value) const; |
| }; |
| |
| /// Compute the default definition type of an associated type. |
| class DefaultDefinitionTypeRequest : |
| public SimpleRequest<DefaultDefinitionTypeRequest, |
| Type(AssociatedTypeDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<Type> evaluate(Evaluator &evaluator, AssociatedTypeDecl *decl) const; |
| |
| public: |
| // Caching. |
| bool isCached() const { return true; } |
| }; |
| |
| /// Describes the owner of a where clause, from which we can extract |
| /// requirements. |
| struct WhereClauseOwner { |
| /// The declaration context in which the where clause will be evaluated. |
| DeclContext *dc; |
| |
| /// The source of the where clause, which can be a generic parameter list |
| /// or a declaration that can have a where clause. |
| llvm::PointerUnion<GenericParamList *, Decl *, SpecializeAttr *, |
| // SWIFT_ENABLE_TENSORFLOW |
| DifferentiableAttr *> |
| source; |
| |
| WhereClauseOwner(Decl *decl); |
| |
| WhereClauseOwner(DeclContext *dc, GenericParamList *genericParams) |
| : dc(dc), source(genericParams) {} |
| |
| WhereClauseOwner(DeclContext *dc, SpecializeAttr *attr) |
| : dc(dc), source(attr) {} |
| |
| // SWIFT_ENABLE_TENSORFLOW |
| WhereClauseOwner(DeclContext *dc, DifferentiableAttr *attr) |
| : dc(dc), source(attr) {} |
| |
| SourceLoc getLoc() const; |
| |
| friend hash_code hash_value(const WhereClauseOwner &owner) { |
| return llvm::hash_combine(owner.dc, owner.source.getOpaqueValue()); |
| } |
| |
| friend bool operator==(const WhereClauseOwner &lhs, |
| const WhereClauseOwner &rhs) { |
| return lhs.dc == rhs.dc && |
| lhs.source.getOpaqueValue() == rhs.source.getOpaqueValue(); |
| } |
| |
| friend bool operator!=(const WhereClauseOwner &lhs, |
| const WhereClauseOwner &rhs) { |
| return !(lhs == rhs); |
| } |
| |
| public: |
| /// Retrieve the array of requirements. |
| MutableArrayRef<RequirementRepr> getRequirements() const; |
| |
| /// Visit each of the requirements, |
| /// |
| /// \returns true after short-circuiting if the callback returned \c true |
| /// for any of the requirements. |
| bool |
| visitRequirements(TypeResolutionStage stage, |
| llvm::function_ref<bool(Requirement, RequirementRepr *)> |
| callback) const &&; |
| }; |
| |
| void simple_display(llvm::raw_ostream &out, const WhereClauseOwner &owner); |
| |
| /// Retrieve a requirement from the where clause of the given declaration. |
| class RequirementRequest : |
| public SimpleRequest<RequirementRequest, |
| Requirement(WhereClauseOwner, unsigned, |
| TypeResolutionStage), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| /// Retrieve the requirement this request operates on. |
| RequirementRepr &getRequirement() const; |
| |
| // Evaluation. |
| llvm::Expected<Requirement> evaluate(Evaluator &evaluator, |
| WhereClauseOwner, |
| unsigned index, |
| TypeResolutionStage stage) const; |
| |
| public: |
| // Source location |
| SourceLoc getNearestLoc() const; |
| |
| // Cycle handling. |
| void noteCycleStep(DiagnosticEngine &diags) const; |
| |
| // Separate caching. |
| bool isCached() const; |
| Optional<Requirement> getCachedResult() const; |
| void cacheResult(Requirement value) const; |
| }; |
| |
| /// Generate the USR for the given declaration. |
| class USRGenerationRequest : |
| public SimpleRequest<USRGenerationRequest, |
| std::string(const ValueDecl*), |
| CacheKind::Cached> |
| { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<std::string> evaluate(Evaluator &eval, const ValueDecl *d) const; |
| |
| public: |
| // Caching |
| bool isCached() const { return true; } |
| }; |
| |
| /// Generate the mangling for the given local type declaration. |
| class MangleLocalTypeDeclRequest : |
| public SimpleRequest<MangleLocalTypeDeclRequest, |
| std::string(const TypeDecl*), |
| CacheKind::Cached> |
| { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<std::string> evaluate(Evaluator &eval, const TypeDecl *d) const; |
| |
| public: |
| // Caching |
| bool isCached() const { return true; } |
| }; |
| |
| void simple_display(llvm::raw_ostream &out, const KnownProtocolKind); |
| class TypeChecker; |
| |
| // Find the type in the cache or look it up |
| class DefaultTypeRequest |
| : public SimpleRequest<DefaultTypeRequest, |
| Type(KnownProtocolKind, const DeclContext *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<Type> evaluate(Evaluator &eval, KnownProtocolKind, |
| const DeclContext *) const; |
| |
| public: |
| // Caching |
| bool isCached() const { return true; } |
| Optional<Type> getCachedResult() const; |
| void cacheResult(Type value) const; |
| }; |
| |
| /// Retrieve information about a property wrapper type. |
| class PropertyWrapperTypeInfoRequest |
| : public SimpleRequest<PropertyWrapperTypeInfoRequest, |
| PropertyWrapperTypeInfo(NominalTypeDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<PropertyWrapperTypeInfo> |
| evaluate(Evaluator &eval, NominalTypeDecl *nominal) const; |
| |
| public: |
| // Caching |
| bool isCached() const; |
| }; |
| |
| /// Request the nominal type declaration to which the given custom attribute |
| /// refers. |
| class AttachedPropertyWrappersRequest : |
| public SimpleRequest<AttachedPropertyWrappersRequest, |
| llvm::TinyPtrVector<CustomAttr *>(VarDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<llvm::TinyPtrVector<CustomAttr *>> |
| evaluate(Evaluator &evaluator, VarDecl *) const; |
| |
| public: |
| // Caching |
| bool isCached() const; |
| }; |
| |
| /// Request the raw (possibly unbound generic) type of the property wrapper |
| /// that is attached to the given variable. |
| class AttachedPropertyWrapperTypeRequest : |
| public SimpleRequest<AttachedPropertyWrapperTypeRequest, |
| Type(VarDecl *, unsigned), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<Type> |
| evaluate(Evaluator &evaluator, VarDecl *var, unsigned i) const; |
| |
| public: |
| // Caching |
| bool isCached() const; |
| }; |
| |
| /// Request the nominal type declaration to which the given custom attribute |
| /// refers. |
| class PropertyWrapperBackingPropertyTypeRequest : |
| public SimpleRequest<PropertyWrapperBackingPropertyTypeRequest, |
| Type(VarDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<Type> |
| evaluate(Evaluator &evaluator, VarDecl *var) const; |
| |
| public: |
| // Caching |
| bool isCached() const; |
| }; |
| |
| /// Request information about the mutability of composed property wrappers. |
| class PropertyWrapperMutabilityRequest : |
| public SimpleRequest<PropertyWrapperMutabilityRequest, |
| Optional<PropertyWrapperMutability> (VarDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<Optional<PropertyWrapperMutability>> |
| evaluate(Evaluator &evaluator, VarDecl *var) const; |
| |
| public: |
| // Caching |
| bool isCached() const; |
| }; |
| |
| /// Request information about the backing property for properties that have |
| /// attached property wrappers. |
| class PropertyWrapperBackingPropertyInfoRequest : |
| public SimpleRequest<PropertyWrapperBackingPropertyInfoRequest, |
| PropertyWrapperBackingPropertyInfo(VarDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<PropertyWrapperBackingPropertyInfo> |
| evaluate(Evaluator &evaluator, VarDecl *var) const; |
| |
| public: |
| // Caching |
| bool isCached() const; |
| }; |
| |
| /// Retrieve the structural type of an alias type. |
| class StructuralTypeRequest : |
| public SimpleRequest<StructuralTypeRequest, |
| Type(TypeAliasDecl*), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<Type> evaluate(Evaluator &eval, TypeAliasDecl *d) const; |
| |
| public: |
| // Caching. |
| bool isCached() const { return true; } |
| }; |
| |
| /// Request the most optimal resilience expansion for the code in the context. |
| class ResilienceExpansionRequest : |
| public SimpleRequest<ResilienceExpansionRequest, |
| ResilienceExpansion(DeclContext*), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<ResilienceExpansion> evaluate(Evaluator &eval, |
| DeclContext *context) const; |
| |
| public: |
| // Caching. |
| bool isCached() const { return true; } |
| }; |
| |
| void simple_display(llvm::raw_ostream &out, |
| const ResilienceExpansion &value); |
| |
| /// Request the custom attribute which attaches a function builder to the |
| /// given declaration. |
| class AttachedFunctionBuilderRequest : |
| public SimpleRequest<AttachedFunctionBuilderRequest, |
| CustomAttr *(ValueDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<CustomAttr *> |
| evaluate(Evaluator &evaluator, ValueDecl *decl) const; |
| |
| public: |
| // Caching |
| bool isCached() const; |
| }; |
| |
| /// Request the function builder type attached to the given declaration, |
| /// if any. |
| class FunctionBuilderTypeRequest : |
| public SimpleRequest<FunctionBuilderTypeRequest, |
| Type(ValueDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| llvm::Expected<Type> |
| evaluate(Evaluator &evaluator, ValueDecl *decl) const; |
| |
| public: |
| // Caching |
| bool isCached() const { return true; } |
| }; |
| |
| /// Request a function's self access kind. |
| class SelfAccessKindRequest : |
| public SimpleRequest<SelfAccessKindRequest, |
| SelfAccessKind(FuncDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<SelfAccessKind> |
| evaluate(Evaluator &evaluator, FuncDecl *func) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<SelfAccessKind> getCachedResult() const; |
| void cacheResult(SelfAccessKind value) const; |
| }; |
| |
| /// Request whether the storage has a mutating getter. |
| class IsGetterMutatingRequest : |
| public SimpleRequest<IsGetterMutatingRequest, |
| bool(AbstractStorageDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> |
| evaluate(Evaluator &evaluator, AbstractStorageDecl *func) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| /// Request whether the storage has a mutating getter. |
| class IsSetterMutatingRequest : |
| public SimpleRequest<IsSetterMutatingRequest, |
| bool(AbstractStorageDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> |
| evaluate(Evaluator &evaluator, AbstractStorageDecl *func) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| /// Request whether reading the storage yields a borrowed value. |
| class OpaqueReadOwnershipRequest : |
| public SimpleRequest<OpaqueReadOwnershipRequest, |
| OpaqueReadOwnership(AbstractStorageDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<OpaqueReadOwnership> |
| evaluate(Evaluator &evaluator, AbstractStorageDecl *storage) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<OpaqueReadOwnership> getCachedResult() const; |
| void cacheResult(OpaqueReadOwnership value) const; |
| }; |
| |
| /// Request to build the underlying storage for a lazy property. |
| class LazyStoragePropertyRequest : |
| public SimpleRequest<LazyStoragePropertyRequest, |
| VarDecl *(VarDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<VarDecl *> |
| evaluate(Evaluator &evaluator, VarDecl *lazyVar) const; |
| |
| public: |
| bool isCached() const { return true; } |
| }; |
| |
| /// Request to type check the body of the given function up to the given |
| /// source location. |
| /// |
| /// Produces true if an error occurred, false otherwise. |
| /// FIXME: it would be far better to return the type-checked body. |
| class TypeCheckFunctionBodyUntilRequest : |
| public SimpleRequest<TypeCheckFunctionBodyUntilRequest, |
| bool(AbstractFunctionDecl *, SourceLoc), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> |
| evaluate(Evaluator &evaluator, AbstractFunctionDecl *func, |
| SourceLoc endTypeCheckLoc) const; |
| |
| public: |
| bool isCached() const { return true; } |
| }; |
| |
| /// Request to obtain a list of stored properties in a nominal type. |
| /// |
| /// This will include backing storage for lazy properties and |
| /// property wrappers, synthesizing them if necessary. |
| class StoredPropertiesRequest : |
| public SimpleRequest<StoredPropertiesRequest, |
| ArrayRef<VarDecl *>(NominalTypeDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<ArrayRef<VarDecl *>> |
| evaluate(Evaluator &evaluator, NominalTypeDecl *decl) const; |
| |
| public: |
| bool isCached() const { return true; } |
| }; |
| |
| /// Request to obtain a list of stored properties in a nominal type, |
| /// together with any missing members corresponding to stored |
| /// properties that could not be deserialized. |
| /// |
| /// This will include backing storage for lazy properties and |
| /// property wrappers, synthesizing them if necessary. |
| class StoredPropertiesAndMissingMembersRequest : |
| public SimpleRequest<StoredPropertiesAndMissingMembersRequest, |
| ArrayRef<Decl *>(NominalTypeDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<ArrayRef<Decl *>> |
| evaluate(Evaluator &evaluator, NominalTypeDecl *decl) const; |
| |
| public: |
| bool isCached() const { return true; } |
| }; |
| |
| class StorageImplInfoRequest : |
| public SimpleRequest<StorageImplInfoRequest, |
| StorageImplInfo(AbstractStorageDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<StorageImplInfo> |
| evaluate(Evaluator &evaluator, AbstractStorageDecl *decl) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<StorageImplInfo> getCachedResult() const; |
| void cacheResult(StorageImplInfo value) const; |
| }; |
| |
| class RequiresOpaqueAccessorsRequest : |
| public SimpleRequest<RequiresOpaqueAccessorsRequest, |
| bool(VarDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> |
| evaluate(Evaluator &evaluator, VarDecl *decl) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| class RequiresOpaqueModifyCoroutineRequest : |
| public SimpleRequest<RequiresOpaqueModifyCoroutineRequest, |
| bool(AbstractStorageDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> |
| evaluate(Evaluator &evaluator, AbstractStorageDecl *decl) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| class IsAccessorTransparentRequest : |
| public SimpleRequest<IsAccessorTransparentRequest, |
| bool(AccessorDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> |
| evaluate(Evaluator &evaluator, AccessorDecl *decl) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| class SynthesizeAccessorRequest : |
| public SimpleRequest<SynthesizeAccessorRequest, |
| AccessorDecl *(AbstractStorageDecl *, |
| AccessorKind), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<AccessorDecl *> |
| evaluate(Evaluator &evaluator, AbstractStorageDecl *decl, |
| AccessorKind kind) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<AccessorDecl *> getCachedResult() const; |
| void cacheResult(AccessorDecl *value) const; |
| }; |
| |
| class EmittedMembersRequest : |
| public SimpleRequest<EmittedMembersRequest, |
| DeclRange(ClassDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<DeclRange> |
| evaluate(Evaluator &evaluator, ClassDecl *classDecl) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<DeclRange> getCachedResult() const; |
| void cacheResult(DeclRange value) const; |
| }; |
| |
| class IsImplicitlyUnwrappedOptionalRequest : |
| public SimpleRequest<IsImplicitlyUnwrappedOptionalRequest, |
| bool(ValueDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> |
| evaluate(Evaluator &evaluator, ValueDecl *value) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| class ClassAncestryFlagsRequest : |
| public SimpleRequest<ClassAncestryFlagsRequest, |
| AncestryFlags (ClassDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<AncestryFlags> |
| evaluate(Evaluator &evaluator, ClassDecl *value) const; |
| public: |
| // Caching. |
| bool isCached() const { return true; } |
| }; |
| |
| void simple_display(llvm::raw_ostream &out, AncestryFlags value); |
| |
| class AbstractGenericSignatureRequest : |
| public SimpleRequest<AbstractGenericSignatureRequest, |
| GenericSignature (GenericSignatureImpl *, |
| SmallVector<GenericTypeParamType *, 2>, |
| SmallVector<Requirement, 2>), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<GenericSignature> |
| evaluate(Evaluator &evaluator, |
| GenericSignatureImpl *baseSignature, |
| SmallVector<GenericTypeParamType *, 2> addedParameters, |
| SmallVector<Requirement, 2> addedRequirements) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const; |
| |
| /// Abstract generic signature requests never have source-location info. |
| SourceLoc getNearestLoc() const { |
| return SourceLoc(); |
| } |
| }; |
| |
| class InferredGenericSignatureRequest : |
| public SimpleRequest<InferredGenericSignatureRequest, |
| GenericSignature (ModuleDecl *, |
| GenericSignatureImpl *, |
| GenericParamList *, |
| SmallVector<Requirement, 2>, |
| SmallVector<TypeLoc, 2>, |
| bool), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<GenericSignature> |
| evaluate(Evaluator &evaluator, |
| ModuleDecl *module, |
| GenericSignatureImpl *baseSignature, |
| GenericParamList *gpl, |
| SmallVector<Requirement, 2> addedRequirements, |
| SmallVector<TypeLoc, 2> inferenceSources, |
| bool allowConcreteGenericParams) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const; |
| |
| /// Inferred generic signature requests don't have source-location info. |
| SourceLoc getNearestLoc() const { |
| return SourceLoc(); |
| } |
| |
| // Cycle handling. |
| void noteCycleStep(DiagnosticEngine &diags) const; |
| }; |
| |
| void simple_display(llvm::raw_ostream &out, const TypeLoc source); |
| |
| class ExtendedTypeRequest |
| : public SimpleRequest<ExtendedTypeRequest, |
| Type(ExtensionDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<Type> evaluate(Evaluator &eval, ExtensionDecl *) const; |
| public: |
| // Caching. |
| bool isCached() const { return true; } |
| }; |
| |
| class FunctionOperatorRequest : |
| public SimpleRequest<FunctionOperatorRequest, |
| OperatorDecl *(FuncDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<OperatorDecl *> |
| evaluate(Evaluator &evaluator, FuncDecl *value) const; |
| |
| public: |
| // Caching. |
| bool isCached() const { return true; } |
| }; |
| |
| class GenericSignatureRequest : |
| public SimpleRequest<GenericSignatureRequest, |
| GenericSignature (GenericContext *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<GenericSignature> |
| evaluate(Evaluator &evaluator, GenericContext *value) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<GenericSignature> getCachedResult() const; |
| void cacheResult(GenericSignature value) const; |
| }; |
| |
| /// Compute the underlying interface type of a typealias. |
| class UnderlyingTypeRequest : |
| public SimpleRequest<UnderlyingTypeRequest, |
| Type(TypeAliasDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<Type> evaluate(Evaluator &evaluator, |
| TypeAliasDecl *decl) const; |
| |
| public: |
| // Caching. |
| bool isCached() const { return true; } |
| Optional<Type> getCachedResult() const; |
| void cacheResult(Type value) const; |
| void diagnoseCycle(DiagnosticEngine &diags) const; |
| }; |
| |
| /// Looks up the precedence group of an operator declaration. |
| class OperatorPrecedenceGroupRequest |
| : public SimpleRequest<OperatorPrecedenceGroupRequest, |
| PrecedenceGroupDecl *(InfixOperatorDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<PrecedenceGroupDecl *> |
| evaluate(Evaluator &evaluator, InfixOperatorDecl *PGD) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| }; |
| |
| /// Computes the raw values for an enum type. |
| class EnumRawValuesRequest : |
| public SimpleRequest<EnumRawValuesRequest, |
| bool (EnumDecl *, TypeResolutionStage), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> |
| evaluate(Evaluator &evaluator, EnumDecl *ED, TypeResolutionStage stage) const; |
| |
| public: |
| // Cycle handling. |
| void diagnoseCycle(DiagnosticEngine &diags) const; |
| void noteCycleStep(DiagnosticEngine &diags) const; |
| |
| // Separate caching. |
| bool isCached() const; |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| /// Determines if an override is ABI compatible with its base method. |
| class IsABICompatibleOverrideRequest |
| : public SimpleRequest<IsABICompatibleOverrideRequest, bool(ValueDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> evaluate(Evaluator &evaluator, ValueDecl *decl) const; |
| |
| public: |
| // Caching. |
| bool isCached() const { return true; } |
| }; |
| |
| /// Builds an opaque result type for a declaration. |
| class OpaqueResultTypeRequest |
| : public SimpleRequest<OpaqueResultTypeRequest, |
| OpaqueTypeDecl *(ValueDecl *), |
| CacheKind::Cached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| llvm::Expected<OpaqueTypeDecl *> |
| evaluate(Evaluator &evaluator, ValueDecl *VD) const; |
| |
| public: |
| // Caching. |
| bool isCached() const { return true; } |
| }; |
| |
| /// Determines if a function declaration is 'static'. |
| class IsStaticRequest : |
| public SimpleRequest<IsStaticRequest, |
| bool(FuncDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> |
| evaluate(Evaluator &evaluator, FuncDecl *value) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| /// Determines if a method override should introduce a new vtable entry, |
| /// because the override is not ABI compatible, or the base method is |
| /// less visible than the override. |
| class NeedsNewVTableEntryRequest |
| : public SimpleRequest<NeedsNewVTableEntryRequest, |
| bool(AbstractFunctionDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<bool> evaluate(Evaluator &evaluator, |
| AbstractFunctionDecl *decl) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<bool> getCachedResult() const; |
| void cacheResult(bool value) const; |
| }; |
| |
| /// Determines the specifier for a parameter (inout, __owned, etc). |
| class ParamSpecifierRequest |
| : public SimpleRequest<ParamSpecifierRequest, |
| ParamSpecifier(ParamDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| // Evaluation. |
| llvm::Expected<ParamSpecifier> |
| evaluate(Evaluator &evaluator, ParamDecl *decl) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<ParamSpecifier> getCachedResult() const; |
| void cacheResult(ParamSpecifier value) const; |
| }; |
| |
| /// Determines the result type of a function or element type of a subscript. |
| class ResultTypeRequest |
| : public SimpleRequest<ResultTypeRequest, |
| Type(ValueDecl *), |
| CacheKind::SeparatelyCached> { |
| public: |
| using SimpleRequest::SimpleRequest; |
| |
| private: |
| friend SimpleRequest; |
| |
| TypeLoc &getResultTypeLoc() const; |
| |
| // Evaluation. |
| llvm::Expected<Type> evaluate(Evaluator &evaluator, ValueDecl *decl) const; |
| |
| public: |
| // Separate caching. |
| bool isCached() const { return true; } |
| Optional<Type> getCachedResult() const; |
| void cacheResult(Type value) const; |
| }; |
| |
| // Allow AnyValue to compare two Type values, even though Type doesn't |
| // support ==. |
| template<> |
| inline bool AnyValue::Holder<Type>::equals(const HolderBase &other) const { |
| assert(typeID == other.typeID && "Caller should match type IDs"); |
| return value.getPointer() == |
| static_cast<const Holder<Type> &>(other).value.getPointer(); |
| } |
| |
| // Allow AnyValue to compare two GenericSignature values. |
| template <> |
| inline bool |
| AnyValue::Holder<GenericSignature>::equals(const HolderBase &other) const { |
| assert(typeID == other.typeID && "Caller should match type IDs"); |
| return value.getPointer() == |
| static_cast<const Holder<GenericSignature> &>(other) |
| .value.getPointer(); |
| } |
| |
| void simple_display(llvm::raw_ostream &out, Type value); |
| void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR); |
| |
| #define SWIFT_TYPEID_ZONE TypeChecker |
| #define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def" |
| #include "swift/Basic/DefineTypeIDZone.h" |
| #undef SWIFT_TYPEID_ZONE |
| #undef SWIFT_TYPEID_HEADER |
| |
| // Set up reporting of evaluated requests. |
| #define SWIFT_REQUEST(Zone, RequestType, Sig, Caching, LocOptions) \ |
| template<> \ |
| inline void reportEvaluatedRequest(UnifiedStatsReporter &stats, \ |
| const RequestType &request) { \ |
| ++stats.getFrontendCounters().RequestType; \ |
| } |
| #include "swift/AST/TypeCheckerTypeIDZone.def" |
| #undef SWIFT_REQUEST |
| |
| } // end namespace swift |
| |
| #endif // SWIFT_TYPE_CHECK_REQUESTS_H |