mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[stdlib] String : RangeReplaceableCollection & BidirectionalCollection (#8921)
* [stdlib] String : RangeReplaceableCollection & BidirectionalCollection * Add source compatibility hack for Swift.max * Add source compatibility hack for Swift.min * Remove redundant conformance in benchmarks * Fix stupid typo I thought I'd already pushed * XFAIL testing now-redundant conformance * XFAIL an IDE test for now
This commit is contained in:
@@ -23,9 +23,6 @@ var editWords: [String] = [
|
||||
"gastroperiodynia",
|
||||
]
|
||||
|
||||
// FIXME: remove when String is a Collection
|
||||
extension String: RangeReplaceableCollection { }
|
||||
|
||||
let alphabet = "abcdefghijklmnopqrstuvwxyz"
|
||||
/// All edits that are one edit away from `word`
|
||||
func edits(_ word: String) -> Set<String> {
|
||||
|
||||
@@ -17,9 +17,6 @@ import Glibc
|
||||
import Darwin
|
||||
#endif
|
||||
|
||||
// FIXME: remove when String is a Collection
|
||||
extension String: Collection { }
|
||||
|
||||
/* match: search for regexp anywhere in text */
|
||||
func match(regexp: String, text: String) -> Bool {
|
||||
if regexp.first == "^" {
|
||||
|
||||
@@ -616,7 +616,7 @@ extension String {
|
||||
return _withOptionalOutParameter(leftover) {
|
||||
self._ns.getBytes(
|
||||
&buffer,
|
||||
maxLength: min(buffer.count, maxBufferCount),
|
||||
maxLength: Swift.min(buffer.count, maxBufferCount),
|
||||
usedLength: usedBufferCount,
|
||||
encoding: encoding.rawValue,
|
||||
options: options,
|
||||
@@ -636,7 +636,8 @@ extension String {
|
||||
public func getCString(
|
||||
_ buffer: inout [CChar], maxLength: Int, encoding: Encoding
|
||||
) -> Bool {
|
||||
return _ns.getCString(&buffer, maxLength: min(buffer.count, maxLength),
|
||||
return _ns.getCString(&buffer,
|
||||
maxLength: Swift.min(buffer.count, maxLength),
|
||||
encoding: encoding.rawValue)
|
||||
}
|
||||
|
||||
@@ -652,7 +653,7 @@ extension String {
|
||||
public func getFileSystemRepresentation(
|
||||
_ buffer: inout [CChar], maxLength: Int) -> Bool {
|
||||
return _ns.getFileSystemRepresentation(
|
||||
&buffer, maxLength: min(buffer.count, maxLength))
|
||||
&buffer, maxLength: Swift.min(buffer.count, maxLength))
|
||||
}
|
||||
|
||||
// - (void)
|
||||
|
||||
@@ -55,7 +55,7 @@ extension String {
|
||||
func _compareASCII(_ rhs: String) -> Int {
|
||||
var compare = Int(extendingOrTruncating: _swift_stdlib_memcmp(
|
||||
self._core.startASCII, rhs._core.startASCII,
|
||||
min(self._core.count, rhs._core.count)))
|
||||
Swift.min(self._core.count, rhs._core.count)))
|
||||
if compare == 0 {
|
||||
compare = self._core.count - rhs._core.count
|
||||
}
|
||||
|
||||
@@ -13,20 +13,6 @@
|
||||
import SwiftShims
|
||||
|
||||
extension String {
|
||||
/// Creates a string representing the given character repeated the specified
|
||||
/// number of times.
|
||||
///
|
||||
/// For example, use this initializer to create a string with ten `"0"`
|
||||
/// characters in a row.
|
||||
///
|
||||
/// let zeroes = String("0" as Character, count: 10)
|
||||
/// print(zeroes)
|
||||
/// // Prints "0000000000"
|
||||
@available(*, unavailable, message: "Replaced by init(repeating: String, count: Int)")
|
||||
public init(repeating repeatedValue: Character, count: Int) {
|
||||
Builtin.unreachable()
|
||||
}
|
||||
|
||||
/// Creates a string representing the given Unicode scalar repeated the
|
||||
/// specified number of times.
|
||||
///
|
||||
|
||||
@@ -10,10 +10,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// `String` does not conform to `RangeReplaceableCollection`, but provides a
|
||||
// similar API.
|
||||
|
||||
extension String {
|
||||
extension String : RangeReplaceableCollection, BidirectionalCollection {
|
||||
/// The index type for subscripting a string.
|
||||
public typealias Index = CharacterView.Index
|
||||
|
||||
@@ -24,6 +21,31 @@ extension String {
|
||||
/// the other through zero or more applications of `index(after:)`.
|
||||
public typealias IndexDistance = CharacterView.IndexDistance
|
||||
|
||||
/// Creates a string representing the given character repeated the specified
|
||||
/// number of times.
|
||||
///
|
||||
/// For example, use this initializer to create a string with ten `"0"`
|
||||
/// characters in a row.
|
||||
///
|
||||
/// let zeroes = String("0" as Character, count: 10)
|
||||
/// print(zeroes)
|
||||
/// // Prints "0000000000"
|
||||
public init(repeating repeatedValue: Character, count: Int) {
|
||||
self.init(repeating: String(repeatedValue), count: count)
|
||||
}
|
||||
|
||||
// Now that String conforms to Collection, we need to disambiguate between:
|
||||
// - init<T>(_ value: T) where T : LosslessStringConvertible
|
||||
// - init<S>(_ characters: S) where S : Sequence, S.Iterator.Element == Character
|
||||
// Cannot simply do init(_: String) as that would itself be ambiguous with
|
||||
// init?(_ description: String)
|
||||
public init<
|
||||
T : LosslessStringConvertible & Sequence
|
||||
>(_ other: T)
|
||||
where T.Iterator.Element == Character {
|
||||
self = other.description
|
||||
}
|
||||
|
||||
/// The position of the first character in a nonempty string.
|
||||
///
|
||||
/// In an empty string, `startIndex` is equal to `endIndex`.
|
||||
@@ -386,3 +408,33 @@ extension String {
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
// This is needed because of the issue described in SR-4660 which causes
|
||||
// source compatibility issues when String becomes a collection
|
||||
@_transparent
|
||||
public func max<T : Comparable>(_ x: T, _ y: T) -> T {
|
||||
return Swift.max(x,y)
|
||||
}
|
||||
|
||||
// This is needed because of the issue described in SR-4660 which causes
|
||||
// source compatibility issues when String becomes a collection
|
||||
@_transparent
|
||||
public func min<T : Comparable>(_ x: T, _ y: T) -> T {
|
||||
return Swift.min(x,y)
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
@available(*, unavailable, message: "Operator '+' cannot be used to append a String to a seqeunce of strings")
|
||||
public static func + <S : Sequence>(lhs: S, rhs: String) -> Never
|
||||
where S.Iterator.Element == String {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
@available(*, unavailable, message: "Operator '+' cannot be used to append a String to a seqeunce of strings")
|
||||
public static func + <S : Sequence>(lhs: String, rhs: S) -> Never
|
||||
where S.Iterator.Element == String {
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,45 +69,6 @@ ${stringSubscriptComment}
|
||||
Builtin.unreachable()
|
||||
}
|
||||
% end
|
||||
/// The unavailable `String.count` API.
|
||||
///
|
||||
/// The concept of "the number of characters in a string" has
|
||||
/// different interpretations in different libraries and system
|
||||
/// components. The correct interpretation should be selected
|
||||
/// according to the use case and the APIs involved, so `String`
|
||||
/// does not have a `count` property, since there is no universal
|
||||
/// answer to the question about the number of characters in a
|
||||
/// given string.
|
||||
///
|
||||
/// Swift provides several different ways to access the character
|
||||
/// data stored inside strings. To access the number of data units
|
||||
/// in each representation you can use the following APIs.
|
||||
///
|
||||
/// - `String.utf8.count` property returns the number of UTF-8 code
|
||||
/// units in the string. Use this API when converting the string
|
||||
/// to UTF-8. Most POSIX APIs process strings in terms of UTF-8
|
||||
/// code units.
|
||||
///
|
||||
/// - `String.utf16.count` property returns the number of UTF-16
|
||||
/// code units in the string. Most Cocoa and Cocoa touch APIs
|
||||
/// process strings in terms of UTF-16 code units. For example,
|
||||
/// instances of `NSRange` used with `NSAttributedString` and
|
||||
/// `NSRegularExpression` store substring offsets and lengths in
|
||||
/// terms of UTF-16 code units.
|
||||
///
|
||||
/// - `String.unicodeScalars.count` property returns the number of
|
||||
/// Unicode scalars in the string. Use this API when you are
|
||||
/// performing low-level manipulation of character data.
|
||||
///
|
||||
/// - `String.characters.count` property returns the number of
|
||||
/// extended grapheme clusters. Use this API to count the
|
||||
/// number of user-perceived characters in the string.
|
||||
@available(
|
||||
*, unavailable,
|
||||
message: "there is no universally good answer, see the documentation comment for discussion")
|
||||
public var count: Int {
|
||||
Builtin.unreachable()
|
||||
}
|
||||
}
|
||||
|
||||
% for View in ['UTF8View', 'UTF16View', 'UnicodeScalarView', 'CharacterView']:
|
||||
|
||||
@@ -705,9 +705,16 @@ protocol B23086402 {
|
||||
var c: [String] { get }
|
||||
}
|
||||
|
||||
// <rdar://problem/23550816> QoI: Poor diagnostic in argument list of "print" (varargs related)
|
||||
func test23086402(a: A23086402) {
|
||||
print(a.b.c + "") // expected-error {{binary operator '+' cannot be applied to operands of type '[String]' and 'String'}} expected-note {{expected an argument list of type '(String, String)'}}
|
||||
print(a.b.c + "") // should not crash but: expected-error {{}}
|
||||
}
|
||||
|
||||
// <rdar://problem/23550816> QoI: Poor diagnostic in argument list of "print" (varargs related)
|
||||
// The situation has changed. String now conforms to the RangeReplaceableCollection protocol
|
||||
// and `ss + s` becomes ambiguous. Diambiguation is provided with the unavailable overload
|
||||
// in order to produce a meaningful diagnostics. (Related: <rdar://problem/31763930>)
|
||||
func test23550816(ss: [String], s: String) {
|
||||
print(ss + s) // expected-error {{'+' is unavailable: Operator '+' cannot be used to append a String to a seqeunce of strings}}
|
||||
}
|
||||
|
||||
// <rdar://problem/23719432> [practicalswift] Compiler crashes on &(Int:_)
|
||||
|
||||
@@ -517,7 +517,7 @@ func _StringAppend(s: inout String, u: UnicodeScalar) {
|
||||
func _StringLegacy(c: Character, u: UnicodeScalar) {
|
||||
_ = String(count: 1, repeatedValue: c) // expected-error {{'init(count:repeatedValue:)' is unavailable: Renamed to init(repeating:count:) and reordered parameters}} {{none}}
|
||||
_ = String(count: 1, repeatedValue: u) // expected-error {{'init(count:repeatedValue:)' is unavailable: Renamed to init(repeating:count:) and reordered parameters}} {{none}}
|
||||
_ = String(repeating: c, count: 1) // expected-error {{'init(repeating:count:)' is unavailable: Replaced by init(repeating: String, count: Int)}} {{none}}
|
||||
_ = String(repeating: c, count: 1) // no more error, since String conforms to BidirectionalCollection
|
||||
_ = String(repeating: u, count: 1) // expected-error {{'init(repeating:count:)' is unavailable: Replaced by init(repeating: String, count: Int)}} {{none}}
|
||||
}
|
||||
|
||||
|
||||
@@ -361,6 +361,10 @@ StringTests.test("CompareStringsWithUnpairedSurrogates")
|
||||
)
|
||||
}
|
||||
|
||||
StringTests.test("String.init(_:String)") {
|
||||
let s: String = String("" as String) // should compile without ambiguities
|
||||
}
|
||||
|
||||
var CStringTests = TestSuite("CStringTests")
|
||||
|
||||
func getNullUTF8() -> UnsafeMutablePointer<UInt8>? {
|
||||
|
||||
@@ -30,11 +30,6 @@ func testIntSubscripting(s: String, i: Int) {
|
||||
_ = s[CountableClosedRange(17...20)] // expected-error{{subscript' is unavailable: cannot subscript String with a CountableClosedRange<Int>, see the documentation comment for discussion}}
|
||||
}
|
||||
|
||||
// Common pitfall: trying to access `String.count`.
|
||||
func testStringCount(s: String) {
|
||||
_ = s.count // expected-error{{'count' is unavailable: there is no universally good answer, see the documentation comment for discussion}}
|
||||
}
|
||||
|
||||
func testNonAmbiguousStringComparisons() {
|
||||
let s1 = "a"
|
||||
let s2 = "b"
|
||||
@@ -60,12 +55,6 @@ func testAmbiguousStringComparisons(s: String) {
|
||||
let a12 = nsString > s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
|
||||
}
|
||||
|
||||
func acceptsSequence<S : Sequence>(_ sequence: S) {}
|
||||
|
||||
func testStringIsNotASequence(s: String) {
|
||||
acceptsSequence(s) // expected-error {{argument type 'String' does not conform to expected type 'Sequence'}}
|
||||
}
|
||||
|
||||
func testStringDeprecation(hello: String) {
|
||||
let hello2 = hello
|
||||
.addingPercentEscapes(using: .utf8) // expected-warning{{'addingPercentEscapes(using:)' is deprecated}}
|
||||
|
||||
@@ -16,7 +16,6 @@ func test_StringSubscriptByInt(
|
||||
_ = x[r2] // expected-error {{'subscript' is unavailable: cannot subscript String with a ClosedRange<Int>, see the documentation comment for discussion}} {{none}}
|
||||
_ = x[r3] // expected-error {{'subscript' is unavailable: cannot subscript String with a CountableRange<Int>, see the documentation comment for discussion}} {{none}}
|
||||
_ = x[r4] // expected-error {{'subscript' is unavailable: cannot subscript String with a CountableClosedRange<Int>, see the documentation comment for discussion}} {{none}}
|
||||
_ = x.count // expected-error {{'count' is unavailable: there is no universally good answer, see the documentation comment for discussion}} {{none}}
|
||||
}
|
||||
|
||||
% if _runtime == 'objc':
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s | %FileCheck %s
|
||||
// RUN: %target-swift-ide-test -code-completion -code-completion-token=B -source-filename=%s | %FileCheck %s
|
||||
// XFAIL: *
|
||||
|
||||
func test1() {
|
||||
1 + [0]#^A^#
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
|
||||
// RUN: %target-swift-frontend %s -emit-ir
|
||||
|
||||
// XFAIL: *
|
||||
// TODO: Decide if this test should just be deleted, now String _is_ an RRC
|
||||
// Test case submitted to project by https://github.com/tmu (Teemu Kurppa)
|
||||
|
||||
extension String : RangeReplaceableCollection {}
|
||||
|
||||
Reference in New Issue
Block a user