Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,11 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl>, public Swi
HasAnyUnavailableDuringLoweringValues : 1
);

SWIFT_INLINE_BITFIELD(OpaqueTypeDecl, GenericTypeDecl, 1,
/// Whether we have lazily-loaded underlying substitutions.
HasLazyUnderlyingSubstitutions : 1
);

SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+8,
/// If the module is compiled as static library.
StaticLibrary : 1,
Expand Down Expand Up @@ -3646,7 +3651,8 @@ class OpaqueTypeDecl final :
OpaqueTypeDecl(ValueDecl *NamingDecl, GenericParamList *GenericParams,
DeclContext *DC,
GenericSignature OpaqueInterfaceGenericSignature,
ArrayRef<TypeRepr *> OpaqueReturnTypeReprs);
ArrayRef<TypeRepr *> OpaqueReturnTypeReprs,
bool hasLazyUnderlyingSubstitutions);

unsigned getNumOpaqueReturnTypeReprs() const {
return NamingDeclAndHasOpaqueReturnTypeRepr.getInt()
Expand All @@ -3658,13 +3664,21 @@ class OpaqueTypeDecl final :
return getNumOpaqueReturnTypeReprs();
}

void loadLazyUnderlyingSubstitutions();

public:
static OpaqueTypeDecl *get(
static OpaqueTypeDecl *create(
ValueDecl *NamingDecl, GenericParamList *GenericParams,
DeclContext *DC,
GenericSignature OpaqueInterfaceGenericSignature,
ArrayRef<TypeRepr *> OpaqueReturnTypeReprs);

static OpaqueTypeDecl *createDeserialized(
GenericParamList *GenericParams,
DeclContext *DC,
GenericSignature OpaqueInterfaceGenericSignature,
LazyMemberLoader *lazyLoader, uint64_t underlyingSubsData);

ValueDecl *getNamingDecl() const {
return NamingDeclAndHasOpaqueReturnTypeRepr.getPointer();
}
Expand Down Expand Up @@ -3720,19 +3734,19 @@ class OpaqueTypeDecl final :
bool typeCheckFunctionBodies=true) const;

void setUniqueUnderlyingTypeSubstitutions(SubstitutionMap subs) {
assert(!UniqueUnderlyingType.has_value() && "resetting underlying type?!");
ASSERT(!Bits.OpaqueTypeDecl.HasLazyUnderlyingSubstitutions);
ASSERT(!UniqueUnderlyingType.has_value() && "resetting underlying type?!");
UniqueUnderlyingType = subs;
}

bool hasConditionallyAvailableSubstitutions() const {
const_cast<OpaqueTypeDecl *>(this)->loadLazyUnderlyingSubstitutions();

return ConditionallyAvailableTypes.has_value();
}

ArrayRef<ConditionallyAvailableSubstitutions *>
getConditionallyAvailableSubstitutions() const {
assert(ConditionallyAvailableTypes);
return ConditionallyAvailableTypes.value();
}
getConditionallyAvailableSubstitutions() const;

void setConditionallyAvailableSubstitutions(
ArrayRef<ConditionallyAvailableSubstitutions *> substitutions);
Expand Down
10 changes: 10 additions & 0 deletions include/swift/AST/LazyResolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ class LazyAssociatedTypeData : public LazyContextData {
uint64_t defaultDefinitionTypeData = 0;
};

class LazyOpaqueTypeData : public LazyContextData {
public:
/// The context data used for loading the underlying type substitution map.
uint64_t underlyingSubsData = 0;
};

/// Context data for protocols.
class LazyProtocolData : public LazyIterableDeclContextData {
public:
Expand Down Expand Up @@ -138,6 +144,10 @@ class alignas(void*) LazyMemberLoader {
// Returns the target parameter of the `@_specialize` attribute or null.
virtual ValueDecl *loadTargetFunctionDecl(const AbstractSpecializeAttr *attr,
uint64_t contextData) = 0;

/// Loads the underlying type substitution map of an opaque result declaration.
virtual void
finishOpaqueTypeDecl(OpaqueTypeDecl *opaqueDecl, uint64_t contextData) = 0;
};

/// A class that can lazily load conformances from a serialized format.
Expand Down
8 changes: 5 additions & 3 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3174,20 +3174,22 @@ ASTContext::getOrCreateLazyContextData(const Decl *decl,
LazyMemberLoader *lazyLoader) {
if (auto *data = getLazyContextData(decl)) {
// Make sure we didn't provide an incompatible lazy loader.
assert(!lazyLoader || lazyLoader == data->loader);
ASSERT(!lazyLoader || lazyLoader == data->loader);
return data;
}

LazyContextData *&entry = getImpl().LazyContexts[decl];

// Create new lazy context data with the given loader.
assert(lazyLoader && "Queried lazy data for non-lazy iterable context");
ASSERT(lazyLoader && "Queried lazy data for non-lazy iterable context");
if (isa<ProtocolDecl>(decl)) {
entry = Allocate<LazyProtocolData>();
} else if (isa<NominalTypeDecl>(decl) || isa<ExtensionDecl>(decl)) {
entry = Allocate<LazyIterableDeclContextData>();
} else if (isa<OpaqueTypeDecl>(decl)) {
entry = Allocate<LazyOpaqueTypeData>();
} else {
assert(isa<AssociatedTypeDecl>(decl));
ASSERT(isa<AssociatedTypeDecl>(decl));
entry = Allocate<LazyAssociatedTypeData>();
}

Expand Down
65 changes: 60 additions & 5 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10820,13 +10820,16 @@ bool AbstractFunctionDecl::isResilient(ModuleDecl *M,
OpaqueTypeDecl::OpaqueTypeDecl(ValueDecl *NamingDecl,
GenericParamList *GenericParams, DeclContext *DC,
GenericSignature OpaqueInterfaceGenericSignature,
ArrayRef<TypeRepr *>
OpaqueReturnTypeReprs)
ArrayRef<TypeRepr *> OpaqueReturnTypeReprs,
bool hasLazyUnderlyingSubstitutions)
: GenericTypeDecl(DeclKind::OpaqueType, DC, Identifier(), SourceLoc(), {},
GenericParams),
NamingDeclAndHasOpaqueReturnTypeRepr(
NamingDecl, !OpaqueReturnTypeReprs.empty()),
OpaqueInterfaceGenericSignature(OpaqueInterfaceGenericSignature) {
Bits.OpaqueTypeDecl.HasLazyUnderlyingSubstitutions
= hasLazyUnderlyingSubstitutions;

// Always implicit.
setImplicit();

Expand All @@ -10839,7 +10842,7 @@ OpaqueTypeDecl::OpaqueTypeDecl(ValueDecl *NamingDecl,
OpaqueReturnTypeReprs.end(), getTrailingObjects());
}

OpaqueTypeDecl *OpaqueTypeDecl::get(
OpaqueTypeDecl *OpaqueTypeDecl::create(
ValueDecl *NamingDecl, GenericParamList *GenericParams,
DeclContext *DC,
GenericSignature OpaqueInterfaceGenericSignature,
Expand All @@ -10850,7 +10853,33 @@ OpaqueTypeDecl *OpaqueTypeDecl::get(
auto mem = ctx.Allocate(size, alignof(OpaqueTypeDecl));
return new (mem) OpaqueTypeDecl(
NamingDecl, GenericParams, DC, OpaqueInterfaceGenericSignature,
OpaqueReturnTypeReprs);
OpaqueReturnTypeReprs, /*hasLazyUnderlyingSubstitutions=*/false);
}

OpaqueTypeDecl *OpaqueTypeDecl::createDeserialized(
GenericParamList *GenericParams, DeclContext *DC,
GenericSignature OpaqueInterfaceGenericSignature,
LazyMemberLoader *lazyLoader, uint64_t underlyingSubsData) {
bool hasLazyUnderlyingSubstitutions = (underlyingSubsData != 0);

ASTContext &ctx = DC->getASTContext();
auto size = totalSizeToAlloc<TypeRepr *>(0);
auto mem = ctx.Allocate(size, alignof(OpaqueTypeDecl));

// NamingDecl is set later by deserialization
auto *decl = new (mem) OpaqueTypeDecl(
/*namingDecl=*/nullptr, GenericParams, DC,
OpaqueInterfaceGenericSignature, { },
hasLazyUnderlyingSubstitutions);

if (hasLazyUnderlyingSubstitutions) {
auto &ctx = DC->getASTContext();
auto *data = static_cast<LazyOpaqueTypeData *>(
ctx.getOrCreateLazyContextData(decl, lazyLoader));
data->underlyingSubsData = underlyingSubsData;
}

return decl;
}

bool OpaqueTypeDecl::isOpaqueReturnTypeOf(const Decl *ownerDecl) const {
Expand Down Expand Up @@ -10906,16 +10935,41 @@ bool OpaqueTypeDecl::exportUnderlyingType() const {
llvm_unreachable("The naming decl is expected to be either an AFD or ASD");
}

void OpaqueTypeDecl::loadLazyUnderlyingSubstitutions() {
if (!Bits.OpaqueTypeDecl.HasLazyUnderlyingSubstitutions)
return;

Bits.OpaqueTypeDecl.HasLazyUnderlyingSubstitutions = 0;

auto &ctx = getASTContext();
auto *data = static_cast<LazyOpaqueTypeData *>(
ctx.getLazyContextData(this));
ASSERT(data != nullptr);

data->loader->finishOpaqueTypeDecl(
this, data->underlyingSubsData);
}

std::optional<SubstitutionMap>
OpaqueTypeDecl::getUniqueUnderlyingTypeSubstitutions(
bool typeCheckFunctionBodies) const {
const_cast<OpaqueTypeDecl *>(this)->loadLazyUnderlyingSubstitutions();

if (!typeCheckFunctionBodies)
return UniqueUnderlyingType;

return evaluateOrDefault(getASTContext().evaluator,
UniqueUnderlyingTypeSubstitutionsRequest{this}, {});
}

ArrayRef<OpaqueTypeDecl::ConditionallyAvailableSubstitutions *>
OpaqueTypeDecl::getConditionallyAvailableSubstitutions() const {
const_cast<OpaqueTypeDecl *>(this)->loadLazyUnderlyingSubstitutions();

assert(ConditionallyAvailableTypes);
return ConditionallyAvailableTypes.value();
}

std::optional<unsigned>
OpaqueTypeDecl::getAnonymousOpaqueParamOrdinal(TypeRepr *repr) const {
assert(NamingDeclAndHasOpaqueReturnTypeRepr.getInt() &&
Expand Down Expand Up @@ -10945,7 +10999,8 @@ Identifier OpaqueTypeDecl::getOpaqueReturnTypeIdentifier() const {

void OpaqueTypeDecl::setConditionallyAvailableSubstitutions(
ArrayRef<ConditionallyAvailableSubstitutions *> substitutions) {
assert(!ConditionallyAvailableTypes &&
ASSERT(!Bits.OpaqueTypeDecl.HasLazyUnderlyingSubstitutions);
ASSERT(!ConditionallyAvailableTypes &&
"resetting conditionally available substitutions?!");
ConditionallyAvailableTypes = getASTContext().AllocateCopy(substitutions);
}
Expand Down
5 changes: 5 additions & 0 deletions lib/ClangImporter/ImporterImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1762,6 +1762,11 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
llvm_unreachable("unimplemented for ClangImporter");
}

void finishOpaqueTypeDecl(OpaqueTypeDecl *decl,
uint64_t contextData) override {
llvm_unreachable("unimplemented for ClangImporter");
}

template <typename DeclTy, typename ...Targs>
DeclTy *createDeclWithClangNode(ClangNode ClangN, AccessLevel access,
Targs &&... Args) {
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/TypeCheckGeneric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
}

// Create the OpaqueTypeDecl for the result type.
auto opaqueDecl = OpaqueTypeDecl::get(
auto opaqueDecl = OpaqueTypeDecl::create(
originatingDecl, genericParams, parentDC, interfaceSignature,
opaqueReprs);
if (auto originatingSig = originatingDC->getGenericSignatureOfContext()) {
Expand Down
3 changes: 2 additions & 1 deletion lib/Serialization/DeclTypeRecordNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,11 @@ OTHER(ERROR_FLAG, 155)
OTHER(ABI_ONLY_COUNTERPART, 156)
OTHER(DECL_NAME_REF, 157)

TRAILING_INFO(UNDERLYING_SUBSTITUTION)
TRAILING_INFO(CONDITIONAL_SUBSTITUTION)
TRAILING_INFO(CONDITIONAL_SUBSTITUTION_COND)

OTHER(LIFETIME_DEPENDENCE, 160)
OTHER(LIFETIME_DEPENDENCE, 161)
TRAILING_INFO(INHERITED_PROTOCOLS)

#ifndef DECL_ATTR
Expand Down
Loading