# Attached macro adding arbitrary conformance

**URL:** <https://forums.swift.org/t/attached-macro-adding-arbitrary-conformance/77426>\
**Category:** Using Swift\
**Tags:** macros, attached-macros, swift-macro, extension-macros\
**Created:** [January 24, 2025, 3:00pm UTC](https://forums.swift.org/t/attached-macro-adding-arbitrary-conformance/77426 "2025-01-24T15:00:31Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jomy10](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jomy10/32/28879_2.png) [@Jomy10](https://forums.swift.org/u/Jomy10)\
**Post date:** [January 24, 2025, 3:00pm UTC](https://forums.swift.org/t/attached-macro-adding-arbitrary-conformance/77426/1 "2025-01-24T15:00:31Z")

</div>

I am wondering if I can write something like the following:

```swift
protocol MyProtocol {
  var a: String { get }
}

@Wrapper(MyProtocol.self)
struct MyStruct {
  var inner: any MyProtocol
}

let instance = MyStruct(inner: /*imagine a value here*/)

print(instance.a)

```

What I want to achieve is for a struct to contain a value that conforms to a protocol and have a macro that will implement the protocol for the struct, calling the methods on the `inner` object.

Is it possible to write a generic macro for this which takes the protocol as an argument? Can I write an extension macro that will output conformance to an arbitrary protocol?

Is it then possible to get the field declarations of the protocol in my macro definition?

---

<div class="post-metadata">

**Author:** ![SimplyDanny](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/simplydanny/32/25114_2.png) [@SimplyDanny](https://forums.swift.org/u/SimplyDanny)\
**Post date:** [January 28, 2025, 8:37pm UTC](https://forums.swift.org/t/attached-macro-adding-arbitrary-conformance/77426/2 "2025-01-28T20:37:48Z")

</div>

That's currently not possible with macros. You can pass the name of the protocol to the macro, but within its implementation there is no way to access the declaration of the protocol. Imagine it being imported from another module ... But even in the same file, the implementation has no way to access context outside of the declaration it was attached to.

---

<div class="post-metadata">

**Author:** ![LiarPrincess](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/liarprincess/32/22594_2.png) [@LiarPrincess](https://forums.swift.org/u/LiarPrincess)\
**Post date:** [February 4, 2025, 3:39pm UTC](https://forums.swift.org/t/attached-macro-adding-arbitrary-conformance/77426/3 "2025-02-04T15:39:02Z")

</div>

# Macros

You may not be able to attach macro to the wrapper, but you can attach the macro to the `protocol`. This is how [swift-spyable](https://github.com/Matejkob/swift-spyable) by @Matejkob works. You write:

```swift
@Spyable
public protocol ServiceProtocol {
  var name: String { get }
  func fetchConfig(arg: UInt8) async throws -> [String: String]
}

```

It generates:

```swift
public class ServiceProtocolSpy: ServiceProtocol {
  public var name: String {
    get { underlyingName }
    set { underlyingName = newValue }
  }
  public var underlyingName: (String)!

  // And so on…
}

```

So, technically what you are asking is possible, and you even have a pretty big code base to _inspire_ you. That said macros would not be my 1st choice for this kind of functionality. Enter the…

# Sourcery

(I'm not affiliated with @krzysztofzablocki, I just really like this repo.)

Macros have tons of problems with compilation times and they involve "virtual" code - code that you can't debug or add to source control.

[Sourcery](https://github.com/krzysztofzablocki/Sourcery) lets you generate the code and store it in a file, just like any other code. No compilation time cost, it is just a normal Swift code.

I will use the spy/mock example here, so you can compare it with [swift-spyable](https://github.com/Matejkob/swift-spyable) from the above. You write:

```swift
// sourcery: generate-fake
protocol FileSystem: Sendable {
  /// Current working directory.
  var cwd: String { get }
}

```

This is processed by the Sourcery using your template:

```swift
@testable import YourModule

{% for type in types.protocols where type|annotated:"generate-fake" %}
class {{ type.name }}Fake: {{ type.name }}, @unchecked Sendable {

  {%- for variable in type.allVariables|!definedInExtension %}
  // Do some stuff for every property.
  {% endfor %}

  {%- for method in type.allMethods|!definedInExtension %}
  // Do some stuff for every method.
  {% endfor %}
}
{% endfor %}

```

This will generate the following file (that you can check into your source control!):

```swift
class FileSystemFake: FileSystem, @unchecked Sendable {

  /// Always return this value.
  var cwdResult: String?
  /// Return specified values in succession.
  var cwdResults = [String]()
  private var cwdResultsIndex = 0
  /// How many times was this property called?
  var cwdCallCount = 0

  var cwd: String {
    self.cwdCallCount += 1

    if let r = self.cwdResult { return r }

    if self.cwdResultsIndex < self.cwdResults.count {
      let r = self.cwdResults[self.cwdResultsIndex]
      self.cwdResultsIndex += 1
      return r
    }

    fatalError("FileSystemFake.cwd - missing mock")
  }
}

```

If you are an iOS dev then I highly recommend looking at [SwiftGen](https://github.com/SwiftGen/SwiftGen) to automate assets/colors/fonts/localization. Very similar to Sourcery.

# Other

One minor thing is that when writing `struct Wrapper: MyProtocol` you need to store an `inner: MyProtocol` instance. You can store it as `any MyProtocol`, but that may involve an [existential container](https://github.com/swiftlang/swift/blob/main/docs/ABIStabilityManifesto.md#existential-containers) ([TypeLayout -\> existential-container-layout](https://github.com/swiftlang/swift/blob/main/docs/ABI/TypeLayout.rst#existential-container-layout)).

In theory it may be better to make the wrapper generic (`struct Wrapper<Inner: MyProtocol> { let inner: Inner }`). Then you would have to use `some MyProtocol`. This is basically a way of saying: "I'm too lazy so spell the whole type, but the compiler knows it".

The big downside is that you will always need `some` concrete type, which can get a bit annoying, and the performance gains would be miniscule (unless you are writing the next SwiftUI that needs to be refreshed at 120Hz).

---

<div class="post-metadata">

**Author:** ![LiarPrincess](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/liarprincess/32/22594_2.png) [@LiarPrincess](https://forums.swift.org/u/LiarPrincess)\
**Post date:** [February 4, 2025, 3:41pm UTC](https://forums.swift.org/t/attached-macro-adding-arbitrary-conformance/77426/4 "2025-02-04T15:41:31Z")

</div>

Btw. You may want too look at this thread: [Can swift macro create separate implementation of a declaration?](https://forums.swift.org/t/can-swift-macro-create-separate-implementation-of-a-declaration/65397/8)

---

<div class="post-metadata">

**Author:** ![Jomy10](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jomy10/32/28879_2.png) [@Jomy10](https://forums.swift.org/u/Jomy10)\
**Post date:** [February 5, 2025, 10:15am UTC](https://forums.swift.org/t/attached-macro-adding-arbitrary-conformance/77426/5 "2025-02-05T10:15:17Z")

</div>

Thank you for that well-explained answer. I have used Sourcery in the past for a different project, indeed a good alternative.
