From 70529b98f0d5c752fe3a3de153cff75c7ffe544c Mon Sep 17 00:00:00 2001 From: David Smith Date: Fri, 8 Nov 2024 09:04:58 -0800 Subject: [PATCH 01/12] Add an overload of append(contentsOf:) on Array that takes a Collection instead of a Sequence, and try using it to accelerate wCSIA-compatible Sequences --- stdlib/public/core/Array.swift | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/stdlib/public/core/Array.swift b/stdlib/public/core/Array.swift index 2a03a8d64dc65..2359a34cabcd1 100644 --- a/stdlib/public/core/Array.swift +++ b/stdlib/public/core/Array.swift @@ -1202,6 +1202,31 @@ extension Array: RangeReplaceableCollection { _appendElementAssumeUniqueAndCapacity(oldCount, newElement: newElement) _endMutation() } + + @inlinable + @_semantics("array.append_contentsOf") + @_effects(notEscaping self.value**) + public mutating func append(contentsOf newElements: __owned some Collection) { + let newElementsCount = newElements.count + // This check prevents a data race writing to _swiftEmptyArrayStorage + if newElementsCount == 0 { + return + } + defer { + _endMutation() + } + _reserveCapacityImpl(minimumCapacity: self.count + newElementsCount, + growForAppend: true) + + let oldCount = _buffer.mutableCount + let startNewElements = _buffer.mutableFirstElementAddress + oldCount + let buf = UnsafeMutableBufferPointer( + start: startNewElements, + count: _buffer.mutableCapacity - oldCount) + + _ = buf.initialize(fromContentsOf: newElements) + _buffer.mutableCount = _buffer.mutableCount + newElementsCount + } /// Adds the elements of a sequence to the end of the array. /// @@ -1228,6 +1253,14 @@ extension Array: RangeReplaceableCollection { defer { _endMutation() } + + let wasContiguous = newElements.withContiguousStorageIfAvailable { + append(contentsOf: $0) + return true + } + if wasContiguous != nil { + return + } let newElementsCount = newElements.underestimatedCount _reserveCapacityImpl(minimumCapacity: self.count + newElementsCount, From 81106a57ec8a5f1afda998a386f0c8dab42fd144 Mon Sep 17 00:00:00 2001 From: David Smith Date: Fri, 8 Nov 2024 10:35:03 -0800 Subject: [PATCH 02/12] Add an overload of append(contentsOf:) on ArraySlice that takes a Collection instead of a Sequence, and try using it to accelerate wCSIA-compatible Sequences --- stdlib/public/core/Array.swift | 24 ++++++++++--- stdlib/public/core/ArraySlice.swift | 56 ++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/stdlib/public/core/Array.swift b/stdlib/public/core/Array.swift index 2359a34cabcd1..90f5aa1e542c6 100644 --- a/stdlib/public/core/Array.swift +++ b/stdlib/public/core/Array.swift @@ -1203,6 +1203,22 @@ extension Array: RangeReplaceableCollection { _endMutation() } + /// Adds the elements of a collection to the end of the array. + /// + /// Use this method to append the elements of a collection to the end of this + /// array. This example appends the elements of a `Range` instance + /// to an array of integers. + /// + /// var numbers = [1, 2, 3, 4, 5] + /// numbers.append(contentsOf: 10...15) + /// print(numbers) + /// // Prints "[1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15]" + /// + /// - Parameter newElements: The elements to append to the array. + /// + /// - Complexity: O(*m*) on average, where *m* is the length of + /// `newElements`, over many calls to `append(contentsOf:)` on the same + /// array. @inlinable @_semantics("array.append_contentsOf") @_effects(notEscaping self.value**) @@ -1250,10 +1266,6 @@ extension Array: RangeReplaceableCollection { public mutating func append(contentsOf newElements: __owned S) where S.Element == Element { - defer { - _endMutation() - } - let wasContiguous = newElements.withContiguousStorageIfAvailable { append(contentsOf: $0) return true @@ -1261,6 +1273,10 @@ extension Array: RangeReplaceableCollection { if wasContiguous != nil { return } + + defer { + _endMutation() + } let newElementsCount = newElements.underestimatedCount _reserveCapacityImpl(minimumCapacity: self.count + newElementsCount, diff --git a/stdlib/public/core/ArraySlice.swift b/stdlib/public/core/ArraySlice.swift index 6c213c31c3a26..bee6fd73d0039 100644 --- a/stdlib/public/core/ArraySlice.swift +++ b/stdlib/public/core/ArraySlice.swift @@ -918,6 +918,7 @@ extension ArraySlice: RangeReplaceableCollection { /// same array. @inlinable @_semantics("array.append_element") + @_effects(notEscaping self.value**) public mutating func append(_ newElement: __owned Element) { _makeUniqueAndReserveCapacityIfNotUnique() let oldCount = _getCount() @@ -925,6 +926,47 @@ extension ArraySlice: RangeReplaceableCollection { _appendElementAssumeUniqueAndCapacity(oldCount, newElement: newElement) _endMutation() } + + /// Adds the elements of a sequence to the end of the array. + /// + /// Use this method to append the elements of a sequence to the end of this + /// array. This example appends the elements of a `Range` instance + /// to an array of integers. + /// + /// var numbers = [1, 2, 3, 4, 5] + /// numbers.append(contentsOf: 10...15) + /// print(numbers) + /// // Prints "[1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15]" + /// + /// - Parameter newElements: The elements to append to the array. + /// + /// - Complexity: O(*m*) on average, where *m* is the length of + /// `newElements`, over many calls to `append(contentsOf:)` on the same + /// array. + @inlinable + @_semantics("array.append_contentsOf") + @_effects(notEscaping self.value**) + public mutating func append(contentsOf newElements: __owned some Collection) { + let newElementsCount = newElements.count + // This check prevents a data race writing to _swiftEmptyArrayStorage + if newElementsCount == 0 { + return + } + defer { + _endMutation() + } + reserveCapacityForAppend(newElementsCount: newElementsCount) + _ = _buffer.beginCOWMutation() + + let oldCount = self.count + let startNewElements = _buffer.firstElementAddress + oldCount + let buf = UnsafeMutableBufferPointer( + start: startNewElements, + count: self.capacity - oldCount) + + _ = buf.initialize(fromContentsOf: newElements) + _buffer.count += newElementsCount + } /// Adds the elements of a sequence to the end of the array. /// @@ -944,9 +986,21 @@ extension ArraySlice: RangeReplaceableCollection { /// array. @inlinable @_semantics("array.append_contentsOf") + @_effects(notEscaping self.value**) public mutating func append(contentsOf newElements: __owned S) where S.Element == Element { + let wasContiguous = newElements.withContiguousStorageIfAvailable { + append(contentsOf: $0) + return true + } + if wasContiguous != nil { + return + } + + defer { + _endMutation() + } let newElementsCount = newElements.underestimatedCount reserveCapacityForAppend(newElementsCount: newElementsCount) _ = _buffer.beginCOWMutation() @@ -975,11 +1029,11 @@ extension ArraySlice: RangeReplaceableCollection { // append them in slow sequence-only mode _buffer._arrayAppendSequence(IteratorSequence(remainder)) } - _endMutation() } @inlinable @_semantics("array.reserve_capacity_for_append") + @_effects(notEscaping self.**) internal mutating func reserveCapacityForAppend(newElementsCount: Int) { let oldCount = self.count let oldCapacity = self.capacity From 47c486fffffe8939b763d45e0b70912fac124a5b Mon Sep 17 00:00:00 2001 From: David Smith Date: Fri, 8 Nov 2024 11:29:06 -0800 Subject: [PATCH 03/12] Add an overload of append(contentsOf:) on ContiguousArray that takes a Collection instead of a Sequence, and try using it to accelerate wCSIA-compatible Sequences --- stdlib/public/core/ArraySlice.swift | 9 ++-- stdlib/public/core/ContiguousArray.swift | 58 ++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/stdlib/public/core/ArraySlice.swift b/stdlib/public/core/ArraySlice.swift index bee6fd73d0039..9245a461de622 100644 --- a/stdlib/public/core/ArraySlice.swift +++ b/stdlib/public/core/ArraySlice.swift @@ -856,6 +856,7 @@ extension ArraySlice: RangeReplaceableCollection { @inlinable @_semantics("array.make_mutable") + @_effects(notEscaping self.**) internal mutating func _makeUniqueAndReserveCapacityIfNotUnique() { if _slowPath(!_buffer.beginCOWMutation()) { _copyToNewBuffer(oldCount: _buffer.count) @@ -864,6 +865,7 @@ extension ArraySlice: RangeReplaceableCollection { @inlinable @_semantics("array.mutate_unknown") + @_effects(notEscaping self.**) internal mutating func _reserveCapacityAssumingUniqueBuffer(oldCount: Int) { // Due to make_mutable hoisting the situation can arise where we hoist // _makeMutableAndUnique out of loop and use it to replace @@ -884,6 +886,7 @@ extension ArraySlice: RangeReplaceableCollection { @inlinable @_semantics("array.mutate_unknown") + @_effects(notEscaping self.**) internal mutating func _appendElementAssumeUniqueAndCapacity( _ oldCount: Int, newElement: __owned Element @@ -927,9 +930,9 @@ extension ArraySlice: RangeReplaceableCollection { _endMutation() } - /// Adds the elements of a sequence to the end of the array. + /// Adds the elements of a collection to the end of the array. /// - /// Use this method to append the elements of a sequence to the end of this + /// Use this method to append the elements of a collection to the end of this /// array. This example appends the elements of a `Range` instance /// to an array of integers. /// @@ -943,7 +946,7 @@ extension ArraySlice: RangeReplaceableCollection { /// - Complexity: O(*m*) on average, where *m* is the length of /// `newElements`, over many calls to `append(contentsOf:)` on the same /// array. - @inlinable + @inlinable @_alwaysEmitIntoClient @_semantics("array.append_contentsOf") @_effects(notEscaping self.value**) public mutating func append(contentsOf newElements: __owned some Collection) { diff --git a/stdlib/public/core/ContiguousArray.swift b/stdlib/public/core/ContiguousArray.swift index 3c7cf01fea388..258c553f600f6 100644 --- a/stdlib/public/core/ContiguousArray.swift +++ b/stdlib/public/core/ContiguousArray.swift @@ -740,6 +740,7 @@ extension ContiguousArray: RangeReplaceableCollection { @inlinable @_semantics("array.make_mutable") + @_effects(notEscaping self.**) internal mutating func _makeUniqueAndReserveCapacityIfNotUnique() { if _slowPath(!_buffer.beginCOWMutation()) { _createNewBuffer(bufferIsUnique: false, @@ -750,6 +751,7 @@ extension ContiguousArray: RangeReplaceableCollection { @inlinable @_semantics("array.mutate_unknown") + @_effects(notEscaping self.**) internal mutating func _reserveCapacityAssumingUniqueBuffer(oldCount: Int) { // Due to make_mutable hoisting the situation can arise where we hoist // _makeMutableAndUnique out of loop and use it to replace @@ -772,6 +774,7 @@ extension ContiguousArray: RangeReplaceableCollection { @inlinable @_semantics("array.mutate_unknown") + @_effects(notEscaping self.**) internal mutating func _appendElementAssumeUniqueAndCapacity( _ oldCount: Int, newElement: __owned Element @@ -805,6 +808,7 @@ extension ContiguousArray: RangeReplaceableCollection { /// - Complexity: O(1) on average, over many calls to `append(_:)` on the /// same array. @inlinable + @_effects(notEscaping self.value**) @_semantics("array.append_element") public mutating func append(_ newElement: __owned Element) { // Separating uniqueness check and capacity check allows hoisting the @@ -815,6 +819,50 @@ extension ContiguousArray: RangeReplaceableCollection { _appendElementAssumeUniqueAndCapacity(oldCount, newElement: newElement) _endMutation() } + + /// Adds the elements of a sequence to the end of the array. + /// + /// Use this method to append the elements of a sequence to the end of this + /// array. This example appends the elements of a `Range` instance + /// to an array of integers. + /// + /// var numbers = [1, 2, 3, 4, 5] + /// numbers.append(contentsOf: 10...15) + /// print(numbers) + /// // Prints "[1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15]" + /// + /// - Parameter newElements: The elements to append to the array. + /// + /// - Complexity: O(*m*) on average, where *m* is the length of + /// `newElements`, over many calls to `append(contentsOf:)` on the same + /// array. + @inlinable @_alwaysEmitIntoClient + @_effects(notEscaping self.value**) + @_semantics("array.append_contentsOf") + public mutating func append( + contentsOf newElements: __owned some Collection + ) { + let newElementsCount = newElements.count + // This check prevents a data race writing to _swiftEmptyArrayStorage + if newElementsCount == 0 { + return + } + defer { + _endMutation() + } + + _reserveCapacityImpl(minimumCapacity: self.count + newElementsCount, + growForAppend: true) + + let oldCount = _buffer.mutableCount + let startNewElements = _buffer.mutableFirstElementAddress + oldCount + let buf = UnsafeMutableBufferPointer( + start: startNewElements, + count: _buffer.mutableCapacity - oldCount) + + _ = buf.initialize(fromContentsOf: newElements) + _buffer.count += newElementsCount + } /// Adds the elements of a sequence to the end of the array. /// @@ -833,9 +881,18 @@ extension ContiguousArray: RangeReplaceableCollection { /// `newElements`, over many calls to `append(contentsOf:)` on the same /// array. @inlinable + @_effects(notEscaping self.value**) @_semantics("array.append_contentsOf") public mutating func append(contentsOf newElements: __owned S) where S.Element == Element { + + let wasContiguous = newElements.withContiguousStorageIfAvailable { + append(contentsOf: $0) + return true + } + if wasContiguous != nil { + return + } defer { _endMutation() @@ -887,6 +944,7 @@ extension ContiguousArray: RangeReplaceableCollection { } @inlinable + @_effects(notEscaping self.value**) @_semantics("array.reserve_capacity_for_append") internal mutating func reserveCapacityForAppend(newElementsCount: Int) { // Ensure uniqueness, mutability, and sufficient storage. Note that From 91c8e31bf2b5b16a308c2612c08098451dad0144 Mon Sep 17 00:00:00 2001 From: David Smith Date: Fri, 8 Nov 2024 12:48:17 -0800 Subject: [PATCH 04/12] Add _aEIC in one place it was missing --- stdlib/public/core/Array.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/core/Array.swift b/stdlib/public/core/Array.swift index 90f5aa1e542c6..29a6ee80ac3b5 100644 --- a/stdlib/public/core/Array.swift +++ b/stdlib/public/core/Array.swift @@ -1219,7 +1219,7 @@ extension Array: RangeReplaceableCollection { /// - Complexity: O(*m*) on average, where *m* is the length of /// `newElements`, over many calls to `append(contentsOf:)` on the same /// array. - @inlinable + @inlinable @_alwaysEmitIntoClient @_semantics("array.append_contentsOf") @_effects(notEscaping self.value**) public mutating func append(contentsOf newElements: __owned some Collection) { From f54c25fd4a8f58a7f7ac95be7387e3a8c40519cf Mon Sep 17 00:00:00 2001 From: David Smith Date: Mon, 11 Nov 2024 12:50:53 -0800 Subject: [PATCH 05/12] Assert that the incoming elements have a correct `count` implementation Co-authored-by: Karoy Lorentey --- stdlib/public/core/Array.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/public/core/Array.swift b/stdlib/public/core/Array.swift index 29a6ee80ac3b5..cee4984cbeeab 100644 --- a/stdlib/public/core/Array.swift +++ b/stdlib/public/core/Array.swift @@ -1240,7 +1240,8 @@ extension Array: RangeReplaceableCollection { start: startNewElements, count: _buffer.mutableCapacity - oldCount) - _ = buf.initialize(fromContentsOf: newElements) + let end = buf.initialize(fromContentsOf: newElements) + _precondition(end == buf.endIndex) _buffer.mutableCount = _buffer.mutableCount + newElementsCount } From 6ea11129e163945d5c84bc4bb79ef10f509753f5 Mon Sep 17 00:00:00 2001 From: David Smith Date: Mon, 11 Nov 2024 16:01:45 -0800 Subject: [PATCH 06/12] Remove inlinable, aEIC takes care of it --- stdlib/public/core/Array.swift | 2 +- stdlib/public/core/ArraySlice.swift | 2 +- stdlib/public/core/ContiguousArray.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/public/core/Array.swift b/stdlib/public/core/Array.swift index 29a6ee80ac3b5..11f2a387ea59c 100644 --- a/stdlib/public/core/Array.swift +++ b/stdlib/public/core/Array.swift @@ -1219,7 +1219,7 @@ extension Array: RangeReplaceableCollection { /// - Complexity: O(*m*) on average, where *m* is the length of /// `newElements`, over many calls to `append(contentsOf:)` on the same /// array. - @inlinable @_alwaysEmitIntoClient + @_alwaysEmitIntoClient @_semantics("array.append_contentsOf") @_effects(notEscaping self.value**) public mutating func append(contentsOf newElements: __owned some Collection) { diff --git a/stdlib/public/core/ArraySlice.swift b/stdlib/public/core/ArraySlice.swift index 9245a461de622..61ab427e90075 100644 --- a/stdlib/public/core/ArraySlice.swift +++ b/stdlib/public/core/ArraySlice.swift @@ -946,7 +946,7 @@ extension ArraySlice: RangeReplaceableCollection { /// - Complexity: O(*m*) on average, where *m* is the length of /// `newElements`, over many calls to `append(contentsOf:)` on the same /// array. - @inlinable @_alwaysEmitIntoClient + @_alwaysEmitIntoClient @_semantics("array.append_contentsOf") @_effects(notEscaping self.value**) public mutating func append(contentsOf newElements: __owned some Collection) { diff --git a/stdlib/public/core/ContiguousArray.swift b/stdlib/public/core/ContiguousArray.swift index 258c553f600f6..3fa1a2d9a9f27 100644 --- a/stdlib/public/core/ContiguousArray.swift +++ b/stdlib/public/core/ContiguousArray.swift @@ -836,7 +836,7 @@ extension ContiguousArray: RangeReplaceableCollection { /// - Complexity: O(*m*) on average, where *m* is the length of /// `newElements`, over many calls to `append(contentsOf:)` on the same /// array. - @inlinable @_alwaysEmitIntoClient + @_alwaysEmitIntoClient @_effects(notEscaping self.value**) @_semantics("array.append_contentsOf") public mutating func append( From 3bef25d6c904c23d7e42ca01b5befe71408f1c87 Mon Sep 17 00:00:00 2001 From: David Smith Date: Mon, 11 Nov 2024 16:02:07 -0800 Subject: [PATCH 07/12] Fix test to refer to the new overload --- test/SILOptimizer/array_contentof_opt.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/SILOptimizer/array_contentof_opt.swift b/test/SILOptimizer/array_contentof_opt.swift index 4671fd11631ad..48e26633cc773 100644 --- a/test/SILOptimizer/array_contentof_opt.swift +++ b/test/SILOptimizer/array_contentof_opt.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -O -sil-verify-all -emit-sil -Xllvm '-sil-inline-never-functions=$sSa6appendyy' -Xllvm -sil-inline-never-function='$sSa6append10contentsOfyqd__n_t7ElementQyd__RszSTRd__lFSi_SaySiGTg5' %s | %FileCheck %s +// RUN: %target-swift-frontend -O -sil-verify-all -emit-sil -Xllvm '-sil-inline-never-functions=$sSa6appendyy' -Xllvm -sil-inline-never-function='$sSa6append10contentsOfyqd__n_t7ElementQyd__RszSlRd__lFSi_SaySiGTg5' %s | %FileCheck %s // REQUIRES: swift_stdlib_no_asserts,optimized_stdlib // This is an end-to-end test of the Array.append(contentsOf:) -> @@ -63,7 +63,7 @@ public func dontPropagateContiguousArray(_ a: inout ContiguousArray) { // Check if the specialized Array.append(contentsOf:) is reasonably optimized for Array. -// CHECK-LABEL: sil shared {{.*}}@$sSa6append10contentsOfyqd__n_t7ElementQyd__RszSTRd__lFSi_SaySiGTg5 +// CHECK-LABEL: sil shared {{.*}}@$sSa6append10contentsOfyqd__n_t7ElementQyd__RszSlRd__lFSi_SaySiGTg5 // There should only be a single call to _createNewBuffer or reserveCapacityForAppend/reserveCapacityImpl. @@ -72,5 +72,5 @@ public func dontPropagateContiguousArray(_ a: inout ContiguousArray) { // CHECK: apply [[F]] // CHECK-NOT: apply -// CHECK-LABEL: } // end sil function '$sSa6append10contentsOfyqd__n_t7ElementQyd__RszSTRd__lFSi_SaySiGTg5 +// CHECK-LABEL: } // end sil function '$sSa6append10contentsOfyqd__n_t7ElementQyd__RszSlRd__lFSi_SaySiGTg5 From ad3e846deef8d1a47af950d7dabfffdb8dd8c0ae Mon Sep 17 00:00:00 2001 From: David Smith Date: Mon, 11 Nov 2024 16:24:58 -0800 Subject: [PATCH 08/12] Use withContiguousStorageIfAvailable in _copySequenceToContiguousArray too --- stdlib/public/core/ContiguousArrayBuffer.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stdlib/public/core/ContiguousArrayBuffer.swift b/stdlib/public/core/ContiguousArrayBuffer.swift index 0796d97668071..67d2df53fca20 100644 --- a/stdlib/public/core/ContiguousArrayBuffer.swift +++ b/stdlib/public/core/ContiguousArrayBuffer.swift @@ -1063,6 +1063,12 @@ extension Sequence { internal func _copySequenceToContiguousArray< S: Sequence >(_ source: S) -> ContiguousArray { + let contigArray = withContiguousStorageIfAvailable { + _copyCollectionToContiguousArray($0) + } + if let contigArray { + return contigArray + } let initialCapacity = source.underestimatedCount var builder = _UnsafePartiallyInitializedContiguousArrayBuffer( From 858caeca0fddeeb3c3d638030221950d0cd27743 Mon Sep 17 00:00:00 2001 From: David Smith Date: Mon, 11 Nov 2024 16:29:47 -0800 Subject: [PATCH 09/12] Verify counts in ArraySlice and ContiguousArray too --- stdlib/public/core/ArraySlice.swift | 3 ++- stdlib/public/core/ContiguousArray.swift | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/stdlib/public/core/ArraySlice.swift b/stdlib/public/core/ArraySlice.swift index 61ab427e90075..183df57128d16 100644 --- a/stdlib/public/core/ArraySlice.swift +++ b/stdlib/public/core/ArraySlice.swift @@ -967,7 +967,8 @@ extension ArraySlice: RangeReplaceableCollection { start: startNewElements, count: self.capacity - oldCount) - _ = buf.initialize(fromContentsOf: newElements) + let end = buf.initialize(fromContentsOf: newElements) + _precondition(end == buf.endIndex) _buffer.count += newElementsCount } diff --git a/stdlib/public/core/ContiguousArray.swift b/stdlib/public/core/ContiguousArray.swift index 3fa1a2d9a9f27..3715ad6a41d8c 100644 --- a/stdlib/public/core/ContiguousArray.swift +++ b/stdlib/public/core/ContiguousArray.swift @@ -860,7 +860,8 @@ extension ContiguousArray: RangeReplaceableCollection { start: startNewElements, count: _buffer.mutableCapacity - oldCount) - _ = buf.initialize(fromContentsOf: newElements) + let end = buf.initialize(fromContentsOf: newElements) + _precondition(end == buf.endIndex) _buffer.count += newElementsCount } From 1e415f41f031ff43c537e37a36711b2b95118f13 Mon Sep 17 00:00:00 2001 From: David Smith Date: Mon, 11 Nov 2024 19:24:23 -0800 Subject: [PATCH 10/12] Build fix --- stdlib/public/core/ContiguousArrayBuffer.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/core/ContiguousArrayBuffer.swift b/stdlib/public/core/ContiguousArrayBuffer.swift index 67d2df53fca20..3fe4882ca39f4 100644 --- a/stdlib/public/core/ContiguousArrayBuffer.swift +++ b/stdlib/public/core/ContiguousArrayBuffer.swift @@ -1063,7 +1063,7 @@ extension Sequence { internal func _copySequenceToContiguousArray< S: Sequence >(_ source: S) -> ContiguousArray { - let contigArray = withContiguousStorageIfAvailable { + let contigArray = source.withContiguousStorageIfAvailable { _copyCollectionToContiguousArray($0) } if let contigArray { From 48278c1931e4fe4cf5f0741113135b2e1fb61f27 Mon Sep 17 00:00:00 2001 From: David Smith Date: Mon, 11 Nov 2024 19:24:57 -0800 Subject: [PATCH 11/12] Remove effect annotations from types that don't currently use them --- stdlib/public/core/ArraySlice.swift | 7 ------- stdlib/public/core/ContiguousArray.swift | 7 ------- 2 files changed, 14 deletions(-) diff --git a/stdlib/public/core/ArraySlice.swift b/stdlib/public/core/ArraySlice.swift index 183df57128d16..c78e563e14ae4 100644 --- a/stdlib/public/core/ArraySlice.swift +++ b/stdlib/public/core/ArraySlice.swift @@ -856,7 +856,6 @@ extension ArraySlice: RangeReplaceableCollection { @inlinable @_semantics("array.make_mutable") - @_effects(notEscaping self.**) internal mutating func _makeUniqueAndReserveCapacityIfNotUnique() { if _slowPath(!_buffer.beginCOWMutation()) { _copyToNewBuffer(oldCount: _buffer.count) @@ -865,7 +864,6 @@ extension ArraySlice: RangeReplaceableCollection { @inlinable @_semantics("array.mutate_unknown") - @_effects(notEscaping self.**) internal mutating func _reserveCapacityAssumingUniqueBuffer(oldCount: Int) { // Due to make_mutable hoisting the situation can arise where we hoist // _makeMutableAndUnique out of loop and use it to replace @@ -886,7 +884,6 @@ extension ArraySlice: RangeReplaceableCollection { @inlinable @_semantics("array.mutate_unknown") - @_effects(notEscaping self.**) internal mutating func _appendElementAssumeUniqueAndCapacity( _ oldCount: Int, newElement: __owned Element @@ -921,7 +918,6 @@ extension ArraySlice: RangeReplaceableCollection { /// same array. @inlinable @_semantics("array.append_element") - @_effects(notEscaping self.value**) public mutating func append(_ newElement: __owned Element) { _makeUniqueAndReserveCapacityIfNotUnique() let oldCount = _getCount() @@ -948,7 +944,6 @@ extension ArraySlice: RangeReplaceableCollection { /// array. @_alwaysEmitIntoClient @_semantics("array.append_contentsOf") - @_effects(notEscaping self.value**) public mutating func append(contentsOf newElements: __owned some Collection) { let newElementsCount = newElements.count // This check prevents a data race writing to _swiftEmptyArrayStorage @@ -990,7 +985,6 @@ extension ArraySlice: RangeReplaceableCollection { /// array. @inlinable @_semantics("array.append_contentsOf") - @_effects(notEscaping self.value**) public mutating func append(contentsOf newElements: __owned S) where S.Element == Element { @@ -1037,7 +1031,6 @@ extension ArraySlice: RangeReplaceableCollection { @inlinable @_semantics("array.reserve_capacity_for_append") - @_effects(notEscaping self.**) internal mutating func reserveCapacityForAppend(newElementsCount: Int) { let oldCount = self.count let oldCapacity = self.capacity diff --git a/stdlib/public/core/ContiguousArray.swift b/stdlib/public/core/ContiguousArray.swift index 3715ad6a41d8c..def3abc9463e3 100644 --- a/stdlib/public/core/ContiguousArray.swift +++ b/stdlib/public/core/ContiguousArray.swift @@ -740,7 +740,6 @@ extension ContiguousArray: RangeReplaceableCollection { @inlinable @_semantics("array.make_mutable") - @_effects(notEscaping self.**) internal mutating func _makeUniqueAndReserveCapacityIfNotUnique() { if _slowPath(!_buffer.beginCOWMutation()) { _createNewBuffer(bufferIsUnique: false, @@ -751,7 +750,6 @@ extension ContiguousArray: RangeReplaceableCollection { @inlinable @_semantics("array.mutate_unknown") - @_effects(notEscaping self.**) internal mutating func _reserveCapacityAssumingUniqueBuffer(oldCount: Int) { // Due to make_mutable hoisting the situation can arise where we hoist // _makeMutableAndUnique out of loop and use it to replace @@ -774,7 +772,6 @@ extension ContiguousArray: RangeReplaceableCollection { @inlinable @_semantics("array.mutate_unknown") - @_effects(notEscaping self.**) internal mutating func _appendElementAssumeUniqueAndCapacity( _ oldCount: Int, newElement: __owned Element @@ -808,7 +805,6 @@ extension ContiguousArray: RangeReplaceableCollection { /// - Complexity: O(1) on average, over many calls to `append(_:)` on the /// same array. @inlinable - @_effects(notEscaping self.value**) @_semantics("array.append_element") public mutating func append(_ newElement: __owned Element) { // Separating uniqueness check and capacity check allows hoisting the @@ -837,7 +833,6 @@ extension ContiguousArray: RangeReplaceableCollection { /// `newElements`, over many calls to `append(contentsOf:)` on the same /// array. @_alwaysEmitIntoClient - @_effects(notEscaping self.value**) @_semantics("array.append_contentsOf") public mutating func append( contentsOf newElements: __owned some Collection @@ -882,7 +877,6 @@ extension ContiguousArray: RangeReplaceableCollection { /// `newElements`, over many calls to `append(contentsOf:)` on the same /// array. @inlinable - @_effects(notEscaping self.value**) @_semantics("array.append_contentsOf") public mutating func append(contentsOf newElements: __owned S) where S.Element == Element { @@ -945,7 +939,6 @@ extension ContiguousArray: RangeReplaceableCollection { } @inlinable - @_effects(notEscaping self.value**) @_semantics("array.reserve_capacity_for_append") internal mutating func reserveCapacityForAppend(newElementsCount: Int) { // Ensure uniqueness, mutability, and sufficient storage. Note that From 0dede682a8430759e0bd4ed4da186dcdb5e93877 Mon Sep 17 00:00:00 2001 From: David Smith Date: Tue, 12 Nov 2024 17:00:56 -0800 Subject: [PATCH 12/12] Fix assertion failures --- stdlib/public/core/Array.swift | 4 ++-- stdlib/public/core/ArraySlice.swift | 4 ++-- stdlib/public/core/ContiguousArray.swift | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/stdlib/public/core/Array.swift b/stdlib/public/core/Array.swift index e0676bfe545f2..859e301e52867 100644 --- a/stdlib/public/core/Array.swift +++ b/stdlib/public/core/Array.swift @@ -1238,8 +1238,8 @@ extension Array: RangeReplaceableCollection { let startNewElements = _buffer.mutableFirstElementAddress + oldCount let buf = UnsafeMutableBufferPointer( start: startNewElements, - count: _buffer.mutableCapacity - oldCount) - + count: newElementsCount) + _debugPrecondition(buf.endIndex <= _buffer.mutableCapacity) let end = buf.initialize(fromContentsOf: newElements) _precondition(end == buf.endIndex) _buffer.mutableCount = _buffer.mutableCount + newElementsCount diff --git a/stdlib/public/core/ArraySlice.swift b/stdlib/public/core/ArraySlice.swift index c78e563e14ae4..9b58f06464bbe 100644 --- a/stdlib/public/core/ArraySlice.swift +++ b/stdlib/public/core/ArraySlice.swift @@ -960,8 +960,8 @@ extension ArraySlice: RangeReplaceableCollection { let startNewElements = _buffer.firstElementAddress + oldCount let buf = UnsafeMutableBufferPointer( start: startNewElements, - count: self.capacity - oldCount) - + count: newElementsCount) + _debugPrecondition(buf.endIndex <= self.capacity) let end = buf.initialize(fromContentsOf: newElements) _precondition(end == buf.endIndex) _buffer.count += newElementsCount diff --git a/stdlib/public/core/ContiguousArray.swift b/stdlib/public/core/ContiguousArray.swift index def3abc9463e3..0c5ca1ec4c300 100644 --- a/stdlib/public/core/ContiguousArray.swift +++ b/stdlib/public/core/ContiguousArray.swift @@ -853,8 +853,8 @@ extension ContiguousArray: RangeReplaceableCollection { let startNewElements = _buffer.mutableFirstElementAddress + oldCount let buf = UnsafeMutableBufferPointer( start: startNewElements, - count: _buffer.mutableCapacity - oldCount) - + count: newElementsCount) + _debugPrecondition(buf.endIndex <= _buffer.mutableCapacity) let end = buf.initialize(fromContentsOf: newElements) _precondition(end == buf.endIndex) _buffer.count += newElementsCount