Skip to content

Commit b27c90b

Browse files
[SE-0494] isTriviallyIdentical(to:) [memory regions] (#84998)
Add `isTriviallyIdentical(to:)` methods to: * `Span` * `RawSpan` * `UTF8Span` * `UnsafeBufferPointer` * `UnsafeMutableBufferPointer` * `UnsafeRawBufferPointer` * `UnsafeMutableRawBufferPointer` Part of issue #84991.
1 parent 0c7aded commit b27c90b

File tree

7 files changed

+163
-21
lines changed

7 files changed

+163
-21
lines changed

stdlib/public/core/Span/RawSpan.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,15 @@ extension RawSpan {
701701
unsafe (self._pointer == other._pointer) && (self._count == other._count)
702702
}
703703

704+
/// Returns a Boolean value indicating whether two instances refer to the same
705+
/// memory region.
706+
///
707+
/// - Complexity: O(1)
708+
@_alwaysEmitIntoClient
709+
public func isTriviallyIdentical(to other: Self) -> Bool {
710+
unsafe (self._pointer == other._pointer) && (self._count == other._count)
711+
}
712+
704713
/// Returns the offsets where the memory of `other` is located within
705714
/// the memory represented by `self`
706715
///

stdlib/public/core/Span/Span.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,15 @@ extension Span where Element: ~Copyable {
752752
unsafe (self._pointer == other._pointer) && (self._count == other._count)
753753
}
754754

755+
/// Returns a Boolean value indicating whether two instances refer to the same
756+
/// memory region.
757+
///
758+
/// - Complexity: O(1)
759+
@_alwaysEmitIntoClient
760+
public func isTriviallyIdentical(to other: Self) -> Bool {
761+
unsafe (self._pointer == other._pointer) && (self._count == other._count)
762+
}
763+
755764
/// Returns the indices within `self` where the memory represented by `other`
756765
/// is located, or `nil` if `other` is not located within `self`.
757766
///

stdlib/public/core/UTF8SpanComparisons.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,19 @@ extension UTF8Span {
104104
}
105105
}
106106

107+
@available(SwiftStdlib 6.2, *)
108+
extension UTF8Span {
109+
/// Returns a Boolean value indicating whether two instances refer to the same
110+
/// memory region, and have the same flags (such as ``isKnownASCII``).
111+
///
112+
/// - Complexity: O(1)
113+
@_alwaysEmitIntoClient
114+
public func isTriviallyIdentical(to other: Self) -> Bool {
115+
unsafe (self._unsafeBaseAddress == other._unsafeBaseAddress) &&
116+
(self._countAndFlags == other._countAndFlags)
117+
}
118+
}
119+
107120
// // FIXME: remove
108121
// @available(SwiftStdlib 6.2, *)
109122
// extension UTF8Span {

stdlib/public/core/UnsafeBufferPointer.swift.gyb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,18 @@ extension Unsafe${Mutable}BufferPointer where Element: ~Copyable {
600600
%end
601601
}
602602

603+
extension Unsafe${Mutable}BufferPointer where Element: ~Copyable {
604+
/// Returns a Boolean value indicating whether two instances refer to the same
605+
/// memory region.
606+
///
607+
/// - Complexity: O(1)
608+
@_alwaysEmitIntoClient
609+
@safe
610+
public func isTriviallyIdentical(to other: Self) -> Bool {
611+
unsafe (self._position == other._position) && (self.count == other.count)
612+
}
613+
}
614+
603615
extension Unsafe${Mutable}BufferPointer {
604616
/// Accesses the element at the specified position.
605617
///

stdlib/public/core/UnsafeRawBufferPointer.swift.gyb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,18 @@ extension Unsafe${Mutable}RawBufferPointer {
12171217
% end
12181218
}
12191219

1220+
extension Unsafe${Mutable}RawBufferPointer {
1221+
/// Returns a Boolean value indicating whether two instances refer to the same
1222+
/// memory region.
1223+
///
1224+
/// - Complexity: O(1)
1225+
@_alwaysEmitIntoClient
1226+
@safe
1227+
public func isTriviallyIdentical(to other: Self) -> Bool {
1228+
unsafe (self._position == other._position) && (self._end == other._end)
1229+
}
1230+
}
1231+
12201232
@_unavailableInEmbedded
12211233
extension Unsafe${Mutable}RawBufferPointer: CustomDebugStringConvertible {
12221234
/// A textual representation of the buffer, suitable for debugging.

test/stdlib/Span/SpanTests.swift

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -496,31 +496,78 @@ suite.test("withUnsafeBytes()")
496496
}
497497
}
498498

499-
suite.test("isIdentical(to:)")
499+
suite.test("isTriviallyIdentical(to:)")
500500
.skip(.custom(
501501
{ if #available(SwiftStdlib 6.2, *) { false } else { true } },
502502
reason: "Requires Swift 6.2's standard library"
503503
))
504504
.code {
505505
guard #available(SwiftStdlib 6.2, *) else { return }
506506

507+
func checkTriviallyIdentical<T: BitwiseCopyable>(
508+
_ x: UnsafeMutableBufferPointer<T>,
509+
_ y: UnsafeMutableBufferPointer<T>,
510+
_ expected: Bool,
511+
stackTrace: SourceLocStack = SourceLocStack(),
512+
showFrame: Bool = true,
513+
file: String = #file,
514+
line: UInt = #line
515+
) {
516+
let stackTrace = stackTrace.pushIf(showFrame, file: file, line: line)
517+
do {
518+
expectEqual(expected, x.isTriviallyIdentical(to: y), stackTrace: stackTrace)
519+
}
520+
do {
521+
let x = UnsafeBufferPointer<T>(x)
522+
let y = UnsafeBufferPointer<T>(y)
523+
expectEqual(expected, x.isTriviallyIdentical(to: y), stackTrace: stackTrace)
524+
}
525+
do {
526+
let x = UnsafeRawBufferPointer(x)
527+
let y = UnsafeRawBufferPointer(y)
528+
expectEqual(expected, x.isTriviallyIdentical(to: y), stackTrace: stackTrace)
529+
}
530+
do {
531+
let x = UnsafeMutableRawBufferPointer(x)
532+
let y = UnsafeMutableRawBufferPointer(y)
533+
expectEqual(expected, x.isTriviallyIdentical(to: y), stackTrace: stackTrace)
534+
}
535+
do {
536+
let x: Span<T> = unsafe x.span
537+
let y: Span<T> = unsafe y.span
538+
expectEqual(expected, x.isTriviallyIdentical(to: y), stackTrace: stackTrace)
539+
expectEqual(expected, x.isIdentical(to: y), stackTrace: stackTrace)
540+
}
541+
do {
542+
let x: RawSpan = unsafe x.span.bytes
543+
let y: RawSpan = unsafe y.span.bytes
544+
expectEqual(expected, x.isTriviallyIdentical(to: y), stackTrace: stackTrace)
545+
expectEqual(expected, x.isIdentical(to: y), stackTrace: stackTrace)
546+
}
547+
}
548+
549+
let a = UnsafeMutableBufferPointer<Int>(start: nil, count: 0)
507550
let b = UnsafeMutableBufferPointer<Int>.allocate(capacity: 8)
551+
let c = b.extracting(..<6) // FIXME: (first: 6)
552+
let d = b.extracting(2...) // FIXME: (last: 6)
553+
let e = c.extracting(2...) // FIXME: (last: 4)
554+
let f = d.extracting(..<4) // FIXME: (first: 4)
555+
508556
_ = b.initialize(fromContentsOf: 0..<8)
509557
defer { b.deallocate() }
510558

511-
let span = Span(_unsafeElements: b)
512-
let pre = span.extracting(first: 6)
513-
let suf = span.extracting(last: 6)
514-
515-
expectFalse(
516-
pre.isIdentical(to: suf)
517-
)
518-
expectFalse(
519-
pre.isIdentical(to: span)
520-
)
521-
expectTrue(
522-
pre.extracting(last: 4).isIdentical(to: suf.extracting(first: 4))
523-
)
559+
checkTriviallyIdentical(a, a, true)
560+
checkTriviallyIdentical(b, b, true)
561+
checkTriviallyIdentical(c, c, true)
562+
checkTriviallyIdentical(d, d, true)
563+
checkTriviallyIdentical(e, e, true)
564+
checkTriviallyIdentical(f, f, true)
565+
566+
checkTriviallyIdentical(a, b, false)
567+
checkTriviallyIdentical(b, c, false)
568+
checkTriviallyIdentical(c, d, false)
569+
checkTriviallyIdentical(d, e, false)
570+
checkTriviallyIdentical(e, f, true)
524571
}
525572

526573
suite.test("indices(of:)")

test/stdlib/UTF8SpanQueriesComparisons.swift

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ if #available(SwiftStdlib 6.2, *) {
9898
case notNFC
9999
}
100100

101-
let nfcQCNo = "\u{0374}"
102-
let nfcQCYes = "\u{0374}"
101+
// FIXME: let nfcQCNo = "\u{0374}"
102+
// FIXME: let nfcQCYes = "\u{0374}"
103103

104104
let tests: [(String, Normalness)] = [
105105
("abc", .known),
@@ -177,15 +177,55 @@ if #available(SwiftStdlib 6.2, *) {
177177
// Equivalence means no-one is less than the other
178178
expectFalse(utf8Decomposed.isCanonicallyLessThan(utf8Precomposed))
179179
expectFalse(utf8Precomposed.isCanonicallyLessThan(utf8Decomposed))
180-
181180
}
182-
183181
}
184-
185-
186182
}
187183

184+
suite.test("isTriviallyIdentical(to:)") {
185+
func checkTriviallyIdentical(
186+
_ x: Span<UInt8>,
187+
_ y: Span<UInt8>,
188+
_ expected: Bool,
189+
stackTrace: SourceLocStack = SourceLocStack(),
190+
showFrame: Bool = true,
191+
file: String = #file,
192+
line: UInt = #line
193+
) throws(UTF8.ValidationError) {
194+
let stackTrace = stackTrace.pushIf(showFrame, file: file, line: line)
195+
do {
196+
expectEqual(expected, x.isTriviallyIdentical(to: y), stackTrace: stackTrace)
197+
}
198+
do {
199+
let x = try UTF8Span(validating: x)
200+
let y = try UTF8Span(validating: y)
201+
expectEqual(expected, x.isTriviallyIdentical(to: y), stackTrace: stackTrace)
202+
}
203+
}
188204

205+
let a = Span<UInt8>()
206+
let b: Span<UInt8> = "isTriviallyIdentical(to:)".utf8.span
207+
let c = b.extracting(first: 20)
208+
let d = b.extracting(last: 23)
209+
let e = c.extracting(last: 18)
210+
let f = d.extracting(first: 18)
211+
212+
do throws(UTF8.ValidationError) {
213+
try checkTriviallyIdentical(a, a, true)
214+
try checkTriviallyIdentical(b, b, true)
215+
try checkTriviallyIdentical(c, c, true)
216+
try checkTriviallyIdentical(d, d, true)
217+
try checkTriviallyIdentical(e, e, true)
218+
try checkTriviallyIdentical(f, f, true)
219+
220+
try checkTriviallyIdentical(a, b, false)
221+
try checkTriviallyIdentical(b, c, false)
222+
try checkTriviallyIdentical(c, d, false)
223+
try checkTriviallyIdentical(d, e, false)
224+
try checkTriviallyIdentical(e, f, true)
225+
} catch {
226+
expectUnreachableCatch(error)
227+
}
228+
}
189229
}
190230

191231
// TODO: Rest of this file is in-progress TODOs
@@ -275,4 +315,4 @@ public func isCanonicallyLessThan(
275315
*/
276316

277317

278-
// }
318+
// }

0 commit comments

Comments
 (0)