Skip to content

Commit 9756755

Browse files
authored
Merge pull request #3758 from swiftix/SE-130-implementation
Implementation of the SE-130 proposal.
2 parents 56dd5ea + a798852 commit 9756755

File tree

5 files changed

+69
-31
lines changed

5 files changed

+69
-31
lines changed

benchmark/single-source/StringTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import TestsUtils
1313

1414
public func run_StringWithCString(_ N: Int) {
15-
let str = String(repeating: "x" as UnicodeScalar, count: 100 * (1 << 16))
15+
let str = String(repeating: "x", count: 100 * (1 << 16))
1616
for _ in 0 ..< N {
1717
str.withCString { _ in }
1818
}

stdlib/public/core/String.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,8 +651,9 @@ extension String {
651651
///
652652
/// - Complexity: Appending a Unicode scalar to a string averages to O(1)
653653
/// over many additions.
654+
@available(*, unavailable, message: "Replaced by append(_: String)")
654655
public mutating func append(_ x: UnicodeScalar) {
655-
_core.append(x)
656+
Builtin.unreachable()
656657
}
657658

658659
public // SPI(Foundation)

stdlib/public/core/StringLegacy.swift

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,9 @@ extension String {
2222
/// let zeroes = String("0" as Character, count: 10)
2323
/// print(zeroes)
2424
/// // Prints "0000000000"
25+
@available(*, unavailable, message: "Replaced by init(repeating: String, count: Int)")
2526
public init(repeating repeatedValue: Character, count: Int) {
26-
let s = String(repeatedValue)
27-
self = String(_storage: _StringBuffer(
28-
capacity: s._core.count * count,
29-
initialSize: 0,
30-
elementWidth: s._core.elementWidth))
31-
for _ in 0..<count {
32-
self += s
33-
}
27+
Builtin.unreachable()
3428
}
3529

3630
/// Creates a string representing the given Unicode scalar repeated the
@@ -42,12 +36,37 @@ extension String {
4236
/// let zeroes = String("0" as UnicodeScalar, count: 10)
4337
/// print(zeroes)
4438
/// // Prints "0000000000"
39+
40+
@available(*, unavailable, message: "Replaced by init(repeating: String, count: Int)")
4541
public init(repeating repeatedValue: UnicodeScalar, count: Int) {
46-
self = String._fromWellFormedCodeUnitSequence(
47-
UTF32.self,
48-
input: repeatElement(repeatedValue.value, count: count))
42+
Builtin.unreachable()
4943
}
50-
44+
45+
/// Creates a string representing the given string repeated the
46+
/// specified number of times.
47+
///
48+
/// For example, use this initializer to create a string with ten `"00"`
49+
/// strings in a row.
50+
///
51+
/// let zeroes = String(repeating: "00", count: 10)
52+
/// print(zeroes)
53+
/// // Prints "00000000000000000000"
54+
public init(repeating repeatedValue: String, count: Int) {
55+
if count == 0 {
56+
self = ""
57+
return
58+
}
59+
precondition(count > 0, "Negative count not allowed")
60+
let s = repeatedValue
61+
self = String(_storage: _StringBuffer(
62+
capacity: s._core.count * count,
63+
initialSize: 0,
64+
elementWidth: s._core.elementWidth))
65+
for _ in 0..<count {
66+
self += s
67+
}
68+
}
69+
5170
public var _lines : [String] {
5271
return _split(separator: "\n")
5372
}
@@ -65,7 +84,9 @@ extension String {
6584

6685
extension String {
6786
public init(_ _c: UnicodeScalar) {
68-
self = String(repeating: _c, count: 1)
87+
self = String._fromWellFormedCodeUnitSequence(
88+
UTF32.self,
89+
input: repeatElement(_c.value, count: 1))
6990
}
7091
}
7192

test/1_stdlib/Renames.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,9 +463,15 @@ func _StringCharacterView<S, C>(x: String.CharacterView, s: S, c: C, i: String.C
463463
x.appendContentsOf(s) // expected-error {{'appendContentsOf' has been renamed to 'append(contentsOf:)'}} {{5-21=append}} {{22-22=contentsOf: }} {{none}}
464464
}
465465

466+
func _StringAppend(s: inout String, u: UnicodeScalar) {
467+
s.append(u) // expected-error {{'append' is unavailable: Replaced by append(_: String)}} {{none}}
468+
}
469+
466470
func _StringLegacy(c: Character, u: UnicodeScalar) {
467471
_ = String(count: 1, repeatedValue: c) // expected-error {{'init(count:repeatedValue:)' is unavailable: Renamed to init(repeating:count:) and reordered parameters}} {{none}}
468472
_ = String(count: 1, repeatedValue: u) // expected-error {{'init(count:repeatedValue:)' is unavailable: Renamed to init(repeating:count:) and reordered parameters}} {{none}}
473+
_ = String(repeating: c, count: 1) // expected-error {{'init(repeating:count:)' is unavailable: Replaced by init(repeating: String, count: Int)}} {{none}}
474+
_ = String(repeating: u, count: 1) // expected-error {{'init(repeating:count:)' is unavailable: Replaced by init(repeating: String, count: Int)}} {{none}}
469475
}
470476

471477
func _Unicode() {

validation-test/stdlib/String.swift

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ StringTests.test("appendToSubstring") {
408408
sliceEnd < sliceStart {
409409
continue
410410
}
411-
var s0 = String(repeating: UnicodeScalar("x"), count: initialSize)
411+
var s0 = String(repeating: "x", count: initialSize)
412412
let originalIdentity = s0.bufferID
413413
s0 = s0[s0.index(_nth: sliceStart)..<s0.index(_nth: sliceEnd)]
414414
expectEqual(originalIdentity, s0.bufferID)
@@ -417,11 +417,15 @@ StringTests.test("appendToSubstring") {
417417
// and we could get some unused capacity in the buffer. In that case,
418418
// the identity would not change.
419419
if sliceEnd != initialSize {
420-
expectNotEqual(originalIdentity, s0.bufferID)
420+
if sliceStart != sliceEnd {
421+
expectNotEqual(originalIdentity, s0.bufferID)
422+
} else {
423+
expectEqual(0, s0.bufferID)
424+
}
421425
}
422426
expectEqual(
423427
String(
424-
repeating: UnicodeScalar("x"),
428+
repeating: "x",
425429
count: sliceEnd - sliceStart + 1),
426430
s0)
427431
}
@@ -450,8 +454,8 @@ StringTests.test("appendToSubstringBug") {
450454
let prefixSize = size - suffixSize
451455
for i in 1..<10 {
452456
// We will be overflowing s0 with s1.
453-
var s0 = String(repeating: UnicodeScalar("x"), count: size)
454-
let s1 = String(repeating: UnicodeScalar("x"), count: prefixSize)
457+
var s0 = String(repeating: "x", count: size)
458+
let s1 = String(repeating: "x", count: prefixSize)
455459
let originalIdentity = s0.bufferID
456460

457461
// Turn s0 into a slice that points to the end.
@@ -460,16 +464,22 @@ StringTests.test("appendToSubstringBug") {
460464
// Slicing should not reallocate.
461465
expectEqual(originalIdentity, s0.bufferID)
462466

467+
let originalCapacity = s0.capacity
468+
463469
// Overflow.
464470
s0 += s1
465471

466-
// We should correctly determine that the storage is too small and
472+
// We should correctly determine if the storage is too small and
467473
// reallocate.
468-
expectNotEqual(originalIdentity, s0.bufferID)
474+
if originalCapacity < suffixSize + prefixSize {
475+
expectNotEqual(originalIdentity, s0.bufferID)
476+
} else {
477+
expectEqual(originalIdentity, s0.bufferID)
478+
}
469479

470480
expectEqual(
471481
String(
472-
repeating: UnicodeScalar("x"),
482+
repeating: "x",
473483
count: suffixSize + prefixSize),
474484
s0)
475485
}
@@ -553,15 +563,15 @@ StringTests.test("COW/removeSubrange/end") {
553563
expectEqual("12345678", slice)
554564

555565
// No more reallocations are expected.
556-
str.append(UnicodeScalar("x"))
566+
str.append("x")
557567
str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
558568
expectEqual(heapStrIdentity, str.bufferID)
559569
expectEqual(literalIdentity, slice.bufferID)
560570
expectEqual("1234567", str)
561571
expectEqual("12345678", slice)
562572

563573
str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
564-
str.append(UnicodeScalar("x"))
574+
str.append("x")
565575
str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
566576
expectEqual(heapStrIdentity, str.bufferID)
567577
expectEqual(literalIdentity, slice.bufferID)
@@ -589,15 +599,15 @@ StringTests.test("COW/removeSubrange/end") {
589599
expectEqual("123456", slice)
590600

591601
// No more reallocations are expected.
592-
str.append(UnicodeScalar("x"))
602+
str.append("x")
593603
str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
594604
expectEqual(heapStrIdentity, str.bufferID)
595605
expectEqual(heapStrIdentity1, slice.bufferID)
596606
expectEqual("12345", str)
597607
expectEqual("123456", slice)
598608

599609
str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
600-
str.append(UnicodeScalar("x"))
610+
str.append("x")
601611
str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
602612
expectEqual(heapStrIdentity, str.bufferID)
603613
expectEqual(heapStrIdentity1, slice.bufferID)
@@ -1159,25 +1169,25 @@ StringTests.test("String.append(_: UnicodeScalar)") {
11591169
do {
11601170
// U+0061 LATIN SMALL LETTER A
11611171
let input: UnicodeScalar = "\u{61}"
1162-
s.append(input)
1172+
s.append(String(input))
11631173
expectEqual(["\u{61}"], Array(s.unicodeScalars))
11641174
}
11651175
do {
11661176
// U+304B HIRAGANA LETTER KA
11671177
let input: UnicodeScalar = "\u{304b}"
1168-
s.append(input)
1178+
s.append(String(input))
11691179
expectEqual(["\u{61}", "\u{304b}"], Array(s.unicodeScalars))
11701180
}
11711181
do {
11721182
// U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
11731183
let input: UnicodeScalar = "\u{3099}"
1174-
s.append(input)
1184+
s.append(String(input))
11751185
expectEqual(["\u{61}", "\u{304b}", "\u{3099}"], Array(s.unicodeScalars))
11761186
}
11771187
do {
11781188
// U+1F425 FRONT-FACING BABY CHICK
11791189
let input: UnicodeScalar = "\u{1f425}"
1180-
s.append(input)
1190+
s.append(String(input))
11811191
expectEqual(
11821192
["\u{61}", "\u{304b}", "\u{3099}", "\u{1f425}"],
11831193
Array(s.unicodeScalars))

0 commit comments

Comments
 (0)