swift-syntax icon indicating copy to clipboard operation
swift-syntax copied to clipboard

makeUniqueName() produces tokens that cannot be used as closure arguments

Open grynspan opened this issue 2 years ago • 13 comments

Description

If I attempt to label closure arguments during macro expansion:

let arg0 = context.makeUniqueName("")
return """
{ \(arg0) in
  ...
}
"""

The compiler complains:

🛑 Inferred projection type 'Int' is not a property wrapper 🛑 Inferred projection type '() -> Int' is not a property wrapper

This means I can't reliably produce closure argument names, which is problematic if my macro expansion generates a closure and the macro is being used inside another closure:

@Test func foo() {
  let x = [2, 4, 6]
  x.forEach {
    #expect($0 % 2 == 0) // 🛑 Anonymous closure arguments cannot be used inside
                         // a closure that has explicit arguments; did you mean '$0'?
  }
}

Steps to Reproduce

See above.

grynspan avatar Oct 03 '23 12:10 grynspan

See also https://github.com/apple/swift/pull/68475

grynspan avatar Oct 03 '23 12:10 grynspan

~~I can repro with swift-DEVELOPMENT-SNAPSHOT-2023-10-02-a-osx, which I think means #68475 isn't a complete fix.~~ My mistake, I was using a different toolchain.

grynspan avatar Oct 03 '23 13:10 grynspan

Having a day here… :) The issue with the spurious error is fixed, but I still can't use makeUniqueName() to generate my labels.

grynspan avatar Oct 03 '23 13:10 grynspan

Tracked in Apple’s issue tracker as rdar://116402749

ahoppen avatar Oct 03 '23 15:10 ahoppen

Reduced reproducer

public struct StringifyMacro: ExpressionMacro {
  public static func expansion(
    of node: some FreestandingMacroExpansionSyntax,
    in context: some MacroExpansionContext
  ) -> ExprSyntax {
    guard let argument = node.argumentList.first?.expression else {
      fatalError("compiler bug: the macro does not have any arguments")
    }
    let arg0 = context.makeUniqueName("")
    return """
      { \(arg0) in
        return \(argument)
      }(1)
      """
  }
}

Usage

_ = #stringify(a + b)

Expands to the following, which doesn’t compile

_ = { $s17mac_adsfjlkClient33_E5FD3D533106409A33F51D71F9BB5B8CLl9stringifyfMf_7__localfMu_ in
  return a + b
}(1)

Reproducing Package

ahoppen avatar Oct 04 '23 17:10 ahoppen