Skip to content
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

Accessor macro executing wrong code #71070

Open
stephencelis opened this issue Jan 22, 2024 · 4 comments
Open

Accessor macro executing wrong code #71070

stephencelis opened this issue Jan 22, 2024 · 4 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. macro expansions Feature → expressions: Macro expansion expressions swift macro Feature → declarations: Swift `macro` declarations

Comments

@stephencelis
Copy link
Contributor

stephencelis commented Jan 22, 2024

Description

We've implemented a macro similar to @ObservationTracked that swaps out a stored property for accessors that call down to some private storage. Much to my surprise, though, that private storage is not being called.

See attached for repro: MyMacro.zip

Reproduction

Macro plugin:

import SwiftCompilerPlugin
import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftSyntaxMacros

public struct MyMacroMacro: AccessorMacro, PeerMacro {
  public static func expansion(
    of node: AttributeSyntax,
    providingAccessorsOf declaration: some DeclSyntaxProtocol,
    in context: some MacroExpansionContext
  ) throws -> [AccessorDeclSyntax] {
    guard
      let property = declaration.as(VariableDeclSyntax.self),
      let binding = property.bindings.first,
      let identifier = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier.trimmed
    else {
      return []
    }
    return [
      """
      @storageRestrictions(initializes: _\(raw: identifier))
      init(initialValue) {
      _\(identifier) = initialValue
      }
      """,
      """
      get {
      _\(identifier)
      }
      """,
      """
      set {
      _\(identifier) = newValue
      }
      """,
    ]
  }

  public static func expansion(
    of node: AttributeSyntax,
    providingPeersOf declaration: some DeclSyntaxProtocol,
    in context: some MacroExpansionContext
  ) throws -> [DeclSyntax] {
    guard
      let property = declaration.as(VariableDeclSyntax.self),
      let binding = property.bindings.first,
      let identifier = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier.trimmed
    else {
      return []
    }
    return [
      """
      private var _\(identifier): () -> Bool = { fatalError() }
      """
    ]
  }
}

@main
struct MyMacroPlugin: CompilerPlugin {
  let providingMacros: [Macro.Type] = [
    MyMacroMacro.self,
  ]
}

Library:

@attached(accessor, names: named(init), named(get), named(set))
@attached(peer, names: arbitrary)
public macro MyMacro() =
  #externalMacro(module: "MyMacroMacros", type: "MyMacroMacro")

Executable:

import MyMacro

struct Foo {
  @MyMacro
  var bar: () -> Bool = { false }
}

let foo = Foo()
print(foo.bar())

What the above should expand to:

image

Expected behavior

I expect foo.bar() to crash in the executable because @MyMacro has swapped var bar for a getter that invokes _bar, which is a member that defaults to calling fatalError().

Instead, I get false printed to the console, which shows that Swift is somehow invoking the original storage.

Environment

swift-driver version: 1.87.3 Apple Swift version 5.9.2 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5)
Target: arm64-apple-macosx14.0

Additional information

No response

@stephencelis stephencelis added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels labels Jan 22, 2024
@stephencelis
Copy link
Contributor Author

@DougGregor I found this bug quite surprising.

@stephencelis
Copy link
Contributor Author

Seems related to swiftlang/swift-syntax#2310

@stephencelis
Copy link
Contributor Author

Is this on anyone's radar?

@stephencelis
Copy link
Contributor Author

This is still a problem in Xcode 16 / Swift 6. /cc @hborla @rxwei

@hborla hborla added swift macro Feature → declarations: Swift `macro` declarations macro expansions Feature → expressions: Macro expansion expressions and removed triage needed This issue needs more specific labels labels Jun 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. macro expansions Feature → expressions: Macro expansion expressions swift macro Feature → declarations: Swift `macro` declarations
Projects
None yet
Development

No branches or pull requests

2 participants