From 479b5a02f5ec0f0db3c9a9868d9843d0654fdb87 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Tue, 7 Oct 2025 20:09:30 -0700 Subject: [PATCH] Fix serialization of mutate accessors --- lib/Serialization/ModuleFormat.h | 15 +++++-- .../Inputs/borrow_accessor_container.swift | 40 +++++++++++++++++++ .../borrow_accessor_client.swift | 38 ++++++++++++++++++ 3 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 test/Serialization/Inputs/borrow_accessor_container.swift create mode 100644 test/Serialization/borrow_accessor_client.swift diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 2c527272e69de..3354e137b6bd8 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 964; // serialize param decl isAddressable +const uint16_t SWIFTMODULE_VERSION_MINOR = 965; // WriteImplKindField and ReadWriteImplKindField size /// A standard hash seed used for all string hashes in a serialized module. /// @@ -209,7 +209,10 @@ enum class ReadImplKind : uint8_t { Read, Read2, Borrow, + LastReadImplKind = Borrow, }; +static_assert(countBitsUsed(static_cast( + ReadImplKind::LastReadImplKind)) <= 3); using ReadImplKindField = BCFixed<3>; // These IDs must \em not be renumbered or reordered without incrementing @@ -224,8 +227,11 @@ enum class WriteImplKind : uint8_t { Modify, Modify2, Mutate, + LastWriteImplKind = Mutate, }; -using WriteImplKindField = BCFixed<3>; +static_assert(countBitsUsed(static_cast( + WriteImplKind::LastWriteImplKind)) <= 4); +using WriteImplKindField = BCFixed<4>; // These IDs must \em not be renumbered or reordered without incrementing // the module version. @@ -239,8 +245,11 @@ enum class ReadWriteImplKind : uint8_t { StoredWithDidSet, InheritedWithDidSet, Mutate, + LastReadWriteImplKind = Mutate, }; -using ReadWriteImplKindField = BCFixed<3>; +static_assert(countBitsUsed(static_cast( + ReadWriteImplKind::LastReadWriteImplKind)) <= 4); +using ReadWriteImplKindField = BCFixed<4>; // These IDs must \em not be renumbered or reordered without incrementing // the module version. diff --git a/test/Serialization/Inputs/borrow_accessor_container.swift b/test/Serialization/Inputs/borrow_accessor_container.swift new file mode 100644 index 0000000000000..e62aa2855ae39 --- /dev/null +++ b/test/Serialization/Inputs/borrow_accessor_container.swift @@ -0,0 +1,40 @@ +public struct Container: ~Copyable { + var _storage: UnsafeMutableBufferPointer + public let _count: Int + + public init(_ storage: UnsafeMutableBufferPointer, _ count: Int) { + self._storage = storage + self._count = count + } + + public var count: Int { + return _count + } + + public var first: Element { + @_unsafeSelfDependentResult + borrow { + return _storage.baseAddress.unsafelyUnwrapped.pointee + } + @_unsafeSelfDependentResult + mutate { + return &_storage.baseAddress.unsafelyUnwrapped.pointee + } + } + + public subscript(index: Int) -> Element { + @_unsafeSelfDependentResult + borrow { + precondition(index >= 0 && index < _count, "Index out of bounds") + return _storage.baseAddress.unsafelyUnwrapped.advanced(by: index).pointee + } + @_unsafeSelfDependentResult + mutate { + precondition(index >= 0 && index < _count, "Index out of bounds") + return &_storage.baseAddress.unsafelyUnwrapped.advanced(by: index).pointee + } + } +} + +extension Container: Copyable where Element: Copyable {} + diff --git a/test/Serialization/borrow_accessor_client.swift b/test/Serialization/borrow_accessor_client.swift new file mode 100644 index 0000000000000..aa39c8806d837 --- /dev/null +++ b/test/Serialization/borrow_accessor_client.swift @@ -0,0 +1,38 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-module -module-name borrow_accessor_container -enable-experimental-feature BorrowAndMutateAccessors -o %t %S/Inputs/borrow_accessor_container.swift +// RUN: %target-swift-frontend -I %t -emit-sil %s -verify | %FileCheck %s + +// REQUIRES: swift_feature_BorrowAndMutateAccessors + +import borrow_accessor_container + +func test() { + let n = 10_000 + var arr = Array(0...n) + let count = arr.count + let sum = arr.withUnsafeMutableBufferPointer { ubpointer in + let container = Container(ubpointer, count) + var sum = 0 + for i in 0.. (Int, @guaranteed Container<τ_0_0>) -> @guaranteed_addr τ_0_0 +// CHECK: sil @$s25borrow_accessor_container9ContainerVAARi_zrlEyxSiciz : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (Int, @inout Container<τ_0_0>) -> @guaranteed_addr τ_0_0 +