Skip to content

Commit 4ae6b92

Browse files
authored
Merge pull request #58968 from Catfish-Man/boundless-guts-5-7
Actually slice things in _StringGutsSlice (5.7 cherry pick)
2 parents 0495ab8 + 052b48b commit 4ae6b92

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

stdlib/public/core/String.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -946,10 +946,11 @@ extension _StringGutsSlice {
946946
}
947947

948948
internal func _withNFCCodeUnits(_ f: (UInt8) throws -> Void) rethrows {
949+
let substring = String(_guts)[range]
949950
// Fast path: If we're already NFC (or ASCII), then we don't need to do
950951
// anything at all.
951952
if _fastPath(_guts.isNFC) {
952-
try String(_guts).utf8.forEach(f)
953+
try substring.utf8.forEach(f)
953954
return
954955
}
955956

@@ -962,7 +963,7 @@ extension _StringGutsSlice {
962963
// Because we have access to the fastUTF8, we can go through that instead
963964
// of accessing the UTF8 view on String.
964965
if isNFCQC {
965-
try _guts.withFastUTF8 {
966+
try withFastUTF8 {
966967
for byte in $0 {
967968
try f(byte)
968969
}
@@ -971,23 +972,23 @@ extension _StringGutsSlice {
971972
return
972973
}
973974
} else {
974-
for scalar in String(_guts).unicodeScalars {
975+
for scalar in substring.unicodeScalars {
975976
if !_isScalarNFCQC(scalar, &prevCCC) {
976977
isNFCQC = false
977978
break
978979
}
979980
}
980981

981982
if isNFCQC {
982-
for byte in String(_guts).utf8 {
983+
for byte in substring.utf8 {
983984
try f(byte)
984985
}
985986

986987
return
987988
}
988989
}
989990

990-
for scalar in String(_guts)._nfc {
991+
for scalar in substring._nfc {
991992
try scalar.withUTF8CodeUnits {
992993
for byte in $0 {
993994
try f(byte)

test/stdlib/StringAPI.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,28 @@ func checkStringComparison(
157157
expectEqual(expected.isGE(), lhs >= rhs, stackTrace: stackTrace)
158158
expectEqual(expected.isGT(), lhs > rhs, stackTrace: stackTrace)
159159
checkComparable(expected, lhs, rhs, stackTrace: stackTrace.withCurrentLoc())
160+
161+
// Substring / Substring
162+
// Matching slices of != Strings may still be ==, but not vice versa
163+
if expected.isEQ() {
164+
for i in 0 ..< Swift.min(lhs.count, rhs.count) {
165+
let lhsSub = lhs.dropFirst(i)
166+
let rhsSub = rhs.dropFirst(i)
167+
168+
expectEqual(expected.isEQ(), lhsSub == rhsSub, stackTrace: stackTrace)
169+
expectEqual(expected.isNE(), lhsSub != rhsSub, stackTrace: stackTrace)
170+
checkHashable(
171+
expectedEqual: expected.isEQ(),
172+
lhs, rhs, stackTrace: stackTrace.withCurrentLoc())
173+
174+
expectEqual(expected.isLT(), lhsSub < rhsSub, stackTrace: stackTrace)
175+
expectEqual(expected.isLE(), lhsSub <= rhsSub, stackTrace: stackTrace)
176+
expectEqual(expected.isGE(), lhsSub >= rhsSub, stackTrace: stackTrace)
177+
expectEqual(expected.isGT(), lhsSub > rhsSub, stackTrace: stackTrace)
178+
checkComparable(
179+
expected, lhsSub, rhsSub, stackTrace: stackTrace.withCurrentLoc())
180+
}
181+
}
160182

161183
#if _runtime(_ObjC)
162184
// NSString / NSString
@@ -471,5 +493,15 @@ StringTests.test("Regression/corelibs-foundation") {
471493
expectEqual(substring(of: s5, with: NSFakeRange(1,6)), "\ncats�")
472494
}
473495

496+
StringTests.test("Regression/radar-87371813") {
497+
let s1 = "what♕/".dropFirst(5)
498+
let s2 = "/"[...]
499+
let s3 = "/⚅".dropLast()
500+
expectEqual(s1, s2)
501+
expectEqual(s1, s3)
502+
expectEqual(s1, s3)
503+
expectEqual(s1.hashValue, s2.hashValue)
504+
expectEqual(s2.hashValue, s3.hashValue)
505+
}
474506

475507
runAllTests()

0 commit comments

Comments
 (0)