Skip to content

[5.3] [stdlib] Performance fixes for removeFirst and removeLast #32647

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions stdlib/public/core/BidirectionalCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,12 @@ extension BidirectionalCollection where SubSequence == Self {
public mutating func removeLast(_ k: Int) {
if k == 0 { return }
_precondition(k >= 0, "Number of elements to remove should be non-negative")
_precondition(count >= k,
"Can't remove more items from a collection than it contains")
self = self[startIndex..<index(endIndex, offsetBy: -k)]
guard let end = index(endIndex, offsetBy: -k, limitedBy: startIndex)
else {
_preconditionFailure(
"Can't remove more items from a collection than it contains")
}
self = self[startIndex..<end]
}
}

Expand Down
8 changes: 5 additions & 3 deletions stdlib/public/core/Collection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1664,8 +1664,10 @@ extension Collection where SubSequence == Self {
public mutating func removeFirst(_ k: Int) {
if k == 0 { return }
_precondition(k >= 0, "Number of elements to remove should be non-negative")
_precondition(count >= k,
"Can't remove more items from a collection than it contains")
self = self[index(startIndex, offsetBy: k)..<endIndex]
guard let idx = index(startIndex, offsetBy: k, limitedBy: endIndex) else {
_preconditionFailure(
"Can't remove more items from a collection than it contains")
}
self = self[idx..<endIndex]
}
}
46 changes: 33 additions & 13 deletions stdlib/public/core/RangeReplaceableCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,17 @@ public protocol RangeReplaceableCollection: Collection
/// Customization point for `removeLast()`. Implement this function if you
/// want to replace the default implementation.
///
/// The collection must not be empty.
///
/// - Returns: A non-nil value if the operation was performed.
mutating func _customRemoveLast() -> Element?

/// Customization point for `removeLast(_:)`. Implement this function if you
/// want to replace the default implementation.
///
/// - Parameter n: The number of elements to remove from the collection.
/// `n` must be greater than or equal to zero and must not exceed the
/// number of elements in the collection.
/// - Returns: `true` if the operation was performed.
mutating func _customRemoveLast(_ n: Int) -> Bool

Expand Down Expand Up @@ -591,9 +596,10 @@ extension RangeReplaceableCollection {
public mutating func removeFirst(_ k: Int) {
if k == 0 { return }
_precondition(k >= 0, "Number of elements to remove should be non-negative")
_precondition(count >= k,
"Can't remove more items from a collection than it has")
let end = index(startIndex, offsetBy: k)
guard let end = index(startIndex, offsetBy: k, limitedBy: endIndex) else {
_preconditionFailure(
"Can't remove more items from a collection than it has")
}
removeSubrange(startIndex..<end)
}

Expand Down Expand Up @@ -699,9 +705,11 @@ extension RangeReplaceableCollection where SubSequence == Self {
public mutating func removeFirst(_ k: Int) {
if k == 0 { return }
_precondition(k >= 0, "Number of elements to remove should be non-negative")
_precondition(count >= k,
"Can't remove more items from a collection than it contains")
self = self[index(startIndex, offsetBy: k)..<endIndex]
guard let idx = index(startIndex, offsetBy: k, limitedBy: endIndex) else {
_preconditionFailure(
"Can't remove more items from a collection than it contains")
}
self = self[idx..<endIndex]
}
}

Expand Down Expand Up @@ -800,7 +808,12 @@ extension RangeReplaceableCollection

@inlinable
public mutating func _customRemoveLast(_ n: Int) -> Bool {
self = self[startIndex..<index(endIndex, offsetBy: numericCast(-n))]
guard let end = index(endIndex, offsetBy: -n, limitedBy: startIndex)
else {
_preconditionFailure(
"Can't remove more items from a collection than it contains")
}
self = self[startIndex..<end]
return true
}
}
Expand Down Expand Up @@ -864,13 +877,17 @@ extension RangeReplaceableCollection where Self: BidirectionalCollection {
public mutating func removeLast(_ k: Int) {
if k == 0 { return }
_precondition(k >= 0, "Number of elements to remove should be non-negative")
_precondition(count >= k,
"Can't remove more items from a collection than it contains")
if _customRemoveLast(k) {
return
}
let end = endIndex
removeSubrange(index(end, offsetBy: -k)..<end)
guard let start = index(end, offsetBy: -k, limitedBy: startIndex)
else {
_preconditionFailure(
"Can't remove more items from a collection than it contains")
}

removeSubrange(start..<end)
}
}

Expand Down Expand Up @@ -934,13 +951,16 @@ where Self: BidirectionalCollection, SubSequence == Self {
public mutating func removeLast(_ k: Int) {
if k == 0 { return }
_precondition(k >= 0, "Number of elements to remove should be non-negative")
_precondition(count >= k,
"Can't remove more items from a collection than it contains")
if _customRemoveLast(k) {
return
}
let end = endIndex
removeSubrange(index(end, offsetBy: -k)..<end)
guard let start = index(end, offsetBy: -k, limitedBy: startIndex)
else {
_preconditionFailure(
"Can't remove more items from a collection than it contains")
}
removeSubrange(start..<end)
}
}

Expand Down