Skip to content

Swiftify fixes for 6.2 #81827

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9201,9 +9201,10 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) {
paramHasLifetimeInfo = true;
}
if (clangParam->hasAttr<clang::LifetimeBoundAttr>()) {
printer.printLifetimeboundReturn(
index, !paramHasBoundsInfo &&
swiftParamTy->isEscapable());
// If this parameter has bounds info we will tranform it into a Span,
// so then it will no longer be Escapable.
bool willBeEscapable = swiftParamTy->isEscapable() && !paramHasBoundsInfo;
printer.printLifetimeboundReturn(index, willBeEscapable);
paramHasLifetimeInfo = true;
returnHasLifetimeInfo = true;
}
Expand Down
412 changes: 254 additions & 158 deletions lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions stdlib/public/Cxx/CxxSpan.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ extension CxxSpan {
unsafe self.init(unsafeMutableBufferPointer.baseAddress!, Size(unsafeMutableBufferPointer.count))
}

@available(SwiftStdlib 6.2, *)
@available(SwiftCompatibilitySpan 5.0, *)
@inlinable
@unsafe
public init(_ span: Span<Element>) {
Expand All @@ -99,7 +99,7 @@ extension CxxSpan {
}
}

@available(SwiftStdlib 6.2, *)
@available(SwiftCompatibilitySpan 5.0, *)
extension Span {
@_alwaysEmitIntoClient
@unsafe
Expand All @@ -115,7 +115,7 @@ extension Span {
}
}

@available(SwiftStdlib 6.2, *)
@available(SwiftCompatibilitySpan 5.0, *)
extension MutableSpan {
@_alwaysEmitIntoClient
@unsafe
Expand Down Expand Up @@ -151,7 +151,7 @@ extension CxxMutableSpan {
unsafe self.init(unsafeMutableBufferPointer.baseAddress!, Size(unsafeMutableBufferPointer.count))
}

@available(SwiftStdlib 6.2, *)
@available(SwiftCompatibilitySpan 5.0, *)
@inlinable
@unsafe
public init(_ span: consuming MutableSpan<Element>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ int * __counted_by(len) _Nonnull nonnull(int len, int len2, int * __counted_by(l
int * __counted_by(len) _Nullable nullable(int len, int len2, int * __counted_by(len2) __lifetimebound _Nullable p);

int * __counted_by(len) noncountedLifetime(int len, int * __lifetimebound p);

int * __counted_by(13) _Nullable constant(int * __counted_by(13) __lifetimebound _Nullable p);
55 changes: 55 additions & 0 deletions test/Interop/C/swiftify-import/Inputs/counted-by-noescape.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,58 @@ int * __counted_by(len) __noescape returnPointer(int len);
int * __counted_by(len1) returnLifetimeBound(int len1, int len2, int * __counted_by(len2) p __lifetimebound);

void anonymous(int len, int * __counted_by(len) _Nullable __noescape);

void keyword(int len, int * __counted_by(len) _Nullable func __noescape,
int extension,
int init,
int open,
int var,
int is,
int as,
int in,
int guard,
int where
);

void pointerName(int len, int * __counted_by(len) _Nullable pointerName __noescape);

void lenName(int lenName, int size, int * __counted_by(lenName * size) _Nullable p __noescape);

void func(int len, int * __counted_by(len) _Nullable func __noescape);

void *funcRenameKeyword(int len, int * __counted_by(len) _Nullable func __noescape,
int extension __lifetimebound,
int init,
int open,
int var,
int is,
int as,
int in,
int guard,
int where) __attribute__((swift_name("funcRenamed(len:func:extension:init:open:var:is:as:in:guard:where:)")));

void *funcRenameKeywordAnonymous(int len, int * __counted_by(len) _Nullable __noescape,
int __lifetimebound,
int,
int,
int,
int,
int,
int,
int,
int) __attribute__((swift_name("funcRenamedAnon(len:func:extension:init:open:var:is:as:in:guard:where:)")));

void funcRenameClash(int len, int * __counted_by(len) _Nullable func __noescape, int where)
__attribute__((swift_name("clash(len:func:clash:)")));

void funcRenameClashKeyword(int len, int * __counted_by(len) _Nullable func __noescape, int where)
__attribute__((swift_name("open(len:func:open:)")));

void funcRenameClashAnonymous(int len, int * __counted_by(len) _Nullable func __noescape, int)
__attribute__((swift_name("clash2(len:func:clash2:)")));

void funcRenameClashKeywordAnonymous(int len, int * __counted_by(len) _Nullable func __noescape, int)
__attribute__((swift_name("in(len:func:in:)")));

typedef struct actor_ *actor;
actor _Nonnull keywordType(int len, actor * __counted_by(len) __noescape p, actor _Nonnull p2);
8 changes: 4 additions & 4 deletions test/Interop/C/swiftify-import/comments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
// CHECK-NEXT:func blockDocComment(_ len: Int32, _ p: UnsafeMutablePointer<Int32>!)

// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop
// CHECK-NEXT:@_alwaysEmitIntoClient public func blockComment(_ p: UnsafeMutableBufferPointer<Int32>)
// CHECK-NEXT:@_alwaysEmitIntoClient @_disfavoredOverload public func blockComment(_ p: UnsafeMutableBufferPointer<Int32>)

// CHECK-NEXT:/**
// CHECK-NEXT: * block doc comment
Expand All @@ -37,10 +37,10 @@
// CHECK-NEXT: * @param p some integers to play with
// CHECK-NEXT: */
// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop
// CHECK-NEXT:@_alwaysEmitIntoClient public func blockDocComment(_ p: UnsafeMutableBufferPointer<Int32>)
// CHECK-NEXT:@_alwaysEmitIntoClient @_disfavoredOverload public func blockDocComment(_ p: UnsafeMutableBufferPointer<Int32>)

// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop
// CHECK-NEXT:@_alwaysEmitIntoClient public func lineComment(_ p: UnsafeMutableBufferPointer<Int32>)
// CHECK-NEXT:@_alwaysEmitIntoClient @_disfavoredOverload public func lineComment(_ p: UnsafeMutableBufferPointer<Int32>)

// CHECK-NEXT:/// line doc comment
// CHECK-NEXT:///
Expand All @@ -49,4 +49,4 @@
// CHECK-NEXT:/// @param len the buffer length
// CHECK-NEXT:/// @param p the buffer
// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop
// CHECK-NEXT:@_alwaysEmitIntoClient public func lineDocComment(_ p: UnsafeMutableBufferPointer<Int32>)
// CHECK-NEXT:@_alwaysEmitIntoClient @_disfavoredOverload public func lineDocComment(_ p: UnsafeMutableBufferPointer<Int32>)
28 changes: 20 additions & 8 deletions test/Interop/C/swiftify-import/counted-by-lifetimebound.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ import CountedByLifetimeboundClang
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
// CHECK-NEXT: @lifetime(copy p)
// CHECK-NEXT: @lifetime(p: copy p)
// CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int32, _ offset: Int32, _ len2: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func complexExpr(_ len: Int32, _ offset: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>

// CHECK: /// This is an auto-generated wrapper for safer interop
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
// CHECK-NEXT: @lifetime(copy p)
// CHECK-NEXT: @lifetime(p: copy p)
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func constant(_ p: inout MutableSpan<Int32>?) -> MutableSpan<Int32>?

// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
Expand All @@ -26,37 +32,37 @@ import CountedByLifetimeboundClang
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
// CHECK-NEXT: @lifetime(copy p)
// CHECK-NEXT: @lifetime(p: copy p)
// CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ len: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func nonnull(_ len: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>

// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
// CHECK-NEXT: @lifetime(copy p)
// CHECK-NEXT: @lifetime(p: copy p)
// CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ len: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func nullUnspecified(_ len: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>

// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
// CHECK-NEXT: @lifetime(copy p)
// CHECK-NEXT: @lifetime(p: copy p)
// CHECK-NEXT: @_alwaysEmitIntoClient public func nullable(_ len: Int32, _ p: inout MutableSpan<Int32>?) -> MutableSpan<Int32>?
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func nullable(_ len: Int32, _ p: inout MutableSpan<Int32>?) -> MutableSpan<Int32>?

// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
// CHECK-NEXT: @lifetime(copy p)
// CHECK-NEXT: @lifetime(p: copy p)
// CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func shared(_ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>

// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
// CHECK-NEXT: @lifetime(copy p)
// CHECK-NEXT: @lifetime(p: copy p)
// CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ len: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func simple(_ len: Int32, _ p: inout MutableSpan<Int32>) -> MutableSpan<Int32>


@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@inlinable
public func callComplexExpr(_ p: inout MutableSpan<CInt>) {
let _: MutableSpan<CInt> = complexExpr(73, 37, 42, &p)
let _: MutableSpan<CInt> = complexExpr(73, 37, &p)
}

@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
Expand All @@ -80,7 +86,7 @@ public func callNullable(_ p: inout MutableSpan<CInt>?) {
@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@inlinable
public func callShared(_ p: inout MutableSpan<CInt>) {
let _: MutableSpan<CInt> = shared(CInt(p.count), &p)
let _: MutableSpan<CInt> = shared(&p)
}

@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
Expand All @@ -94,3 +100,9 @@ public func callSimple(_ p: inout MutableSpan<CInt>) {
public func callNoncountedLifetime(_ p: UnsafeMutablePointer<CInt>) {
let _: MutableSpan<CInt> = noncountedLifetime(73, p)
}

@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
@inlinable
public func callConstant(_ p: inout MutableSpan<CInt>?) {
let _: MutableSpan<CInt>? = constant(&p)
}
Loading