Skip to content

Commit 3ce1d11

Browse files
authored
Merge pull request #84783 from meg-gupta/fixserializationbug
Fix serialization of mutate accessors
2 parents 47049ce + 479b5a0 commit 3ce1d11

File tree

3 files changed

+90
-3
lines changed

3 files changed

+90
-3
lines changed

lib/Serialization/ModuleFormat.h

Lines changed: 12 additions & 3 deletions
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 = 964; // serialize param decl isAddressable
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 965; // WriteImplKindField and ReadWriteImplKindField size
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
@@ -209,7 +209,10 @@ enum class ReadImplKind : uint8_t {
209209
Read,
210210
Read2,
211211
Borrow,
212+
LastReadImplKind = Borrow,
212213
};
214+
static_assert(countBitsUsed(static_cast<unsigned>(
215+
ReadImplKind::LastReadImplKind)) <= 3);
213216
using ReadImplKindField = BCFixed<3>;
214217

215218
// These IDs must \em not be renumbered or reordered without incrementing
@@ -224,8 +227,11 @@ enum class WriteImplKind : uint8_t {
224227
Modify,
225228
Modify2,
226229
Mutate,
230+
LastWriteImplKind = Mutate,
227231
};
228-
using WriteImplKindField = BCFixed<3>;
232+
static_assert(countBitsUsed(static_cast<unsigned>(
233+
WriteImplKind::LastWriteImplKind)) <= 4);
234+
using WriteImplKindField = BCFixed<4>;
229235

230236
// These IDs must \em not be renumbered or reordered without incrementing
231237
// the module version.
@@ -239,8 +245,11 @@ enum class ReadWriteImplKind : uint8_t {
239245
StoredWithDidSet,
240246
InheritedWithDidSet,
241247
Mutate,
248+
LastReadWriteImplKind = Mutate,
242249
};
243-
using ReadWriteImplKindField = BCFixed<3>;
250+
static_assert(countBitsUsed(static_cast<unsigned>(
251+
ReadWriteImplKind::LastReadWriteImplKind)) <= 4);
252+
using ReadWriteImplKindField = BCFixed<4>;
244253

245254
// These IDs must \em not be renumbered or reordered without incrementing
246255
// the module version.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
public struct Container<Element: ~Copyable >: ~Copyable {
2+
var _storage: UnsafeMutableBufferPointer<Element>
3+
public let _count: Int
4+
5+
public init(_ storage: UnsafeMutableBufferPointer<Element>, _ count: Int) {
6+
self._storage = storage
7+
self._count = count
8+
}
9+
10+
public var count: Int {
11+
return _count
12+
}
13+
14+
public var first: Element {
15+
@_unsafeSelfDependentResult
16+
borrow {
17+
return _storage.baseAddress.unsafelyUnwrapped.pointee
18+
}
19+
@_unsafeSelfDependentResult
20+
mutate {
21+
return &_storage.baseAddress.unsafelyUnwrapped.pointee
22+
}
23+
}
24+
25+
public subscript(index: Int) -> Element {
26+
@_unsafeSelfDependentResult
27+
borrow {
28+
precondition(index >= 0 && index < _count, "Index out of bounds")
29+
return _storage.baseAddress.unsafelyUnwrapped.advanced(by: index).pointee
30+
}
31+
@_unsafeSelfDependentResult
32+
mutate {
33+
precondition(index >= 0 && index < _count, "Index out of bounds")
34+
return &_storage.baseAddress.unsafelyUnwrapped.advanced(by: index).pointee
35+
}
36+
}
37+
}
38+
39+
extension Container: Copyable where Element: Copyable {}
40+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -module-name borrow_accessor_container -enable-experimental-feature BorrowAndMutateAccessors -o %t %S/Inputs/borrow_accessor_container.swift
3+
// RUN: %target-swift-frontend -I %t -emit-sil %s -verify | %FileCheck %s
4+
5+
// REQUIRES: swift_feature_BorrowAndMutateAccessors
6+
7+
import borrow_accessor_container
8+
9+
func test() {
10+
let n = 10_000
11+
var arr = Array(0...n)
12+
let count = arr.count
13+
let sum = arr.withUnsafeMutableBufferPointer { ubpointer in
14+
let container = Container(ubpointer, count)
15+
var sum = 0
16+
for i in 0..<container._count {
17+
sum &+= container[i]
18+
}
19+
return sum
20+
}
21+
let expectedSum = n * (n + 1) / 2
22+
assert(sum == expectedSum)
23+
let mutated_sum = arr.withUnsafeMutableBufferPointer { ubpointer in
24+
var container = Container(ubpointer, count)
25+
var sum = 0
26+
for i in 0..<container._count {
27+
container[i] &+= 1
28+
sum += container[i]
29+
}
30+
return sum
31+
}
32+
let mutatedExpectedSum = (n + 1) * (n + 2) / 2
33+
assert(mutated_sum == mutatedExpectedSum)
34+
}
35+
36+
// CHECK: sil @$s25borrow_accessor_container9ContainerVAARi_zrlEyxSicib : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (Int, @guaranteed Container<τ_0_0>) -> @guaranteed_addr τ_0_0
37+
// CHECK: sil @$s25borrow_accessor_container9ContainerVAARi_zrlEyxSiciz : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (Int, @inout Container<τ_0_0>) -> @guaranteed_addr τ_0_0
38+

0 commit comments

Comments
 (0)