Skip to content

[5.7] Fix algorithms overload resolution issues #425

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
30 changes: 29 additions & 1 deletion Sources/RegexBuilder/Algorithms.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//
//===----------------------------------------------------------------------===//

import _StringProcessing
@_spi(RegexBuilder) import _StringProcessing

// FIXME(rdar://92459215): We should be using 'some RegexComponent' instead of
// <R: RegexComponent> for the methods below that don't impose any additional
Expand Down Expand Up @@ -313,3 +313,31 @@ where Self: BidirectionalCollection, SubSequence == Substring {
try replace(content(), maxReplacements: maxReplacements, with: replacement)
}
}

// String split overload breakers

extension StringProtocol where SubSequence == Substring {
@available(SwiftStdlib 5.7, *)
public func split(
separator: String,
maxSplits: Int = .max,
omittingEmptySubsequences: Bool = true
) -> [Substring] {
return _split(
separator: separator,
maxSplits: maxSplits,
omittingEmptySubsequences: omittingEmptySubsequences)
}

@available(SwiftStdlib 5.7, *)
public func split(
separator: Substring,
maxSplits: Int = .max,
omittingEmptySubsequences: Bool = true
) -> [Substring] {
return _split(
separator: separator,
maxSplits: maxSplits,
omittingEmptySubsequences: omittingEmptySubsequences)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ extension Collection where Element: Equatable {
/// - Parameter other: A sequence to search for within this collection.
/// - Returns: `true` if the collection contains the specified sequence,
/// otherwise `false`.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func contains<C: Collection>(_ other: C) -> Bool
where C.Element == Element
Expand All @@ -49,11 +50,13 @@ extension BidirectionalCollection where Element: Comparable {
// Overload breakers

extension StringProtocol {
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func contains(_ other: String) -> Bool {
firstRange(of: other) != nil
}

@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func contains(_ other: Substring) -> Bool {
firstRange(of: other) != nil
Expand All @@ -68,6 +71,7 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Parameter regex: A regex to search for within this collection.
/// - Returns: `true` if the regex was found in the collection, otherwise
/// `false`.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func contains<R: RegexComponent>(_ regex: R) -> Bool {
_contains(RegexConsumer(regex))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Parameter regex: The regex to search for.
/// - Returns: A range in the collection of the first occurrence of `regex`.
/// Returns `nil` if `regex` is not found.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func firstRange<R: RegexComponent>(of regex: R) -> Range<Index>? {
_firstRange(of: RegexConsumer(regex))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Parameter regex: The regex to search for.
/// - Returns: A collection or ranges in the receiver of all occurrences of
/// `regex`. Returns an empty collection if `regex` is not found.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func ranges<R: RegexComponent>(
of regex: R
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ extension RangeReplaceableCollection where SubSequence == Substring {
/// sequence matching `regex` to replace. Default is `Int.max`.
/// - Returns: A new collection in which all occurrences of subsequence
/// matching `regex` are replaced by `replacement`.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func replacing<R: RegexComponent, Replacement: Collection>(
_ regex: R,
Expand Down
50 changes: 48 additions & 2 deletions Sources/_StringProcessing/Algorithms/Algorithms/Split.swift
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,17 @@ extension Collection where Element: Equatable {
/// - Parameter separator: The element to be split upon.
/// - Returns: A collection of subsequences, split from this collection's
/// elements.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func split<C: Collection>(
separator: C,
maxSplits: Int = .max,
omittingEmptySubsequences: Bool = true
) -> [SubSequence] where C.Element == Element {
Array(split(by: ZSearcher(pattern: Array(separator), by: ==), maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences))
Array(split(
by: ZSearcher(pattern: Array(separator), by: ==),
maxSplits: maxSplits,
omittingEmptySubsequences: omittingEmptySubsequences))
}
}

Expand Down Expand Up @@ -352,6 +356,45 @@ extension BidirectionalCollection where Element: Comparable {
// }
}

// String split overload breakers
//
// These are underscored and marked as SPI so that the *actual* public overloads
// are only visible in RegexBuilder, to avoid breaking source with the
// standard library's function of the same name that takes a `Character`
// as the separator. *Those* overloads are necessary as tie-breakers between
// the Collection-based and Regex-based `split`s, which in turn are both marked
// @_disfavoredOverload to avoid the wrong overload being selected when a
// collection's element type could be used interchangably with a collection of
// that element (e.g. `Array<OptionSet>.split(separator: [])`).

extension StringProtocol where SubSequence == Substring {
@_spi(RegexBuilder)
@available(SwiftStdlib 5.7, *)
public func _split(
separator: String,
maxSplits: Int = .max,
omittingEmptySubsequences: Bool = true
) -> [Substring] {
Array(split(
by: ZSearcher(pattern: Array(separator), by: ==),
maxSplits: maxSplits,
omittingEmptySubsequences: omittingEmptySubsequences))
}

@_spi(RegexBuilder)
@available(SwiftStdlib 5.7, *)
public func _split(
separator: Substring,
maxSplits: Int = .max,
omittingEmptySubsequences: Bool = true
) -> [Substring] {
Array(split(
by: ZSearcher(pattern: Array(separator), by: ==),
maxSplits: maxSplits,
omittingEmptySubsequences: omittingEmptySubsequences))
}
}

// MARK: Regex algorithms

@available(SwiftStdlib 5.7, *)
Expand Down Expand Up @@ -388,6 +431,9 @@ extension BidirectionalCollection where SubSequence == Substring {
maxSplits: Int = .max,
omittingEmptySubsequences: Bool = true
) -> [SubSequence] {
Array(split(by: RegexConsumer(separator), maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences))
Array(split(
by: RegexConsumer(separator),
maxSplits: maxSplits,
omittingEmptySubsequences: omittingEmptySubsequences))
}
}
3 changes: 2 additions & 1 deletion Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ extension Collection where SubSequence == Self, Element: Equatable {
}

extension RangeReplaceableCollection where Element: Equatable {
@_disfavoredOverload
/// Removes the initial elements that satisfy the given predicate from the
/// start of the sequence.
/// - Parameter predicate: A closure that takes an element of the sequence
Expand Down Expand Up @@ -290,6 +289,7 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Parameter prefix: The collection to remove from this collection.
/// - Returns: A collection containing the elements that does not match
/// `prefix` from the start.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func trimmingPrefix<R: RegexComponent>(_ regex: R) -> SubSequence {
_trimmingPrefix(RegexConsumer(regex))
Expand All @@ -311,6 +311,7 @@ extension RangeReplaceableCollection
{
/// Removes the initial elements that matches the given regex.
/// - Parameter regex: The regex to remove from this collection.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public mutating func trimPrefix<R: RegexComponent>(_ regex: R) {
_trimPrefix(RegexConsumer(regex))
Expand Down
Loading