blob: 9d3f3a9df636169bf8885a9c88491f829113cf39 [file] [log] [blame]
//===--- 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/Type.h"
#include "swift/AST/Evaluator.h"
#include "swift/AST/SimpleRequest.h"
#include "swift/AST/TypeResolutionStage.h"
#include "swift/Basic/Statistic.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/TinyPtrVector.h"
namespace swift {
class GenericParamList;
class RequirementRepr;
class SpecializeAttr;
struct TypeLoc;
/// 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,
CacheKind::SeparatelyCached,
Type,
llvm::PointerUnion<TypeDecl *, ExtensionDecl *>,
unsigned,
TypeResolutionStage>
{
/// Retrieve the TypeLoc for this inherited type.
TypeLoc &getTypeLoc(llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
unsigned index) const;
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:
// Cycle handling
void diagnoseCycle(DiagnosticEngine &diags) const;
void noteCycleStep(DiagnosticEngine &diags) 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,
CacheKind::SeparatelyCached,
Type,
NominalTypeDecl *,
TypeResolutionStage> {
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;
void noteCycleStep(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,
CacheKind::SeparatelyCached,
Type,
EnumDecl *,
TypeResolutionStage> {
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;
void noteCycleStep(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,
CacheKind::SeparatelyCached,
llvm::TinyPtrVector<ValueDecl *>,
ValueDecl *> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<llvm::TinyPtrVector<ValueDecl *>>
evaluate(Evaluator &evaluator, ValueDecl *decl) const;
public:
// Cycle handling
void diagnoseCycle(DiagnosticEngine &diags) const;
void noteCycleStep(DiagnosticEngine &diags) const;
// 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,
CacheKind::SeparatelyCached,
bool,
ValueDecl *> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<bool> evaluate(Evaluator &evaluator, ValueDecl *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 'dynamic''.
class IsDynamicRequest :
public SimpleRequest<IsDynamicRequest,
CacheKind::SeparatelyCached,
bool,
ValueDecl *> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<bool> evaluate(Evaluator &evaluator, ValueDecl *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;
};
/// 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::PointerUnion3<GenericParamList *, Decl *, SpecializeAttr *> source;
WhereClauseOwner(Decl *decl);
WhereClauseOwner(DeclContext *dc, GenericParamList *genericParams)
: dc(dc), source(genericParams) { }
WhereClauseOwner(DeclContext *dc, SpecializeAttr *attr)
: dc(dc), source(attr) { }
SourceLoc getLoc() const;
friend hash_code hash_value(const WhereClauseOwner &owner) {
return hash_combine(hash_value(owner.dc),
hash_value(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);
}
};
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,
CacheKind::SeparatelyCached,
Requirement,
WhereClauseOwner,
unsigned,
TypeResolutionStage> {
public:
using SimpleRequest::SimpleRequest;
/// Retrieve the array of requirements from the given owner.
static MutableArrayRef<RequirementRepr> getRequirements(WhereClauseOwner);
/// Visit each of the requirements in the given owner,
///
/// \returns true after short-circuiting if the callback returned \c true
/// for any of the requirements.
static bool visitRequirements(
WhereClauseOwner, TypeResolutionStage stage,
llvm::function_ref<bool(Requirement, RequirementRepr*)> callback);
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:
// Cycle handling
void diagnoseCycle(DiagnosticEngine &diags) const;
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,
CacheKind::Cached,
std::string,
const ValueDecl*>
{
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<std::string> evaluate(Evaluator &eval, const ValueDecl *d) const;
public:
// Cycle handling
void diagnoseCycle(DiagnosticEngine &diags) const;
void noteCycleStep(DiagnosticEngine &diags) const;
// Caching
bool isCached() const { return true; }
};
/// Generate the mangling for the given local type declaration.
class MangleLocalTypeDeclRequest :
public SimpleRequest<MangleLocalTypeDeclRequest,
CacheKind::Cached,
std::string,
const TypeDecl*>
{
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<std::string> evaluate(Evaluator &eval, const TypeDecl *d) const;
public:
// Cycle handling
void diagnoseCycle(DiagnosticEngine &diags) const;
void noteCycleStep(DiagnosticEngine &diags) const;
// 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, CacheKind::SeparatelyCached,
Type, KnownProtocolKind, const DeclContext *> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<Type> evaluate(Evaluator &eval, KnownProtocolKind,
const DeclContext *) const;
public:
// Cycle handling
void diagnoseCycle(DiagnosticEngine &diags) const;
void noteCycleStep(DiagnosticEngine &diags) const;
// Caching
bool isCached() const { return true; }
Optional<Type> getCachedResult() const;
void cacheResult(Type value) const;
private:
KnownProtocolKind getKnownProtocolKind() const {
return std::get<0>(getStorage());
}
const DeclContext *getDeclContext() const {
return std::get<1>(getStorage());
}
static const char *getTypeName(KnownProtocolKind);
static bool getPerformLocalLookup(KnownProtocolKind);
TypeChecker &getTypeChecker() const;
SourceFile *getSourceFile() const;
Type &getCache() const;
};
/// The zone number for the type checker.
#define SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE 10
#define SWIFT_TYPEID_ZONE SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE
#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_TYPEID(RequestType) \
template<> \
inline void reportEvaluatedRequest(UnifiedStatsReporter &stats, \
const RequestType &request) { \
++stats.getFrontendCounters().RequestType; \
}
#include "swift/AST/TypeCheckerTypeIDZone.def"
#undef SWIFT_TYPEID
} // end namespace swift
#endif // SWIFT_TYPE_CHECK_REQUESTS_H