Skip to content

Commit 788d0f9

Browse files
authored
Merge pull request swiftlang#79396 from swiftlang/gaborh/fix-lifetime-errors-in-macros
[cxx-interop] Work around lifetime errors in SwiftifyImport generated code
2 parents 6ef0a93 + df27b79 commit 788d0f9

File tree

6 files changed

+42
-10
lines changed

6 files changed

+42
-10
lines changed

lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ struct CxxSpanReturnThunkBuilder: BoundsCheckedThunkBuilder {
437437

438438
func buildFunctionCall(_ pointerArgs: [Int: ExprSyntax]) throws -> ExprSyntax {
439439
let call = try base.buildFunctionCall(pointerArgs)
440-
return "Span(_unsafeCxxSpan: \(call))"
440+
return "_unsafeRemoveLifetime(Span(_unsafeCxxSpan: \(call)))"
441441
}
442442
}
443443

stdlib/public/Cxx/CxxSpan.swift

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

21+
/// Used by SwiftifyImport to work around a compiler diagnostic. It should be removed once the
22+
/// workaround is no longer needed.
23+
@_unsafeNonescapableResult
24+
@_alwaysEmitIntoClient
25+
@_transparent
26+
public func _unsafeRemoveLifetime<T: ~Copyable & ~Escapable>(_ dependent: consuming T) -> T {
27+
dependent
28+
}
29+
2130
/// Unsafely discard any lifetime dependency on the `dependent` argument. Return
2231
/// a value identical to `dependent` with a lifetime dependency on the caller's
2332
/// borrow scope of the `source` argument.
@@ -81,7 +90,7 @@ extension CxxSpan {
8190
extension Span {
8291
@_alwaysEmitIntoClient
8392
@unsafe
84-
@lifetime(borrow span)
93+
@_unsafeNonescapableResult
8594
public init<T: CxxSpan<Element>>(
8695
_unsafeCxxSpan span: borrowing T,
8796
) {

test/Interop/Cxx/stdlib/Inputs/std-span.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ inline SpanOfInt initSpan(int arr[], size_t size) {
5757
struct DependsOnSelf {
5858
std::vector<int> v;
5959
__attribute__((swift_name("get()")))
60-
ConstSpanOfInt get() [[clang::lifetimebound]] { return ConstSpanOfInt(v.data(), v.size()); }
60+
ConstSpanOfInt get() const [[clang::lifetimebound]] { return ConstSpanOfInt(v.data(), v.size()); }
6161
};
6262

6363
inline struct SpanBox getStructSpanBox() { return {iarray, iarray, sarray, sarray}; }

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import CxxStdlib
1515

1616
// CHECK: struct DependsOnSelf {
1717
// CHECK: @lifetime(borrow self)
18-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public mutating func get() -> Span<CInt>
19-
// CHECK-NEXT: mutating func get() -> ConstSpanOfInt
18+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public borrowing func get() -> Span<CInt>
19+
// CHECK-NEXT: borrowing func get() -> ConstSpanOfInt
2020

2121
// CHECK: mutating func set(_ x: borrowing std.{{.*}}vector<CInt, std.{{.*}}allocator<CInt>>)
2222
// CHECK: func funcWithSafeWrapper(_ s: ConstSpanOfInt)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %target-run-simple-swift(-plugin-path %swift-plugin-dir -I %S/Inputs -Xfrontend -enable-experimental-cxx-interop -swift-version 6 -Xfrontend -disable-availability-checking -Xcc -std=c++20 -enable-experimental-feature LifetimeDependence -enable-experimental-feature Span -enable-experimental-feature SafeInteropWrappers)
2+
3+
// FIXME swift-ci linux tests do not support std::span
4+
// UNSUPPORTED: OS=linux-gnu
5+
6+
// TODO: test failed in Windows PR testing: rdar://144384453
7+
// UNSUPPORTED: OS=windows-msvc
8+
9+
// REQUIRES: swift_feature_SafeInteropWrappers
10+
// REQUIRES: swift_feature_Span
11+
// REQUIRES: swift_feature_LifetimeDependence
12+
13+
// REQUIRES: executable_test
14+
15+
#if !BRIDGING_HEADER
16+
import StdSpan
17+
#endif
18+
import CxxStdlib
19+
20+
func canCallSafeSpanAPIs(_ x: Span<CInt>) {
21+
funcWithSafeWrapper(x)
22+
funcWithSafeWrapper2(x)
23+
}

test/Macros/SwiftifyImport/CxxSpan/LifetimeboundSpan.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,25 @@ struct X {
3535

3636
// CHECK: @_alwaysEmitIntoClient @lifetime(span)
3737
// CHECK-NEXT: func myFunc(_ span: Span<CInt>) -> Span<CInt> {
38-
// CHECK-NEXT: return Span(_unsafeCxxSpan: myFunc(SpanOfInt(span)))
38+
// CHECK-NEXT: return _unsafeRemoveLifetime(Span(_unsafeCxxSpan: myFunc(SpanOfInt(span))))
3939
// CHECK-NEXT: }
4040

4141
// CHECK: @_alwaysEmitIntoClient @lifetime(borrow vec) @_disfavoredOverload
4242
// CHECK-NEXT: func myFunc2(_ vec: borrowing VecOfInt) -> Span<CInt> {
43-
// CHECK-NEXT: return Span(_unsafeCxxSpan: myFunc2(vec))
43+
// CHECK-NEXT: return _unsafeRemoveLifetime(Span(_unsafeCxxSpan: myFunc2(vec)))
4444
// CHECK-NEXT: }
4545

4646
// CHECK: @_alwaysEmitIntoClient @lifetime(span1, span2)
4747
// CHECK-NEXT: func myFunc3(_ span1: Span<CInt>, _ span2: Span<CInt>) -> Span<CInt> {
48-
// CHECK-NEXT: return Span(_unsafeCxxSpan: myFunc3(SpanOfInt(span1), SpanOfInt(span2)))
48+
// CHECK-NEXT: return _unsafeRemoveLifetime(Span(_unsafeCxxSpan: myFunc3(SpanOfInt(span1), SpanOfInt(span2))))
4949
// CHECK-NEXT: }
5050

5151
// CHECK: @_alwaysEmitIntoClient @lifetime(borrow vec, span)
5252
// CHECK-NEXT: func myFunc4(_ vec: borrowing VecOfInt, _ span: Span<CInt>) -> Span<CInt> {
53-
// CHECK-NEXT: return Span(_unsafeCxxSpan: myFunc4(vec, SpanOfInt(span)))
53+
// CHECK-NEXT: return _unsafeRemoveLifetime(Span(_unsafeCxxSpan: myFunc4(vec, SpanOfInt(span))))
5454
// CHECK-NEXT: }
5555

5656
// CHECK: @_alwaysEmitIntoClient @lifetime(borrow self) @_disfavoredOverload
5757
// CHECK-NEXT: func myFunc5() -> Span<CInt> {
58-
// CHECK-NEXT: return Span(_unsafeCxxSpan: myFunc5())
58+
// CHECK-NEXT: return _unsafeRemoveLifetime(Span(_unsafeCxxSpan: myFunc5()))
5959
// CHECK-NEXT: }

0 commit comments

Comments
 (0)