Skip to content

Commit 854cffa

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 26efa24 commit 854cffa

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
@@ -182,4 +182,11 @@ SubstringTests.test("UTF8View") {
182182
expectEqual("", String(u.dropLast(10))!)
183183
}
184184

185+
SubstringTests.test("Persistent Content") {
186+
var str = "abc"
187+
str += "def"
188+
expectEqual("bcdefg", str.dropFirst(1) + "g")
189+
expectEqual("bcdefg", (str.dropFirst(1) + "g") as String)
190+
}
191+
185192
runAllTests()

0 commit comments

Comments
 (0)