swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.27k stars 10.33k forks source link

Attaching macros to a type messes up with Equatable/Comparable conformance synthesis #72040

Open Malien opened 6 months ago

Malien commented 6 months ago

Not completely sure this is a bug report or a feature request. Don't think there is a spec for this case.

Motivation

Imagine attaching a dummy @attached(member) macro Dummy() = #externalMacro(...) macro to a type. A macro does literally nothing, aka here's it's implementation:

public struct DummyMacro: MemberMacro {
  public static func expansion(
    of node: AttributeSyntax,
    providingMembersOf declaration: some DeclGroupSyntax,
    conformingTo protocols: [TypeSyntax],
    in context: some MacroExpansionContext
  ) throws -> [DeclSyntax] {
      []
  }
}

Attaching a macro messes up the ability to declare conformance to Equatable to the types where Equatable conformance cannot be synthesised automatically (like for e.g. tuples, which still cannot conform to protocols):

// This behaves as expected
struct Foo: Equatable {
  var bar: (Int, Int)

  static func == (lhs: Self, rhs: Self) -> Bool { lhs.bar == rhs.bar }
}

@Dummy()
struct FooToo: Equatable { // Type 'FooToo' does not conform to protocol 'Equatable'
  var bar: (Int, Int)

  static func == (lhs: Self, rhs: Self) -> Bool { lhs.bar == rhs.bar }
}

Of course one can declare Equatable conformance as an extension on FooToo, but this is not an ergonomic solution for my case.

I am implementing a StaticArray macro, to generate C-like fixed sized array, while there are still uncertainties in fixed-size arrays being introduced to the swift language.

Since tuples don't conform to Equatable, I'd like to synthesize an implementation, only for the cases where user declared that they desire the conformance (and presumably have proved that the inner type is Equatable as well):

@StaticArray<UInt8>(count: 4)
struct IPv4: Equatable { }
// ^ Synthesize `static func ==(lhs:, rhs:)` as a part of macro expansion

As stated above, compiler ignores any manual conformance to the Equatable inside of the struct's body.

Proposed solution

Allow manual Equatable/Comparable/Hashable conformance inside of the type's definition, when attaching macros.

...or make tuples conform to Equatable/Comparable/Hashable

...or make tuples to conform to any protocol

...or implement fixed-size arrays into the language, rendering my efforts of backporting the feature redundant

Alternatives considered

No response

Additional information

No response

KeithBauerANZ commented 6 months ago

This may be related to https://github.com/apple/swift/issues/68683