blob: 87afbd2df37107fcb8f28e1cd272aa3fd515c23b [file] [log] [blame]
//===--- NameLookupRequests.h - Name Lookup Requests ------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines name-lookup requests.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_NAME_LOOKUP_REQUESTS_H
#define SWIFT_NAME_LOOKUP_REQUESTS_H
#include "swift/AST/SimpleRequest.h"
#include "swift/AST/ASTTypeIDs.h"
#include "swift/Basic/Statistic.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/TinyPtrVector.h"
namespace swift {
class ClassDecl;
class DestructorDecl;
class GenericContext;
class GenericParamList;
class TypeAliasDecl;
class TypeDecl;
namespace ast_scope {
class ASTScopeImpl;
class ScopeCreator;
} // namespace ast_scope
/// Display a nominal type or extension thereof.
void simple_display(
llvm::raw_ostream &out,
const llvm::PointerUnion<TypeDecl *, ExtensionDecl *> &value);
/// Describes a set of type declarations that are "direct" referenced by
/// a particular type in the AST.
using DirectlyReferencedTypeDecls = llvm::TinyPtrVector<TypeDecl *>;
/// Request the set of declarations directly referenced by the an "inherited"
/// type of a type or extension declaration.
///
/// This request retrieves the set of declarations that are directly referenced
/// by a particular type in the "inherited" clause of a type or extension
/// declaration. For example:
///
/// \code
/// protocol P { }
/// protocol Q { }
/// typealias Alias = P & Q
/// class C { }
///
/// class D: C, Alias { }
/// \endcode
///
/// The inherited declaration of \c D at index 0 is the class declaration C.
/// The inherited declaration of \c D at index 1 is the typealias Alias.
class InheritedDeclsReferencedRequest :
public SimpleRequest<InheritedDeclsReferencedRequest,
DirectlyReferencedTypeDecls(
llvm::PointerUnion<TypeDecl *, ExtensionDecl *>,
unsigned),
CacheKind::Uncached> // FIXME: Cache these
{
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
DirectlyReferencedTypeDecls evaluate(
Evaluator &evaluator,
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
unsigned index) const;
public:
// Caching
bool isCached() const { return true; }
// Source location information.
SourceLoc getNearestLoc() const;
};
/// Request the set of declarations directly referenced by the underlying
/// type of a typealias.
///
/// This request retrieves the set of type declarations that directly referenced
/// by the underlying type of a typealias. For example:
///
/// \code
/// protocol P { }
/// protocol Q { }
/// class C { }
/// typealias PQ = P & Q
/// typealias Alias = C & PQ
/// \endcode
///
/// The set of declarations referenced by the underlying type of \c PQ
/// contains both \c P and \c Q.
/// The set of declarations referenced by the underlying type of \c Alias
/// contains \c C and \c PQ. Clients can choose to look further into \c PQ
/// using another instance of this request.
class UnderlyingTypeDeclsReferencedRequest :
public SimpleRequest<UnderlyingTypeDeclsReferencedRequest,
DirectlyReferencedTypeDecls(TypeAliasDecl *),
CacheKind::Uncached> // FIXME: Cache these
{
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
DirectlyReferencedTypeDecls evaluate(
Evaluator &evaluator,
TypeAliasDecl *typealias) const;
public:
// Caching
bool isCached() const { return true; }
};
/// Request the superclass declaration for the given class.
class SuperclassDeclRequest :
public SimpleRequest<SuperclassDeclRequest,
ClassDecl *(NominalTypeDecl *),
CacheKind::SeparatelyCached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<ClassDecl *>
evaluate(Evaluator &evaluator, NominalTypeDecl *subject) const;
public:
// Caching
bool isCached() const { return true; }
Optional<ClassDecl *> getCachedResult() const;
void cacheResult(ClassDecl *value) const;
};
/// Request the nominal declaration extended by a given extension declaration.
class ExtendedNominalRequest :
public SimpleRequest<ExtendedNominalRequest,
NominalTypeDecl *(ExtensionDecl *),
CacheKind::SeparatelyCached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<NominalTypeDecl *>
evaluate(Evaluator &evaluator, ExtensionDecl *ext) const;
public:
// Separate caching.
bool isCached() const { return true; }
Optional<NominalTypeDecl *> getCachedResult() const;
void cacheResult(NominalTypeDecl *value) const;
};
struct SelfBounds {
llvm::TinyPtrVector<NominalTypeDecl *> decls;
bool anyObject = false;
};
/// Request the nominal types that occur as the right-hand side of "Self: Foo"
/// constraints in the "where" clause of a protocol extension.
class SelfBoundsFromWhereClauseRequest :
public SimpleRequest<SelfBoundsFromWhereClauseRequest,
SelfBounds(llvm::PointerUnion<TypeDecl *,
ExtensionDecl *>),
CacheKind::Uncached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
SelfBounds evaluate(Evaluator &evaluator,
llvm::PointerUnion<TypeDecl *, ExtensionDecl *>) const;
};
/// Request all type aliases and nominal types that appear in the "where"
/// clause of an extension.
class TypeDeclsFromWhereClauseRequest :
public SimpleRequest<TypeDeclsFromWhereClauseRequest,
DirectlyReferencedTypeDecls(ExtensionDecl *),
CacheKind::Uncached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
DirectlyReferencedTypeDecls evaluate(Evaluator &evaluator,
ExtensionDecl *ext) const;
};
/// Request the nominal type declaration to which the given custom attribute
/// refers.
class CustomAttrNominalRequest :
public SimpleRequest<CustomAttrNominalRequest,
NominalTypeDecl *(CustomAttr *, DeclContext *),
CacheKind::Cached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<NominalTypeDecl *>
evaluate(Evaluator &evaluator, CustomAttr *attr, DeclContext *dc) const;
public:
// Caching
bool isCached() const { return true; }
};
/// Finds or synthesizes a destructor for the given class.
class GetDestructorRequest :
public SimpleRequest<GetDestructorRequest,
DestructorDecl *(ClassDecl *),
CacheKind::SeparatelyCached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<DestructorDecl *>
evaluate(Evaluator &evaluator, ClassDecl *classDecl) const;
public:
// Caching
bool isCached() const { return true; }
Optional<DestructorDecl *> getCachedResult() const;
void cacheResult(DestructorDecl *value) const;
};
class GenericParamListRequest :
public SimpleRequest<GenericParamListRequest,
GenericParamList *(GenericContext *),
CacheKind::SeparatelyCached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<GenericParamList *>
evaluate(Evaluator &evaluator, GenericContext *value) const;
public:
// Separate caching.
bool isCached() const { return true; }
Optional<GenericParamList *> getCachedResult() const;
void cacheResult(GenericParamList *value) const;
};
struct PrecedenceGroupDescriptor {
DeclContext *dc;
Identifier ident;
SourceLoc nameLoc;
SourceLoc getLoc() const;
friend llvm::hash_code hash_value(const PrecedenceGroupDescriptor &owner) {
return hash_combine(llvm::hash_value(owner.dc),
llvm::hash_value(owner.ident.getAsOpaquePointer()),
llvm::hash_value(owner.nameLoc.getOpaquePointerValue()));
}
friend bool operator==(const PrecedenceGroupDescriptor &lhs,
const PrecedenceGroupDescriptor &rhs) {
return lhs.dc == rhs.dc &&
lhs.ident == rhs.ident &&
lhs.nameLoc == rhs.nameLoc;
}
friend bool operator!=(const PrecedenceGroupDescriptor &lhs,
const PrecedenceGroupDescriptor &rhs) {
return !(lhs == rhs);
}
};
void simple_display(llvm::raw_ostream &out, const PrecedenceGroupDescriptor &d);
class LookupPrecedenceGroupRequest
: public SimpleRequest<LookupPrecedenceGroupRequest,
PrecedenceGroupDecl *(PrecedenceGroupDescriptor),
CacheKind::Cached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<PrecedenceGroupDecl *>
evaluate(Evaluator &evaluator, PrecedenceGroupDescriptor descriptor) const;
public:
// Source location
SourceLoc getNearestLoc() const;
// Separate caching.
bool isCached() const { return true; }
};
/// Expand the given ASTScope. Requestified to detect recursion.
class ExpandASTScopeRequest
: public SimpleRequest<ExpandASTScopeRequest,
ast_scope::ASTScopeImpl *(ast_scope::ASTScopeImpl *,
ast_scope::ScopeCreator *),
CacheKind::SeparatelyCached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<ast_scope::ASTScopeImpl *>
evaluate(Evaluator &evaluator, ast_scope::ASTScopeImpl *,
ast_scope::ScopeCreator *) const;
public:
// Separate caching.
bool isCached() const;
Optional<ast_scope::ASTScopeImpl *> getCachedResult() const;
void cacheResult(ast_scope::ASTScopeImpl *) const {}
};
#define SWIFT_TYPEID_ZONE NameLookup
#define SWIFT_TYPEID_HEADER "swift/AST/NameLookupTypeIDZone.def"
#include "swift/Basic/DefineTypeIDZone.h"
#undef SWIFT_TYPEID_ZONE
#undef SWIFT_TYPEID_HEADER
// Set up reporting of evaluated requests.
template<typename Request>
void reportEvaluatedRequest(UnifiedStatsReporter &stats,
const Request &request);
#define SWIFT_REQUEST(Zone, RequestType, Sig, Caching, LocOptions) \
template <> \
inline void reportEvaluatedRequest(UnifiedStatsReporter &stats, \
const RequestType &request) { \
++stats.getFrontendCounters().RequestType; \
}
#include "swift/AST/NameLookupTypeIDZone.def"
#undef SWIFT_REQUEST
} // end namespace swift
#endif // SWIFT_NAME_LOOKUP_REQUESTS