blob: 48894a0f6cf3743f790af22df3fde2da69cb2f8d [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/TypeCheckRequests.h"
#include "swift/AST/Decl.h"
#include "swift/AST/DiagnosticsCommon.h"
#include "swift/AST/TypeLoc.h"
#include "swift/AST/Types.h"
using namespace swift;
namespace swift {
// Implement the type checker type zone (zone 10).
#define SWIFT_TYPEID_ZONE SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE
#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<TypeDecl *, ExtensionDecl *> &value) {
if (auto type = value.dyn_cast<TypeDecl *>()) {
type->dumpRef(out);
return;
}
auto ext = value.get<ExtensionDecl *>();
out << "extension of ";
ext->getAsNominalTypeOrNominalTypeExtensionContext()->dumpRef(out);
}
//----------------------------------------------------------------------------//
// Inherited type computation.
//----------------------------------------------------------------------------//
TypeLoc &InheritedTypeRequest::getTypeLoc(
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
unsigned index) const {
if (auto typeDecl = decl.dyn_cast<TypeDecl *>())
return typeDecl->getInherited()[index];
return decl.get<ExtensionDecl *>()->getInherited()[index];
}
void InheritedTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
const auto &storage = getStorage();
auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
diags.diagnose(typeLoc.getLoc(), diag::circular_reference);
}
void InheritedTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
const auto &storage = getStorage();
auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
diags.diagnose(typeLoc.getLoc(), diag::circular_reference_through);
}
Optional<Type> InheritedTypeRequest::getCachedResult() const {
const auto &storage = getStorage();
auto &typeLoc = getTypeLoc(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 = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
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());
}
void SuperclassTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
auto nominalDecl = std::get<0>(getStorage());
// FIXME: Customize this further.
diags.diagnose(nominalDecl, diag::circular_reference_through);
}
Optional<Type> SuperclassTypeRequest::getCachedResult() const {
auto nominalDecl = std::get<0>(getStorage());
if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
if (classDecl->LazySemanticInfo.Superclass.getInt())
return classDecl->LazySemanticInfo.Superclass.getPointer();
if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
if (protocolDecl->LazySemanticInfo.Superclass.getInt())
return protocolDecl->LazySemanticInfo.Superclass.getPointer();
return None;
}
void SuperclassTypeRequest::cacheResult(Type value) const {
auto nominalDecl = std::get<0>(getStorage());
if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
classDecl->LazySemanticInfo.Superclass.setPointerAndInt(value, true);
if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
protocolDecl->LazySemanticInfo.Superclass.setPointerAndInt(value, true);
}
//----------------------------------------------------------------------------//
// 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 enumDecl = std::get<0>(getStorage());
// FIXME: Customize this further.
diags.diagnose(enumDecl, diag::circular_reference_through);
}
Optional<Type> EnumRawTypeRequest::getCachedResult() const {
auto enumDecl = std::get<0>(getStorage());
if (enumDecl->LazySemanticInfo.RawType.getInt())
return enumDecl->LazySemanticInfo.RawType.getPointer();
return None;
}
void EnumRawTypeRequest::cacheResult(Type value) const {
auto enumDecl = std::get<0>(getStorage());
enumDecl->LazySemanticInfo.RawType.setPointerAndInt(value, true);
}
//----------------------------------------------------------------------------//
// Overridden decls computation.
//----------------------------------------------------------------------------//
void OverriddenDeclsRequest::diagnoseCycle(DiagnosticEngine &diags) const {
auto decl = std::get<0>(getStorage());
diags.diagnose(decl, diag::circular_reference);
}
void OverriddenDeclsRequest::noteCycleStep(DiagnosticEngine &diags) const {
auto decl = std::get<0>(getStorage());
diags.diagnose(decl, diag::circular_reference_through);
}
//----------------------------------------------------------------------------//
// isObjC computation.
//----------------------------------------------------------------------------//
bool IsObjCRequest::breakCycle() const {
auto decl = std::get<0>(getStorage());
return decl->getAttrs().hasAttribute<ObjCAttr>();
}
void IsObjCRequest::diagnoseCycle(DiagnosticEngine &diags) const {
// FIXME: Improve this diagnostic.
auto decl = std::get<0>(getStorage());
diags.diagnose(decl, diag::circular_reference);
}
void IsObjCRequest::noteCycleStep(DiagnosticEngine &diags) const {
auto decl = std::get<0>(getStorage());
// FIXME: Customize this further.
diags.diagnose(decl, diag::circular_reference_through);
}
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);
}
//----------------------------------------------------------------------------//
// isDynamic computation.
//----------------------------------------------------------------------------//
bool IsDynamicRequest::breakCycle() const {
auto decl = std::get<0>(getStorage());
return decl->getAttrs().hasAttribute<DynamicAttr>();
}
void IsDynamicRequest::diagnoseCycle(DiagnosticEngine &diags) const {
// FIXME: Improve this diagnostic.
auto decl = std::get<0>(getStorage());
diags.diagnose(decl, diag::circular_reference);
}
void IsDynamicRequest::noteCycleStep(DiagnosticEngine &diags) const {
auto decl = std::get<0>(getStorage());
// FIXME: Customize this further.
diags.diagnose(decl, diag::circular_reference_through);
}
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);
}