Skip to content

Commit 301a752

Browse files
authored
Merge pull request #81097 from swiftlang/gaborh/mutable-span-conversion
2 parents 7cfc1b9 + 7d0d872 commit 301a752

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

stdlib/public/Cxx/CxxSpan.swift

+13-3
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
import Builtin
1313

1414
@usableFromInline
15-
internal func unsafeBitCast<T: ~Escapable, U>(
16-
_ x: T, to type: U.Type
15+
internal func unsafeBitCast<T: ~Escapable & ~Copyable, U>(
16+
_ x: consuming T, to type: U.Type
1717
) -> U {
1818
Builtin.reinterpretCast(x)
1919
}
@@ -139,7 +139,7 @@ public protocol CxxMutableSpan<Element> {
139139
init(_ unsafeMutablePointer : UnsafeMutablePointer<Element>, _ count: Size)
140140

141141
func size() -> Size
142-
func __dataUnsafe() -> UnsafeMutablePointer<Element>
142+
func __dataUnsafe() -> UnsafeMutablePointer<Element>?
143143
}
144144

145145
extension CxxMutableSpan {
@@ -150,4 +150,14 @@ extension CxxMutableSpan {
150150
"UnsafeMutableBufferPointer should not point to nil")
151151
unsafe self.init(unsafeMutableBufferPointer.baseAddress!, Size(unsafeMutableBufferPointer.count))
152152
}
153+
154+
@available(SwiftStdlib 6.2, *)
155+
@inlinable
156+
@unsafe
157+
public init(_ span: consuming MutableSpan<Element>) {
158+
let (p, c) = unsafe unsafeBitCast(span, to: (UnsafeMutableRawPointer?, Int).self)
159+
unsafe precondition(p != nil, "Span should not point to nil")
160+
let binding = unsafe p!.bindMemory(to: Element.self, capacity: c)
161+
unsafe self.init(binding, Size(c))
162+
}
153163
}

test/Interop/Cxx/stdlib/use-std-span.swift

+24
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,30 @@ StdSpanTestSuite.test("Convert between Swift and C++ span types")
687687
expectEqual(cxxSpan[2], 3)
688688
}
689689
}
690+
do {
691+
var arr: [Int32] = [1, 2, 3]
692+
arr.withUnsafeMutableBufferPointer{ ubpointer in
693+
let s = SpanOfInt(ubpointer.baseAddress!, ubpointer.count)
694+
let swiftSpan = MutableSpan(_unsafeCxxSpan: s)
695+
expectEqual(swiftSpan.count, 3)
696+
expectFalse(swiftSpan.isEmpty)
697+
expectEqual(swiftSpan[0], 1)
698+
expectEqual(swiftSpan[1], 2)
699+
expectEqual(swiftSpan[2], 3)
700+
}
701+
}
702+
do {
703+
var arr: [Int32] = [1, 2, 3]
704+
arr.withUnsafeMutableBufferPointer{ ubpointer in
705+
let s = MutableSpan(_unsafeElements: ubpointer)
706+
let cxxSpan = SpanOfInt(s)
707+
expectEqual(cxxSpan.size(), 3)
708+
expectFalse(cxxSpan.empty())
709+
expectEqual(cxxSpan[0], 1)
710+
expectEqual(cxxSpan[1], 2)
711+
expectEqual(cxxSpan[2], 3)
712+
}
713+
}
690714
}
691715

692716
runAllTests()

0 commit comments

Comments
 (0)