@@ -88,6 +88,9 @@ struct CxxSpan: ParamInfo {
8888 return CxxSpanThunkBuilder ( base: base, index: i - 1 , signature: funcDecl. signature,
8989 typeMappings: typeMappings, node: original, nonescaping: nonescaping)
9090 case . return:
91+ if dependencies. isEmpty {
92+ return base
93+ }
9194 return CxxSpanReturnThunkBuilder ( base: base, signature: funcDecl. signature,
9295 typeMappings: typeMappings, node: original)
9396 case . self :
@@ -125,7 +128,7 @@ struct CountedBy: ParamInfo {
125128 return CountedOrSizedReturnPointerThunkBuilder (
126129 base: base, countExpr: count,
127130 signature: funcDecl. signature,
128- nonescaping: nonescaping, isSizedBy: sizedBy)
131+ nonescaping: nonescaping, isSizedBy: sizedBy, dependencies : dependencies )
129132 case . self :
130133 return base
131134 }
@@ -184,11 +187,13 @@ func getTypeName(_ type: TypeSyntax) throws -> TokenSyntax {
184187 }
185188}
186189
187- func replaceTypeName( _ type: TypeSyntax , _ name: TokenSyntax ) -> TypeSyntax {
190+ func replaceTypeName( _ type: TypeSyntax , _ name: TokenSyntax ) throws -> TypeSyntax {
188191 if let memberType = type. as ( MemberTypeSyntax . self) {
189192 return TypeSyntax ( memberType. with ( \. name, name) )
190193 }
191- let idType = type. as ( IdentifierTypeSyntax . self) !
194+ guard let idType = type. as ( IdentifierTypeSyntax . self) else {
195+ throw DiagnosticError ( " unexpected type \( type) with kind \( type. kind) " , node: type)
196+ }
192197 return TypeSyntax ( idType. with ( \. name, name) )
193198}
194199
@@ -264,6 +269,10 @@ func transformType(_ prev: TypeSyntax, _ generateSpan: Bool, _ isSizedBy: Bool)
264269 if let impOptType = prev. as ( ImplicitlyUnwrappedOptionalTypeSyntax . self) {
265270 return try transformType ( impOptType. wrappedType, generateSpan, isSizedBy)
266271 }
272+ if let attrType = prev. as ( AttributedTypeSyntax . self) {
273+ return TypeSyntax (
274+ attrType. with ( \. baseType, try transformType ( attrType. baseType, generateSpan, isSizedBy) ) )
275+ }
267276 let name = try getTypeName ( prev)
268277 let text = name. text
269278 let isRaw = isRawPointerType ( text: text)
@@ -283,7 +292,7 @@ func transformType(_ prev: TypeSyntax, _ generateSpan: Bool, _ isSizedBy: Bool)
283292 if isSizedBy {
284293 return TypeSyntax ( IdentifierTypeSyntax ( name: token) )
285294 }
286- return replaceTypeName ( prev, token)
295+ return try replaceTypeName ( prev, token)
287296}
288297
289298protocol BoundsCheckedThunkBuilder {
@@ -485,8 +494,9 @@ struct CountedOrSizedReturnPointerThunkBuilder: PointerBoundsThunkBuilder {
485494 public let signature : FunctionSignatureSyntax
486495 public let nonescaping : Bool
487496 public let isSizedBy : Bool
497+ public let dependencies : [ LifetimeDependence ]
488498
489- var generateSpan : Bool = false // needs more lifetime information
499+ var generateSpan : Bool { !dependencies . isEmpty }
490500
491501 var oldType : TypeSyntax {
492502 return signature. returnClause!. type
@@ -504,9 +514,14 @@ struct CountedOrSizedReturnPointerThunkBuilder: PointerBoundsThunkBuilder {
504514
505515 func buildFunctionCall( _ pointerArgs: [ Int : ExprSyntax ] ) throws -> ExprSyntax {
506516 let call = try base. buildFunctionCall ( pointerArgs)
517+ let startLabel = if generateSpan {
518+ " _unsafeStart "
519+ } else {
520+ " start "
521+ }
507522 return
508523 """
509- \( raw: try newType) (start : \( call) , count: Int( \( countExpr) ))
524+ \( raw: try newType) ( \( raw : startLabel ) : \( call) , count: Int( \( countExpr) ))
510525 """
511526 }
512527}
@@ -1102,6 +1117,11 @@ public struct SwiftifyImportMacro: PeerMacro {
11021117 }
11031118 }
11041119 try checkArgs ( parsedArgs, funcDecl)
1120+ parsedArgs. sort { a, b in
1121+ // make sure return value cast to Span happens last so that withUnsafeBufferPointer
1122+ // doesn't return a ~Escapable type
1123+ ( a. pointerIndex != . return && b. pointerIndex == . return) || paramOrReturnIndex ( a. pointerIndex) < paramOrReturnIndex ( b. pointerIndex)
1124+ }
11051125 let baseBuilder = FunctionCallBuilder ( funcDecl)
11061126
11071127 let skipTrivialCount = hasTrivialCountVariants ( parsedArgs)
0 commit comments