diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index ad98f125598..ea24ff365cb 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -2758,6 +2758,10 @@ private: /// output a null pointer. unsigned noDynamicallyReplacedDecl : 1; + /// Whether the OpaqueResultTypeRequest request was evaluated and produced + /// a null pointer. + unsigned noOpaqueResultType : 1; + /// Whether the "isFinal" bit has been computed yet. unsigned isFinalComputed : 1; @@ -2785,7 +2789,7 @@ private: friend class InterfaceTypeRequest; friend class CheckRedeclarationRequest; friend class ActorIsolationRequest; - friend class DynamicallyReplacedDeclRequest; + friend class OpaqueResultTypeRequest; friend class ApplyAccessNoteRequest; friend class Decl; diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 8cee7ab8f21..6729f702e4c 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -2295,21 +2295,22 @@ public: /// Builds an opaque result type for a declaration. class OpaqueResultTypeRequest - : public SimpleRequest { + : public SimpleRequest< + OpaqueResultTypeRequest, OpaqueTypeDecl *(ValueDecl *), + RequestFlags::SeparatelyCached | RequestFlags::SplitCached> { public: using SimpleRequest::SimpleRequest; private: friend SimpleRequest; - OpaqueTypeDecl * - evaluate(Evaluator &evaluator, ValueDecl *VD) const; + OpaqueTypeDecl *evaluate(Evaluator &evaluator, ValueDecl *VD) const; public: - // Caching. + // Split caching. bool isCached() const { return true; } + std::optional getCachedResult() const; + void cacheResult(OpaqueTypeDecl *result) const; }; /// Determines if a function declaration is 'static'. diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 0ca2b7ba1eb..cf890724b67 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -262,7 +262,7 @@ SWIFT_REQUEST(TypeChecker, OpaqueReadOwnershipRequest, NoLocationInfo) SWIFT_REQUEST(TypeChecker, OpaqueResultTypeRequest, OpaqueTypeDecl *(ValueDecl *), - Cached, NoLocationInfo) + SeparatelyCached | SplitCached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, OperatorPrecedenceGroupRequest, PrecedenceGroupDecl *(PrecedenceGroupDecl *), Cached, NoLocationInfo) diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 0e469191776..969571df4b5 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3887,21 +3887,6 @@ TypeRepr *ValueDecl::getOpaqueResultTypeRepr() const { } OpaqueTypeDecl *ValueDecl::getOpaqueResultTypeDecl() const { - if (getOpaqueResultTypeRepr() == nullptr) { - if (!isa(this) && - !isa(this) && - !isa(this)) - return nullptr; - auto file = cast(getDeclContext()->getModuleScopeContext()); - // Don't look up when the decl is from source, otherwise a cycle will happen. - if (file->getKind() == FileUnitKind::SerializedAST) { - Mangle::ASTMangler mangler; - auto name = mangler.mangleOpaqueTypeDecl(this); - return file->lookupOpaqueResultType(name); - } - return nullptr; - } - return evaluateOrDefault(getASTContext().evaluator, OpaqueResultTypeRequest{const_cast(this)}, nullptr); diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index d4e60d3cbb9..b36c2d1ab3c 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -385,6 +385,28 @@ void DynamicallyReplacedDeclRequest::cacheResult(ValueDecl *result) const { decl->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(result)); } +//----------------------------------------------------------------------------// +// OpaqueResultTypeRequest caching. +//----------------------------------------------------------------------------// + +std::optional +OpaqueResultTypeRequest::getCachedResult() const { + auto *decl = std::get<0>(getStorage()); + if (decl->LazySemanticInfo.noOpaqueResultType) + return std::optional(nullptr); + + return decl->getASTContext().evaluator.getCachedNonEmptyOutput(*this); +} + +void OpaqueResultTypeRequest::cacheResult(OpaqueTypeDecl *result) const { + auto *decl = std::get<0>(getStorage()); + if (!result) { + decl->LazySemanticInfo.noOpaqueResultType = 1; + return; + } + decl->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(result)); +} + //----------------------------------------------------------------------------// // ApplyAccessNoteRequest computation. //----------------------------------------------------------------------------// diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index cc3f33c2032..ba8e4378de3 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -42,7 +42,9 @@ OpaqueTypeDecl * OpaqueResultTypeRequest::evaluate(Evaluator &evaluator, ValueDecl *originatingDecl) const { auto *repr = originatingDecl->getOpaqueResultTypeRepr(); - assert(repr && "Declaration does not have an opaque result type"); + if (!repr) + return nullptr; + auto *dc = originatingDecl->getInnermostDeclContext(); auto &ctx = dc->getASTContext(); diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index a45e5ab0199..207a40c9925 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -3936,14 +3936,17 @@ public: if (var->hasStorage()) AddAttribute(new (ctx) HasStorageAttr(/*isImplicit:*/true)); - if (opaqueReturnTypeID) { - auto opaqueReturnType = MF.getDeclChecked(opaqueReturnTypeID); - if (!opaqueReturnType) - return opaqueReturnType.takeError(); + { + OpaqueTypeDecl *opaqueDecl = nullptr; + if (opaqueReturnTypeID) { + auto opaqueReturnType = MF.getDeclChecked(opaqueReturnTypeID); + if (!opaqueReturnType) + return opaqueReturnType.takeError(); - ctx.evaluator.cacheOutput( - OpaqueResultTypeRequest{var}, - cast(opaqueReturnType.get())); + opaqueDecl = cast(opaqueReturnType.get()); + } + ctx.evaluator.cacheOutput(OpaqueResultTypeRequest{var}, + std::move(opaqueDecl)); } // If this is a lazy property, record its backing storage. @@ -4357,14 +4360,17 @@ public: fn->setIsObjC(isObjC); fn->setForcedStaticDispatch(hasForcedStaticDispatch); - if (opaqueReturnTypeID) { - auto declOrError = MF.getDeclChecked(opaqueReturnTypeID); - if (!declOrError) - return declOrError.takeError(); + { + OpaqueTypeDecl *opaqueDecl = nullptr; + if (opaqueReturnTypeID) { + auto declOrError = MF.getDeclChecked(opaqueReturnTypeID); + if (!declOrError) + return declOrError.takeError(); - ctx.evaluator.cacheOutput( - OpaqueResultTypeRequest{fn}, - cast(declOrError.get())); + opaqueDecl = cast(declOrError.get()); + } + ctx.evaluator.cacheOutput(OpaqueResultTypeRequest{fn}, + std::move(opaqueDecl)); } if (!isAccessor) @@ -5204,16 +5210,19 @@ public: subscript->setOverriddenDecl(cast_or_null(overridden.get())); if (subscript->getOverriddenDecl()) AddAttribute(new (ctx) OverrideAttr(SourceLoc())); - - if (opaqueReturnTypeID) { - Decl *opaqueReturnType; - UNWRAP(MF.getDeclChecked(opaqueReturnTypeID), opaqueReturnType); - ctx.evaluator.cacheOutput( - OpaqueResultTypeRequest{subscript}, - cast(opaqueReturnType)); + { + OpaqueTypeDecl *opaqueDecl = nullptr; + if (opaqueReturnTypeID) { + Decl *opaqueReturnType; + UNWRAP(MF.getDeclChecked(opaqueReturnTypeID), opaqueReturnType); + + opaqueDecl = cast(opaqueReturnType); + } + ctx.evaluator.cacheOutput(OpaqueResultTypeRequest{subscript}, + std::move(opaqueDecl)); } - + return subscript; }