| //===--- 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/TypeRepr.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 "; |
| if (auto typeRepr = ext->getExtendedTypeLoc().getTypeRepr()) |
| typeRepr->print(out); |
| else |
| ext->getSelfNominalTypeDecl()->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. |
| //----------------------------------------------------------------------------// |
| |
| 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. |
| //----------------------------------------------------------------------------// |
| |
| 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); |
| } |