Skip to content

Commit 36f3574

Browse files
committed
Fix deserialization of lifetime dependencies on ast function types
While deserializing AST function types FunctionType and GenericFunctionType which include lifetime dependencies and an implicit self parameter, we don't correctly populate ASTExtInfoBuilder.lifetimeDependencies. We end up reading one dependency less due to incorrect index calculation. Unlike SILFunctionType, AST function types FunctionType and GenericFunctionType do not include implicit self in their param list. They represent methods with implicit self as like: `(Self) -> (Args...) -> Result` and don't have any information to indicate they may have implicit self. Since we use number of parameters while deserializing lifetime dependencies, we go wrong for such function types. Serialize the length of parameter indices, so that lifetime dependencies can be deserialized to that length. rdar://151768216
1 parent 284c371 commit 36f3574

File tree

6 files changed

+70
-22
lines changed

6 files changed

+70
-22
lines changed

include/swift/AST/LifetimeDependence.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,25 @@ class LifetimeDependenceInfo {
227227
|| !conditionallyAddressableParamIndices
228228
|| conditionallyAddressableParamIndices->isDisjointWith(
229229
addressableParamIndices)));
230+
231+
if (CONDITIONAL_ASSERT_enabled()) {
232+
// Ensure inherit/scope/addressable param indices are of the same length
233+
// or 0.
234+
unsigned paramIndicesLength = 0;
235+
if (inheritLifetimeParamIndices) {
236+
paramIndicesLength = inheritLifetimeParamIndices->getCapacity();
237+
}
238+
if (scopeLifetimeParamIndices) {
239+
assert(paramIndicesLength == 0 ||
240+
paramIndicesLength == scopeLifetimeParamIndices->getCapacity());
241+
paramIndicesLength = scopeLifetimeParamIndices->getCapacity();
242+
}
243+
if (addressableParamIndices) {
244+
assert(paramIndicesLength == 0 ||
245+
paramIndicesLength == addressableParamIndices->getCapacity());
246+
paramIndicesLength = addressableParamIndices->getCapacity();
247+
}
248+
}
230249
}
231250

232251
operator bool() const { return !empty(); }
@@ -250,6 +269,19 @@ class LifetimeDependenceInfo {
250269
return addressableParamIndicesAndImmortal.getPointer() != nullptr;
251270
}
252271

272+
unsigned getParamIndicesLength() const {
273+
if (hasInheritLifetimeParamIndices()) {
274+
return getInheritIndices()->getCapacity();
275+
}
276+
if (hasScopeLifetimeParamIndices()) {
277+
return getScopeIndices()->getCapacity();
278+
}
279+
if (hasAddressableParamIndices()) {
280+
return getAddressableIndices()->getCapacity();
281+
}
282+
return 0;
283+
}
284+
253285
IndexSubset *getInheritIndices() const { return inheritLifetimeParamIndices; }
254286

255287
IndexSubset *getScopeIndices() const { return scopeLifetimeParamIndices; }

lib/Serialization/Deserialization.cpp

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3891,7 +3891,7 @@ class DeclDeserializer {
38913891
ctor->setParameters(bodyParams);
38923892

38933893
SmallVector<LifetimeDependenceInfo, 1> lifetimeDependencies;
3894-
while (auto info = MF.maybeReadLifetimeDependence(bodyParams->size() + 1)) {
3894+
while (auto info = MF.maybeReadLifetimeDependence()) {
38953895
assert(info.has_value());
38963896
lifetimeDependencies.push_back(*info);
38973897
}
@@ -4493,11 +4493,9 @@ class DeclDeserializer {
44934493
ParameterList *paramList;
44944494
SET_OR_RETURN_ERROR(paramList, MF.readParameterList());
44954495
fn->setParameters(paramList);
4496-
auto numParams =
4497-
fn->hasImplicitSelfDecl() ? paramList->size() + 1 : paramList->size();
44984496

44994497
SmallVector<LifetimeDependenceInfo, 1> lifetimeDependencies;
4500-
while (auto info = MF.maybeReadLifetimeDependence(numParams)) {
4498+
while (auto info = MF.maybeReadLifetimeDependence()) {
45014499
assert(info.has_value());
45024500
lifetimeDependencies.push_back(*info);
45034501
}
@@ -7438,8 +7436,7 @@ detail::function_deserializer::deserialize(ModuleFile &MF,
74387436

74397437
SmallVector<LifetimeDependenceInfo, 1> lifetimeDependencies;
74407438

7441-
while (auto lifetimeDependence =
7442-
MF.maybeReadLifetimeDependence(params.size())) {
7439+
while (auto lifetimeDependence = MF.maybeReadLifetimeDependence()) {
74437440
lifetimeDependencies.push_back(*lifetimeDependence);
74447441
}
74457442
if (!lifetimeDependencies.empty()) {
@@ -8091,7 +8088,7 @@ Expected<Type> DESERIALIZE_TYPE(SIL_FUNCTION_TYPE)(
80918088

80928089
SmallVector<LifetimeDependenceInfo, 1> lifetimeDependencies;
80938090

8094-
while (auto lifetimeDependence = MF.maybeReadLifetimeDependence(numParams)) {
8091+
while (auto lifetimeDependence = MF.maybeReadLifetimeDependence()) {
80958092
lifetimeDependencies.push_back(*lifetimeDependence);
80968093
}
80978094

@@ -9378,7 +9375,7 @@ bool ModuleFile::maybeReadLifetimeDependenceRecord(
93789375
}
93799376

93809377
std::optional<LifetimeDependenceInfo>
9381-
ModuleFile::maybeReadLifetimeDependence(unsigned numParams) {
9378+
ModuleFile::maybeReadLifetimeDependence() {
93829379
using namespace decls_block;
93839380

93849381
SmallVector<uint64_t, 8> scratch;
@@ -9387,28 +9384,29 @@ ModuleFile::maybeReadLifetimeDependence(unsigned numParams) {
93879384
}
93889385

93899386
unsigned targetIndex;
9387+
unsigned paramIndicesLength;
93909388
bool isImmortal;
93919389
bool hasInheritLifetimeParamIndices;
93929390
bool hasScopeLifetimeParamIndices;
93939391
bool hasAddressableParamIndices;
93949392
ArrayRef<uint64_t> lifetimeDependenceData;
93959393
LifetimeDependenceLayout::readRecord(
9396-
scratch, targetIndex, isImmortal, hasInheritLifetimeParamIndices,
9397-
hasScopeLifetimeParamIndices, hasAddressableParamIndices,
9398-
lifetimeDependenceData);
9394+
scratch, targetIndex, paramIndicesLength, isImmortal,
9395+
hasInheritLifetimeParamIndices, hasScopeLifetimeParamIndices,
9396+
hasAddressableParamIndices, lifetimeDependenceData);
93999397

9400-
SmallBitVector inheritLifetimeParamIndices(numParams, false);
9401-
SmallBitVector scopeLifetimeParamIndices(numParams, false);
9402-
SmallBitVector addressableParamIndices(numParams, false);
9398+
SmallBitVector inheritLifetimeParamIndices(paramIndicesLength, false);
9399+
SmallBitVector scopeLifetimeParamIndices(paramIndicesLength, false);
9400+
SmallBitVector addressableParamIndices(paramIndicesLength, false);
94039401

94049402
unsigned startIndex = 0;
94059403
auto pushData = [&](SmallBitVector &bits) {
9406-
for (unsigned i = 0; i < numParams; i++) {
9404+
for (unsigned i = 0; i < paramIndicesLength; i++) {
94079405
if (lifetimeDependenceData[startIndex + i]) {
94089406
bits.set(i);
94099407
}
94109408
}
9411-
startIndex += numParams;
9409+
startIndex += paramIndicesLength;
94129410
};
94139411

94149412
if (hasInheritLifetimeParamIndices) {

lib/Serialization/ModuleFile.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,8 +1100,7 @@ class ModuleFile
11001100
bool maybeReadLifetimeDependenceRecord(SmallVectorImpl<uint64_t> &scratch);
11011101

11021102
// Reads lifetime dependence info from type if present.
1103-
std::optional<LifetimeDependenceInfo>
1104-
maybeReadLifetimeDependence(unsigned numParams);
1103+
std::optional<LifetimeDependenceInfo> maybeReadLifetimeDependence();
11051104

11061105
// Reads lifetime dependence specifier from decl if present
11071106
bool maybeReadLifetimeEntry(SmallVectorImpl<LifetimeEntry> &specifierList,

lib/Serialization/ModuleFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 952; // Add @specialized
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 953; // update LifetimeDependence layout
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
@@ -2323,6 +2323,7 @@ namespace decls_block {
23232323
using LifetimeDependenceLayout =
23242324
BCRecordLayout<LIFETIME_DEPENDENCE,
23252325
BCVBR<4>, // targetIndex
2326+
BCVBR<4>, // paramIndicesLength
23262327
BCFixed<1>, // isImmortal
23272328
BCFixed<1>, // hasInheritLifetimeParamIndices
23282329
BCFixed<1>, // hasScopeLifetimeParamIndices

lib/Serialization/Serialization.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2733,10 +2733,10 @@ void Serializer::writeLifetimeDependencies(
27332733

27342734
auto abbrCode = DeclTypeAbbrCodes[LifetimeDependenceLayout::Code];
27352735
LifetimeDependenceLayout::emitRecord(
2736-
Out, ScratchRecord, abbrCode, info.getTargetIndex(), info.isImmortal(),
2736+
Out, ScratchRecord, abbrCode, info.getTargetIndex(),
2737+
info.getParamIndicesLength(), info.isImmortal(),
27372738
info.hasInheritLifetimeParamIndices(),
2738-
info.hasScopeLifetimeParamIndices(),
2739-
info.hasAddressableParamIndices(),
2739+
info.hasScopeLifetimeParamIndices(), info.hasAddressableParamIndices(),
27402740
paramIndices);
27412741
paramIndices.clear();
27422742
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module %s -o %t -enable-experimental-feature LifetimeDependence
3+
4+
// RUN: %target-swift-frontend -emit-sil %t/rdar151768216.swiftmodule \
5+
// RUN: -enable-experimental-feature LifetimeDependence
6+
7+
// REQUIRES: swift_feature_LifetimeDependence
8+
9+
// Ensure no crash
10+
extension Result {
11+
@inlinable
12+
func castError(i: Int, j: Int, k: Int) -> Result<Success, Failure> {
13+
return self.mapError { error in
14+
return error
15+
}
16+
}
17+
}
18+

0 commit comments

Comments
 (0)