Skip to content

Commit 6084567

Browse files
committed
Fix Span initialization from CxxSpan.
CxxSpan is trivial, but not immortal. This initializer is diagnosed with an error after enabling trivial dependence enforcement. Correct this with an _overrideLifetime call. This could be avoided if we had a another way to tell the compiler that CxxSpan.__dataUnsafe() produced a pointer with the same effective lifetime as the CxxSpan.
1 parent 1f6a744 commit 6084567

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

stdlib/public/Cxx/CxxSpan.swift

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,24 @@ internal func unsafeBitCast<T: ~Escapable, U>(
1818
Builtin.reinterpretCast(x)
1919
}
2020

21+
/// Unsafely discard any lifetime dependency on the `dependent` argument. Return
22+
/// a value identical to `dependent` with a lifetime dependency on the caller's
23+
/// borrow scope of the `source` argument.
24+
@unsafe
25+
@_unsafeNonescapableResult
26+
@_alwaysEmitIntoClient
27+
@_transparent
28+
@lifetime(borrow source)
29+
internal func _overrideLifetime<
30+
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
31+
>(
32+
_ dependent: consuming T, borrowing source: borrowing U
33+
) -> T {
34+
// TODO: Remove @_unsafeNonescapableResult. Instead, the unsafe dependence
35+
// should be expressed by a builtin that is hidden within the function body.
36+
dependent
37+
}
38+
2139
/// A C++ type that is an object that can refer to a contiguous sequence of objects.
2240
///
2341
/// C++ standard library type `std::span` conforms to this protocol.
@@ -62,12 +80,15 @@ extension CxxSpan {
6280
@available(SwiftStdlib 6.1, *)
6381
extension Span {
6482
@_alwaysEmitIntoClient
65-
@lifetime(immortal)
6683
@unsafe
84+
@lifetime(borrow span)
6785
public init<T: CxxSpan<Element>>(
68-
_unsafeCxxSpan span: T,
86+
_unsafeCxxSpan span: borrowing T,
6987
) {
70-
self.init(_unsafeElements: .init(start: span.__dataUnsafe(), count: Int(span.size())))
88+
let buffer = UnsafeBufferPointer(start: span.__dataUnsafe(), count: Int(span.size()))
89+
let newSpan = Span(_unsafeElements: buffer)
90+
// 'self' is limited to the caller's scope of the variable passed to the 'span' argument.
91+
self = _overrideLifetime(newSpan, borrowing: span)
7192
}
7293
}
7394

0 commit comments

Comments
 (0)