Skip to content

Commit 5d354ce

Browse files
committed
[stdlib] Fix String.UTF16View.distance(from:to:)
- Align input indices to scalar boundaries - Don’t pass decreasing indices to _utf16Distance
1 parent 051f9ed commit 5d354ce

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

stdlib/public/core/StringUTF16View.swift

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,10 @@ extension String.UTF16View: BidirectionalCollection {
258258
return result
259259
}
260260

261+
@_effects(releasenone)
261262
public func distance(from start: Index, to end: Index) -> Int {
262-
let start = _guts.ensureMatchingEncoding(start)
263-
let end = _guts.ensureMatchingEncoding(end)
263+
var start = _guts.ensureMatchingEncoding(start)
264+
var end = _guts.ensureMatchingEncoding(end)
264265

265266
// FIXME: This method used to not properly validate indices before 5.7;
266267
// temporarily allow older binaries to keep invoking undefined behavior as
@@ -293,6 +294,11 @@ extension String.UTF16View: BidirectionalCollection {
293294
// code unit will map to a single UTF-8 code unit, i.e., the worst
294295
// possible (a.k.a. most compact) case with all ASCII scalars.
295296
// FIXME: Figure out if a more optimistic threshold would work better.
297+
start = _utf16AlignNativeIndex(start)
298+
end = _utf16AlignNativeIndex(end)
299+
guard start <= end else {
300+
return -_utf16Distance(from: end, to: start)
301+
}
296302
return _utf16Distance(from: start, to: end)
297303
}
298304

@@ -737,8 +743,7 @@ extension String.UTF16View {
737743
return utf16Count
738744
}
739745
#endif
740-
741-
@inline(__always)
746+
742747
internal func _utf16Distance(from start: Index, to end: Index) -> Int {
743748
_internalInvariant(end.transcodedOffset == 0 || end.transcodedOffset == 1)
744749

0 commit comments

Comments
 (0)