Skip to content

Commit 10e9e33

Browse files
committed
[stdlib] Fix bug in Substring's _persistentContent
Substring's _persistentContent has a fast path that avoids a copy when the Substring represents the entire outer String. It correctly detected situations where the wrapped _StringCore was not itself a slice, but was omitting the extra checks to make sure the Substring's own range covered the entire String. Test added.
1 parent b37417b commit 10e9e33

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

stdlib/public/core/Substring.swift.gyb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,16 @@ extension Substring : _SwiftStringView {
266266
var _persistentContent : String {
267267
let wholeCore = _slice._base._core
268268
let native = wholeCore.nativeBuffer
269-
if _fastPath(native != nil), let n = native {
269+
if _fastPath(native != nil) {
270+
let wholeString = String(wholeCore)
271+
let n = native._unsafelyUnwrappedUnchecked
270272
if _fastPath(
271-
n.start == wholeCore._baseAddress && n.usedCount == wholeCore.count) {
272-
return String(wholeCore)
273+
n.start == wholeCore._baseAddress
274+
&& n.usedCount == wholeCore.count
275+
&& _slice.startIndex == wholeString.startIndex
276+
&& _slice.endIndex == wholeString.endIndex
277+
) {
278+
return wholeString
273279
}
274280
}
275281
var r = String()

test/stdlib/subString.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,11 @@ SubstringTests.test("UTF8View") {
190190
expectEqual("", String(u.dropLast(10))!)
191191
}
192192

193+
SubstringTests.test("Persistent Content") {
194+
var str = "abc"
195+
str += "def"
196+
expectEqual("bcdefg", str.dropFirst(1) + "g")
197+
expectEqual("bcdefg", (str.dropFirst(1) + "g") as String)
198+
}
199+
193200
runAllTests()

0 commit comments

Comments
 (0)