Skip to content

Commit b0a4c94

Browse files
authored
Merge pull request #72076 from meg-gupta/fixserialization
Fix serialization of lifetime dependence
2 parents afeef85 + eb84095 commit b0a4c94

14 files changed

+273
-75
lines changed

include/swift/AST/ExtInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,6 +1335,10 @@ class SILExtInfo {
13351335
return builder.withTransferringResult(hasTransferringResult).build();
13361336
}
13371337

1338+
SILExtInfo withLifetimeDependenceInfo(LifetimeDependenceInfo info) const {
1339+
return builder.withLifetimeDependenceInfo(info);
1340+
}
1341+
13381342
void Profile(llvm::FoldingSetNodeID &ID) const { builder.Profile(ID); }
13391343

13401344
bool isEqualTo(SILExtInfo other, bool useClangTypes) const {

include/swift/AST/LifetimeDependence.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ class LifetimeDependenceSpecifier {
132132
class LifetimeDependenceInfo {
133133
IndexSubset *inheritLifetimeParamIndices;
134134
IndexSubset *scopeLifetimeParamIndices;
135+
bool isExplicit;
135136

136137
static LifetimeDependenceInfo getForParamIndex(AbstractFunctionDecl *afd,
137138
unsigned index,
@@ -146,11 +147,18 @@ class LifetimeDependenceInfo {
146147
public:
147148
LifetimeDependenceInfo()
148149
: inheritLifetimeParamIndices(nullptr),
149-
scopeLifetimeParamIndices(nullptr) {}
150+
scopeLifetimeParamIndices(nullptr), isExplicit(false) {}
150151
LifetimeDependenceInfo(IndexSubset *inheritLifetimeParamIndices,
151-
IndexSubset *scopeLifetimeParamIndices)
152+
IndexSubset *scopeLifetimeParamIndices,
153+
bool isExplicit = false)
152154
: inheritLifetimeParamIndices(inheritLifetimeParamIndices),
153-
scopeLifetimeParamIndices(scopeLifetimeParamIndices) {}
155+
scopeLifetimeParamIndices(scopeLifetimeParamIndices),
156+
isExplicit(isExplicit) {
157+
assert(!empty());
158+
assert(!inheritLifetimeParamIndices ||
159+
!inheritLifetimeParamIndices->isEmpty());
160+
assert(!scopeLifetimeParamIndices || !scopeLifetimeParamIndices->isEmpty());
161+
}
154162

155163
operator bool() const { return !empty(); }
156164

@@ -159,6 +167,8 @@ class LifetimeDependenceInfo {
159167
scopeLifetimeParamIndices == nullptr;
160168
}
161169

170+
bool isExplicitlySpecified() const { return isExplicit; }
171+
162172
bool hasInheritLifetimeParamIndices() const {
163173
return inheritLifetimeParamIndices != nullptr;
164174
}

include/swift/AST/Types.h

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3433,7 +3433,14 @@ class AnyFunctionType : public TypeBase {
34333433
Type getGlobalActor() const;
34343434
Type getThrownError() const;
34353435

3436-
LifetimeDependenceInfo getLifetimeDependenceInfo() const;
3436+
const LifetimeDependenceInfo *getLifetimeDependenceInfoOrNull() const;
3437+
3438+
LifetimeDependenceInfo getLifetimeDependenceInfo() const {
3439+
if (auto *depInfo = getLifetimeDependenceInfoOrNull()) {
3440+
return *depInfo;
3441+
}
3442+
return LifetimeDependenceInfo();
3443+
}
34373444

34383445
FunctionTypeIsolation getIsolation() const {
34393446
if (hasExtInfo())
@@ -3765,14 +3772,22 @@ class FunctionType final
37653772
return getTrailingObjects<Type>()[hasGlobalActor()];
37663773
}
37673774

3768-
LifetimeDependenceInfo getLifetimeDependenceInfo() const {
3775+
inline LifetimeDependenceInfo getLifetimeDependenceInfo() const {
3776+
if (auto *depInfo = getLifetimeDependenceInfoOrNull()) {
3777+
return *depInfo;
3778+
}
3779+
return LifetimeDependenceInfo();
3780+
}
3781+
3782+
/// Returns nullptr for an empty dependence list.
3783+
const LifetimeDependenceInfo *getLifetimeDependenceInfoOrNull() const {
37693784
if (!hasLifetimeDependenceInfo()) {
3770-
return LifetimeDependenceInfo();
3785+
return nullptr;
37713786
}
37723787
auto *info = getTrailingObjects<LifetimeDependenceInfo>();
37733788
assert(!info->empty() && "If the LifetimeDependenceInfo was empty, we "
37743789
"shouldn't have stored it.");
3775-
return *info;
3790+
return info;
37763791
}
37773792

37783793
void Profile(llvm::FoldingSetNodeID &ID) {
@@ -3914,14 +3929,22 @@ class GenericFunctionType final
39143929
return getTrailingObjects<Type>()[hasGlobalActor()];
39153930
}
39163931

3917-
LifetimeDependenceInfo getLifetimeDependenceInfo() const {
3932+
inline LifetimeDependenceInfo getLifetimeDependenceInfo() const {
3933+
if (auto *depInfo = getLifetimeDependenceInfoOrNull()) {
3934+
return *depInfo;
3935+
}
3936+
return LifetimeDependenceInfo();
3937+
}
3938+
3939+
/// Returns nullptr for an empty dependence list.
3940+
const LifetimeDependenceInfo *getLifetimeDependenceInfoOrNull() const {
39183941
if (!hasLifetimeDependenceInfo()) {
3919-
return LifetimeDependenceInfo();
3942+
return nullptr;
39203943
}
39213944
auto *info = getTrailingObjects<LifetimeDependenceInfo>();
39223945
assert(!info->empty() && "If the LifetimeDependenceInfo was empty, we "
39233946
"shouldn't have stored it.");
3924-
return *info;
3947+
return info;
39253948
}
39263949

39273950
/// Retrieve the generic signature of this function type.

lib/AST/Type.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3896,12 +3896,13 @@ Type AnyFunctionType::getGlobalActor() const {
38963896
}
38973897
}
38983898

3899-
LifetimeDependenceInfo AnyFunctionType::getLifetimeDependenceInfo() const {
3899+
const LifetimeDependenceInfo *
3900+
AnyFunctionType::getLifetimeDependenceInfoOrNull() const {
39003901
switch (getKind()) {
39013902
case TypeKind::Function:
3902-
return cast<FunctionType>(this)->getLifetimeDependenceInfo();
3903+
return cast<FunctionType>(this)->getLifetimeDependenceInfoOrNull();
39033904
case TypeKind::GenericFunction:
3904-
return cast<GenericFunctionType>(this)->getLifetimeDependenceInfo();
3905+
return cast<GenericFunctionType>(this)->getLifetimeDependenceInfoOrNull();
39053906

39063907
default:
39073908
llvm_unreachable("Illegal type kind for AnyFunctionType.");

lib/Sema/LifetimeDependence.cpp

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,24 @@ void LifetimeDependenceInfo::getConcatenatedData(
103103
}
104104
}
105105

106+
static bool hasEscapableResultOrYield(AbstractFunctionDecl *afd,
107+
Type resultType) {
108+
Type resultTypeInContext = afd->mapTypeIntoContext(resultType);
109+
std::optional<Type> yieldTyInContext;
110+
111+
if (auto *accessor = dyn_cast<AccessorDecl>(afd)) {
112+
if (accessor->isCoroutine()) {
113+
yieldTyInContext = accessor->getStorage()->getValueInterfaceType();
114+
yieldTyInContext = accessor->mapTypeIntoContext(*yieldTyInContext);
115+
}
116+
}
117+
if (resultTypeInContext->isEscapable() &&
118+
(!yieldTyInContext.has_value() || (*yieldTyInContext)->isEscapable())) {
119+
return true;
120+
}
121+
return false;
122+
}
123+
106124
std::optional<LifetimeDependenceInfo>
107125
LifetimeDependenceInfo::fromTypeRepr(AbstractFunctionDecl *afd, Type resultType,
108126
bool allowIndex) {
@@ -114,6 +132,12 @@ LifetimeDependenceInfo::fromTypeRepr(AbstractFunctionDecl *afd, Type resultType,
114132
auto lifetimeDependentRepr =
115133
cast<LifetimeDependentReturnTypeRepr>(afd->getResultTypeRepr());
116134

135+
if (hasEscapableResultOrYield(afd, resultType)) {
136+
diags.diagnose(lifetimeDependentRepr->getLoc(),
137+
diag::lifetime_dependence_invalid_return_type);
138+
return std::nullopt;
139+
}
140+
117141
SmallBitVector inheritLifetimeParamIndices(capacity);
118142
SmallBitVector scopeLifetimeParamIndices(capacity);
119143

@@ -122,11 +146,6 @@ LifetimeDependenceInfo::fromTypeRepr(AbstractFunctionDecl *afd, Type resultType,
122146
ValueOwnership ownership) {
123147
auto loc = specifier.getLoc();
124148
auto kind = specifier.getLifetimeDependenceKind();
125-
Type resultTypeInContext = afd->mapTypeIntoContext(resultType);
126-
if (resultTypeInContext->isEscapable()) {
127-
diags.diagnose(loc, diag::lifetime_dependence_invalid_return_type);
128-
return true;
129-
}
130149

131150
if (ownership == ValueOwnership::Default) {
132151
diags.diagnose(loc, diag::lifetime_dependence_missing_ownership_modifier);
@@ -253,7 +272,8 @@ LifetimeDependenceInfo::fromTypeRepr(AbstractFunctionDecl *afd, Type resultType,
253272
: nullptr,
254273
scopeLifetimeParamIndices.any()
255274
? IndexSubset::get(ctx, scopeLifetimeParamIndices)
256-
: nullptr);
275+
: nullptr,
276+
/*isExplicit*/ true);
257277
}
258278

259279
std::optional<LifetimeDependenceInfo>
@@ -274,19 +294,11 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd, Type resultType) {
274294
auto &diags = ctx.Diags;
275295
auto returnTypeRepr = afd->getResultTypeRepr();
276296
auto returnLoc = returnTypeRepr ? returnTypeRepr->getLoc() : afd->getLoc();
277-
Type returnTyInContext = afd->mapTypeIntoContext(resultType);
278-
std::optional<Type> yieldTyInContext;
279297

280-
if (auto *accessor = dyn_cast<AccessorDecl>(afd)) {
281-
if (accessor->isCoroutine()) {
282-
yieldTyInContext = accessor->getStorage()->getValueInterfaceType();
283-
yieldTyInContext = accessor->mapTypeIntoContext(*yieldTyInContext);
284-
}
285-
}
286-
if (returnTyInContext->isEscapable() &&
287-
(!yieldTyInContext.has_value() || (*yieldTyInContext)->isEscapable())) {
298+
if (hasEscapableResultOrYield(afd, resultType)) {
288299
return std::nullopt;
289300
}
301+
290302
if (afd->getAttrs().hasAttribute<UnsafeNonEscapableResultAttr>()) {
291303
return std::nullopt;
292304
}

lib/Serialization/Deserialization.cpp

Lines changed: 86 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3590,7 +3590,8 @@ class DeclDeserializer {
35903590
ctor->setParameters(bodyParams);
35913591

35923592
SmallVector<LifetimeDependenceSpecifier> specifierList;
3593-
if (MF.maybeReadLifetimeDependence(specifierList, bodyParams->size())) {
3593+
if (MF.maybeReadLifetimeDependenceSpecifier(specifierList,
3594+
bodyParams->size())) {
35943595
auto SelfType = ctor->getDeclaredInterfaceType();
35953596
auto typeRepr = new (ctx) FixedTypeRepr(SelfType, SourceLoc());
35963597
auto lifetimeTypeRepr =
@@ -4159,7 +4160,8 @@ class DeclDeserializer {
41594160
ParameterList *paramList = MF.readParameterList();
41604161
fn->setParameters(paramList);
41614162
SmallVector<LifetimeDependenceSpecifier> specifierList;
4162-
if (MF.maybeReadLifetimeDependence(specifierList, paramList->size())) {
4163+
if (MF.maybeReadLifetimeDependenceSpecifier(specifierList,
4164+
paramList->size())) {
41634165
auto typeRepr = new (ctx) FixedTypeRepr(resultType, SourceLoc());
41644166
auto lifetimeTypeRepr =
41654167
LifetimeDependentReturnTypeRepr::create(ctx, typeRepr, specifierList);
@@ -6851,7 +6853,6 @@ detail::function_deserializer::deserialize(ModuleFile &MF,
68516853
isolation = swift::FunctionTypeIsolation::forGlobalActor(globalActorTy.get());
68526854
}
68536855

6854-
// TODO: Handle LifetimeDependenceInfo here.
68556856
auto info = FunctionType::ExtInfoBuilder(
68566857
*representation, noescape, throws, thrownError, *diffKind,
68576858
clangFunctionType, isolation, LifetimeDependenceInfo(),
@@ -6866,6 +6867,7 @@ detail::function_deserializer::deserialize(ModuleFile &MF,
68666867

68676868
SmallVector<AnyFunctionType::Param, 8> params;
68686869
while (true) {
6870+
BCOffsetRAII restoreOffset(MF.DeclTypeCursor);
68696871
llvm::BitstreamEntry entry =
68706872
MF.fatalIfUnexpected(MF.DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
68716873
if (entry.Kind != llvm::BitstreamEntry::Record)
@@ -6877,6 +6879,8 @@ detail::function_deserializer::deserialize(ModuleFile &MF,
68776879
if (recordID != decls_block::FUNCTION_PARAM)
68786880
break;
68796881

6882+
restoreOffset.reset();
6883+
68806884
IdentifierID labelID;
68816885
IdentifierID internalLabelID;
68826886
TypeID typeID;
@@ -6907,6 +6911,13 @@ detail::function_deserializer::deserialize(ModuleFile &MF,
69076911
MF.getIdentifier(internalLabelID));
69086912
}
69096913

6914+
auto lifetimeDependenceInfo =
6915+
MF.maybeReadLifetimeDependenceInfo(params.size());
6916+
6917+
if (lifetimeDependenceInfo.has_value()) {
6918+
info = info.withLifetimeDependenceInfo(*lifetimeDependenceInfo);
6919+
}
6920+
69106921
if (!isGeneric) {
69116922
assert(genericSig.isNull());
69126923
return FunctionType::get(params, resultTy.get(), info);
@@ -7384,7 +7395,6 @@ Expected<Type> DESERIALIZE_TYPE(SIL_FUNCTION_TYPE)(
73847395
if (erasedIsolation)
73857396
isolation = SILFunctionTypeIsolation::Erased;
73867397

7387-
// Handle LifetimeDependenceInfo here.
73887398
auto extInfo =
73897399
SILFunctionType::ExtInfoBuilder(
73907400
*representation, pseudogeneric, noescape, concurrent, async,
@@ -7527,6 +7537,13 @@ Expected<Type> DESERIALIZE_TYPE(SIL_FUNCTION_TYPE)(
75277537
if (!patternSubsOrErr)
75287538
return patternSubsOrErr.takeError();
75297539

7540+
auto lifetimeDependenceInfo = MF.maybeReadLifetimeDependenceInfo(
7541+
extInfo.hasSelfParam() ? numParams : numParams + 1);
7542+
7543+
if (lifetimeDependenceInfo.has_value()) {
7544+
extInfo = extInfo.withLifetimeDependenceInfo(*lifetimeDependenceInfo);
7545+
}
7546+
75307547
return SILFunctionType::get(invocationSig, extInfo, coroutineKind.value(),
75317548
calleeConvention.value(), allParams, allYields,
75327549
allResults, errorResult,
@@ -8687,11 +8704,9 @@ ModuleFile::maybeReadForeignAsyncConvention() {
86878704
errorFlagPolarity);
86888705
}
86898706

8690-
bool ModuleFile::maybeReadLifetimeDependence(
8691-
SmallVectorImpl<LifetimeDependenceSpecifier> &specifierList,
8692-
unsigned numParams) {
8707+
bool ModuleFile::maybeReadLifetimeDependenceRecord(
8708+
SmallVectorImpl<uint64_t> &scratch) {
86938709
using namespace decls_block;
8694-
SmallVector<uint64_t, 8> scratch;
86958710

86968711
BCOffsetRAII restoreOffset(DeclTypeCursor);
86978712

@@ -8711,22 +8726,82 @@ bool ModuleFile::maybeReadLifetimeDependence(
87118726
return false;
87128727
}
87138728

8714-
bool hasInheritLifetimeParamIndices, hasScopeLifetimeParamIndices;
8729+
return true;
8730+
}
8731+
8732+
std::optional<LifetimeDependenceInfo>
8733+
ModuleFile::maybeReadLifetimeDependenceInfo(unsigned numParams) {
8734+
using namespace decls_block;
8735+
8736+
SmallVector<uint64_t, 8> scratch;
8737+
if (!maybeReadLifetimeDependenceRecord(scratch)) {
8738+
return std::nullopt;
8739+
}
8740+
8741+
bool hasInheritLifetimeParamIndices;
8742+
bool hasScopeLifetimeParamIndices;
8743+
ArrayRef<uint64_t> lifetimeDependenceData;
8744+
LifetimeDependenceLayout::readRecord(scratch, hasInheritLifetimeParamIndices,
8745+
hasScopeLifetimeParamIndices,
8746+
lifetimeDependenceData);
8747+
8748+
SmallBitVector inheritLifetimeParamIndices(numParams, false);
8749+
SmallBitVector scopeLifetimeParamIndices(numParams, false);
8750+
8751+
unsigned startIndex = 0;
8752+
auto pushData = [&](SmallBitVector &bits) {
8753+
for (unsigned i = 0; i < numParams; i++) {
8754+
if (lifetimeDependenceData[startIndex + i]) {
8755+
bits.set(i);
8756+
}
8757+
}
8758+
startIndex += numParams;
8759+
};
8760+
8761+
if (hasInheritLifetimeParamIndices) {
8762+
pushData(inheritLifetimeParamIndices);
8763+
}
8764+
if (hasScopeLifetimeParamIndices) {
8765+
pushData(scopeLifetimeParamIndices);
8766+
}
8767+
8768+
ASTContext &ctx = getContext();
8769+
return LifetimeDependenceInfo(
8770+
hasInheritLifetimeParamIndices
8771+
? IndexSubset::get(ctx, inheritLifetimeParamIndices)
8772+
: nullptr,
8773+
hasScopeLifetimeParamIndices
8774+
? IndexSubset::get(ctx, scopeLifetimeParamIndices)
8775+
: nullptr);
8776+
}
8777+
8778+
bool ModuleFile::maybeReadLifetimeDependenceSpecifier(
8779+
SmallVectorImpl<LifetimeDependenceSpecifier> &specifierList,
8780+
unsigned numDeclParams) {
8781+
using namespace decls_block;
8782+
8783+
SmallVector<uint64_t, 8> scratch;
8784+
if (!maybeReadLifetimeDependenceRecord(scratch)) {
8785+
return false;
8786+
}
8787+
8788+
bool hasInheritLifetimeParamIndices;
8789+
bool hasScopeLifetimeParamIndices;
87158790
ArrayRef<uint64_t> lifetimeDependenceData;
87168791
LifetimeDependenceLayout::readRecord(scratch, hasInheritLifetimeParamIndices,
87178792
hasScopeLifetimeParamIndices,
87188793
lifetimeDependenceData);
87198794

87208795
unsigned startIndex = 0;
87218796
auto pushData = [&](LifetimeDependenceKind kind) {
8722-
for (unsigned i = 0; i < numParams + 1; i++) {
8797+
for (unsigned i = 0; i < numDeclParams + 1; i++) {
87238798
if (lifetimeDependenceData[startIndex + i]) {
87248799
specifierList.push_back(
87258800
LifetimeDependenceSpecifier::getOrderedLifetimeDependenceSpecifier(
87268801
SourceLoc(), kind, i));
87278802
}
87288803
}
8729-
startIndex += numParams + 1;
8804+
startIndex += numDeclParams + 1;
87308805
};
87318806

87328807
if (hasInheritLifetimeParamIndices) {

0 commit comments

Comments
 (0)