blob: 1764a14222059c6e78ac426681a9acfc8f8c0510 [file] [log] [blame]
//===--- TypeCheckRequest.h - Type Checking Request -------------*- 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 the TypeCheckRequest type, which describes a request
// to the type checker to compute certain information.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SEMA_TYPE_CHECK_REQUEST_H
#define SWIFT_SEMA_TYPE_CHECK_REQUEST_H
#include "swift/AST/Identifier.h"
#include "swift/AST/Type.h"
#include "swift/Basic/SourceLoc.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
#include <utility>
namespace swift {
class ClassDecl;
class DeclContext;
class EnumDecl;
class ExtensionDecl;
class ProtocolDecl;
class TypeDecl;
class TypeRepr;
/// Describes the information needed to perform name lookup into a
/// declaration context.
struct DeclContextLookupInfo {
DeclContext *DC;
DeclName Name;
SourceLoc Loc;
friend bool operator==(const DeclContextLookupInfo &x,
const DeclContextLookupInfo &y) {
return x.DC == y.DC && x.Name == y.Name;
}
friend bool operator!=(const DeclContextLookupInfo &x,
const DeclContextLookupInfo &y) {
return !(x == y);
}
};
/// A request to the type checker to compute some particular kind of
/// information.
class TypeCheckRequest {
public:
/// Describes the kind of request.
enum Kind : uint8_t {
#define TYPE_CHECK_REQUEST(Request,Payload) \
Request,
#include "swift/Sema/TypeCheckRequestKinds.def"
} TheKind;
private:
/// The payload of the request, which differs based on the request kind.
union PayloadType {
PayloadType() { }
#define TYPE_CHECK_REQUEST_PAYLOAD(PayloadName,...) \
__VA_ARGS__ PayloadName;
#include "swift/Sema/TypeCheckRequestPayloads.def"
} Payload;
/// Describes the kind of payload expected.
///
/// The enumerators in this enumeration type are expected to map 1-1 to the
/// fields of the \c Payload union.
enum class PayloadKind {
#define TYPE_CHECK_REQUEST_PAYLOAD(PayloadName,...) \
PayloadName,
#include "swift/Sema/TypeCheckRequestPayloads.def"
};
/// Determine the payload kind for the given type check request kind.
static PayloadKind getPayloadKind(Kind kind) {
switch (kind) {
#define TYPE_CHECK_REQUEST(Request,PayloadName) \
case Request: \
return PayloadKind::PayloadName;
#include "swift/Sema/TypeCheckRequestKinds.def"
}
llvm_unreachable("Unhandled PayloadKind in switch.");
}
public:
// The payload types.
#define TYPE_CHECK_REQUEST_PAYLOAD(PayloadName,...) \
typedef __VA_ARGS__ PayloadName##PayloadType;
#include "swift/Sema/TypeCheckRequestPayloads.def"
// Constructors.
#define TYPE_CHECK_REQUEST_PAYLOAD(PayloadName,...) \
TypeCheckRequest(Kind kind, __VA_ARGS__ payload) : TheKind(kind) { \
assert(getPayloadKind(kind) == PayloadKind::PayloadName); \
Payload.PayloadName = payload; \
}
#include "swift/Sema/TypeCheckRequestPayloads.def"
TypeCheckRequest(const TypeCheckRequest &T) { *this = T; }
TypeCheckRequest& operator=(const TypeCheckRequest &T) {
TheKind = T.getKind();
switch (getPayloadKind(TheKind)) {
case PayloadKind::Class:
Payload.Class = T.Payload.Class;
break;
case PayloadKind::Enum:
Payload.Enum = T.Payload.Enum;
break;
case PayloadKind::InheritedClauseEntry:
new (&Payload.InheritedClauseEntry)
std::pair<llvm::PointerUnion<TypeDecl *, ExtensionDecl *>, unsigned>();
Payload.InheritedClauseEntry = T.Payload.InheritedClauseEntry;
break;
case PayloadKind::Protocol:
Payload.Protocol = T.Payload.Protocol;
break;
case PayloadKind::DeclContextLookup:
new (&Payload.DeclContextLookup) DeclContextLookupInfo();
Payload.DeclContextLookup = T.Payload.DeclContextLookup;
break;
case PayloadKind::TypeResolution:
new (&Payload.InheritedClauseEntry)
std::tuple<TypeRepr *, DeclContext *, unsigned>();
Payload.TypeResolution = T.Payload.TypeResolution;
break;
case PayloadKind::TypeDeclResolution:
Payload.TypeDeclResolution = T.Payload.TypeDeclResolution;
break;
}
return *this;
}
/// Determine the kind of type check request.
Kind getKind() const { return TheKind; }
// Payload retrieval.
#define TYPE_CHECK_REQUEST_PAYLOAD(PayloadName,...) \
__VA_ARGS__ get##PayloadName##Payload() const { \
assert(getPayloadKind(TheKind) == PayloadKind::PayloadName); \
return Payload.PayloadName; \
}
#include "swift/Sema/TypeCheckRequestPayloads.def"
/// Retrieve the location at which this request was initiated.
SourceLoc getLoc() const;
/// Retrieve the declaration to which this request was anchored.
///
/// A request is anchored on a declaration if the request is
/// specifically about that declaration, e.g., the superclass of a
/// class or some inheritance clause entry of a type.
Decl *getAnchor() const;
friend bool operator==(const TypeCheckRequest &x, const TypeCheckRequest &y);
};
/// A callback used to check whether a particular dependency of this
/// operation has been satisfied. If so, it returns \c false. If not,
/// the dependency will be recorded and this operation returns \c true.
typedef llvm::function_ref<bool(TypeCheckRequest)> UnsatisfiedDependency;
// Create requestXXX functions to more easily form type check requests
// of the appropriate type.
#define TYPE_CHECK_REQUEST(Request,PayloadName) \
inline TypeCheckRequest request##Request( \
TypeCheckRequest::PayloadName##PayloadType payload) {\
return TypeCheckRequest(TypeCheckRequest::Request, payload); \
}
#include "swift/Sema/TypeCheckRequestKinds.def"
/// Compare two type checking requests for equality.
bool operator==(const TypeCheckRequest &x, const TypeCheckRequest &y);
inline bool operator!=(const TypeCheckRequest &x, const TypeCheckRequest &y) {
return !(x == y);
}
}
#endif /* SWIFT_SEMA_TYPE_CHECK_REQUEST_H */