# \[Pitch\] Conformance Builders

**URL:** <https://forums.swift.org/t/pitch-conformance-builders/46980>\
**Category:** Pitches\
**Tags:** protocols, macros, synthesis\
**Created:** [March 28, 2021, 6:40pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980 "2021-03-28T18:40:30Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![filip-sakel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/filip-sakel/32/8697_2.png) [@filip-sakel](https://forums.swift.org/u/filip-sakel)\
**Post date:** [March 28, 2021, 6:40pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/1 "2021-03-28T18:40:30Z")

</div>

# Conformance Builders

# Introduction

Swift currently provides two micro features: function builders and property wrappers. I propose that we introduce conformance builders for synthesizing protocol conformances on structs. Unlike other proposals, this proposal focuses solely on structs and doesn't try to address static reflection.

# Motivation

## Implementation Complexity of Compiler Synthesis

The compiler synthesizes implementations for standard-library protocols, such as `Hashable` and `Codable`. However, this introduces significant implementation complexity for a very narrow feature, that is not offered to libraries. This makes altering the synthesis behavior difficult for non-compiler developers.

## Synthesis for Library Authors

Synthesis is also useful for libraries, which often resort to less performant approaches, such as reflection, for auto-synthesis-like behavior on their protocols.

Furthermore, auto-synthesis from reflection restricts type safety and results in less informative diagnostics, only available at runtime. When, for example, `Hashable` synthesis is unavailable, the user is notified at compile-time and doesn't need to run their program to verify its validity.

## Lack of Synthesis for Regular Users

Libraries that utilize reflection usually rely on custom reflection code — not the built-in `Mirror` API — to minimize the performance penalties of reflection and to access more powerful APIs. This is not an option for small-scale libraries or regular users who need auto-synthesis, leading to boilerplate.

Boilerplate, of course, is prone to errors, pollutes the call-site, hinders code maintainability, and can, accidentally, lead to less performant implementations.

# Proposed Design

I propose that we introduce conformance builders, as a well-defined, static, and type-safe feature for declaring explicit and implicit synthesis for protocol conformances.

Declaring a conformance builder requires a type marked `@conformanceBuilder(of:)` with the protocol targeted for synthesis specified in the attribute. This type must provide an `init(root:properties)` initializer, which is used for passing an instance of the synthesized type and key paths to its properties. Additionally, the conformance builder type can satisfy slightly altered requirements of the target protocol for which it offers synthesized implementations.

As for the application of conformance builders, a custom attribute is offered, which can be used to either declare them as implicit or explicit. For implicit application, the conformance builder custom attribute is applied to the protocol to be auto-synthesized. For explicit synthesis, the custom attribute is applied to the conformance declaration of a struct.

Implicit conformance builders can be overridden by explicit ones, and all synthesized requirements, provided by conformance builders, can be overridden by the conforming type itself.

Here's an example using SwiftUI's `View` and `DynamicProperty` protocols.

```swift

@conformanceBuilder(of: View)
struct ViewConformanceBuilder<Root> { ... }

@ViewConformanceBuilder
protocol View {
  // Some hidden requirements...

  static var _dynamicProperties(
    instance: Self
  ) -> [KeyPath<Self, DynamicProperty>]

  associatedtype Body: View 
  @ViewBuilder var body: Body { get }
}

struct ContentView: View {
  var body: some View {
    Text("Hello world!")
  }
}

```

# Detailed Design

## Semantics

### **Conformance-Builder Type**

The `@conformanceBuilder(of:)` attribute only accepts protocols in its parameter and can be applied to both structs and enums.

Furthermore, a conformance builder is required to:

1. satisfy at least one "adjusted" requirement of the protocol it builds conformances to (as described below);
2. provide one or more initializers of the form `init(root:properties:)`, with the access level of the conformance builder, and a variadic `properties` parameter (or multiple parameters after `properties`, or a combination of the two) where all accept values are of type `AnyKeyPath` (and any of its subclasses).

**Adjusted Requirement**

Adjusted requirements are all the non-type requirements taken from the protocol the conformance-builder targets, where `Self` is substituted by the branch builder type, whose generic parameters are inferred as described below.

### **Implicit Conformance-Builder Requirements**

Conformance builders must be unambiguous. This means, that their generic parameters must either be fixed — via a same-type constraint or by being specified in the custom attribute — or used in their significant initializers. Additionally, synthesis of protocol composition is not currently allowed.

> **Rationale: Implicitly synthesized protocols provide no means for the user to disambiguate by specifying the conformance builder's generic parameter, through its custom attribute; hence, it is required to be unambiguous.**

### **Application**

Applying two or more same-protocol conformance builders a declaration is prohibited. Furthermore, the conformance-builder custom attribute can only be applied to _protocols_, to indicate implicit synthesis, and to _struct conformance declarations_, for explicit synthesis.

## Type Inference

Type inference may be used to determine: the generic parameters of the significant initializers; or the generic parameters of the conformance-builder type.

To determine the generic parameters of the initializer, the compiler will start by taking the conformance-builder type with any attributes specified on the custom attribute; then, it will call the initializer of this type. The initializer will be passed `self` in its `root` parameter and the stored property key paths for `properties` and the following parameters. After that, the compiler will use the regular type-inference procedure for function calls to determine the generic parameters of the initializer.

To determine the concrete conformance-builder type, the compiler will follow the above process with a pseudo `Self` instance, and use the inferred and concrete conformance-builder type for requirements with `Self` in a covariant position, and for static requirements.

## Synthesizing Witnesses

In conformance synthesis, the compiler will only synthesize the protocol requirements that the conformance builder has satisfied in their adjusted form, and omit any requirements witnessed by the conforming-struct. In particular, the synthesized members will, first, be transformed to a recursive form, and then replaced so as to transform any `Self` or `self` references and parameters.

### Example:

```swift
@conformanceBuilder(of: Equatable)
struct VectorEquatableBuilder<Root, E1: Equatable, E2: Equatable> { ... }

struct Vector: @VectorEquatableBuilder Equatable {
  let x, y: Double
}

// ——————————————————— Transforms to ⬇️ ——————————————————— \\

struct Vector: Equatable {
  let x, y: Double

  static func == (lhs: Self, rhs: Self) {
    lhs == rhs // The parameters 'lhs' and 'rhs' are of type 'Self'. 
  }
}

// ——————————————————— Transforms to ⬇️ ——————————————————— \\
struct Vector: Equatable {
  let x, y: Double

  static func == (lhs: Self, rhs: Self) {
    VectorEquatableBuilder(root: lhs, properties: \Self.x, \Self.y) ==
    VectorEquatableBuilder(root: rhs, properties: \Self.x, \Self.y) 
  }
}

```

## Diagnostics

### Too Many or Too Little Properties

Some conformance builders may require a minimum or a maximum number of parameters. This is communicated to the compiler by the significant initializers, that — through overloads or variadic parameters — offer a certain number of available properties for their generic constraints. The compiler will understand and diagnose that with an appropriate error:

```swift
@conformanceBuilder(of: Equatable)
struct VectorEquatableBuilder<Root, E1: Equatable, E2: Equatable> { ... }

struct Vector3D: @VectorEquatableBuilder Equatable {
  // ❌ 'VectorEquatableBuilder' can't synthesize  
  // 'Equatable' conformance for struct with 3 properties. 

  let x, y, z: Double 
}

```

### Non-satisfied Constraints of Property Key Paths

There are, also, cases wherein the compiler can't find an overload for the generic constraints imposed on the conformance builder. In these cases, the compiler will inform the user about these constraints through notes, and emit an error at the conformance declaration:

```swift
struct MyNumber {
  ... 
}

struct Vector: @VectorEquatableBuilder Equatable {
  // ❌ 'VectorEquatableBuilder' can't synthesize
  // 'Equatable' conformance. 

  let x: MyNumber // ℹ️ 'MyNumber' does not conform to 'Equatable'
  let y: MyNumber // ℹ️ 'MyNumber' does not conform to 'Equatable'            
}

```

# Alternatives Considered

## Ban Synthesis for Structs containing Class or Unsafe Types

Structs whose properties may cause problems for the synthesized implementations can opt-out by offering their own implementations. Furthermore, some users may utilize immutable classes that do not require special implementations. As for the case of unsafe code, users utilizing it should be aware of its effects, and cautious when using synthesized implementations; nevertheless, unsafe code is often wrapped in safe container types to avoid such problems.

# Future Directions

## Options in Conformance Builder Attributes

Currently, conformance builders can only alter the synthesis behavior of a given conformance builder through their generic parameters; this approach is quite limited. To address this, we could ease the restriction that mandates that the initializer receive just one property, and use any parameters before `root` as option parameters — similar to arguments on property-wrapper custom attributes.

```swift
@conformanceBuilder(of: Identifiable) 
struct TargetedID<Root, ID> {
  let id: KeyPath<Root, ID>, root: Root // No properties are allowed here.

  var id: ID { root[keyPath: id] }
}

struct User: @TargetedID(id: \.userID) Identifiable {
  let name: String
  let userID: UUID
}

```

## Stateful Conformance Builders

Protocols are not allowed to declare stored properties. However, with stateful conformance builders, we could alleviate some boilerplate associated with specifying stored properties by hand:

```swift
@conformanceBuilder(of: Identifiable, attributes: stateful) 
struct UUIDIdentifiable<Root: Identifiable> where Root.ID == UUID {
  let root: Root, let id = UUID()
}

struct User: @UUIDIdentifiable Identifiable {
  let name: String
}

// ——————————————————— Transforms to ⬇️ ——————————————————— \\

struct User: Identifiable {
  let name: String
	
  // The conformance builder is stored.
  let __Identifiable_proxy: UUIDIdentifiable<Self> = UUIDIdentifiable(root: self)

  var id: UUID {
    __Identifiable_proxy.id
  }
}

```

## Mutable Root

The proposed solution doesn't offer a way to satisfy `mutating` requirements, as `root` can't automatically mutate `self`, due to conformance builders' value semantics. This can be quite limiting and certain situations, and could be addressed by introducing mutable conformance builders:

```swift
@conformanceBuilder(of: IteratorProtocol, attributes: mutable)
struct ForwardedIterator<
	Root: IteratorProtocol, 
	Iterator: IteratorProtocol
> where Iterator.Element == Root.Element {
	var root: Root
	let properties: WritableKeyPath<Root, Iterator>

	mutating func next() -> Root.Element? {
		root[keyPath: properties].next()
  }
}

struct IteratorWrapper<Iterator: IteratorProtocol>: @ForwardedIterator IteratorProtocol {
	var _iterator: Iterator
}

// ——————————————————— Transforms to ⬇️ ——————————————————— \\

struct IteratorWrapper<Iterator: IteratorProtocol>: @ForwardedIterator IteratorProtocol {
  var _iterator: Iterator

  mutating func next() -> Root.Element? {
    let proxy = ForwardedIterator(root: self, properties: \Self._iterator)
    defer { self = proxy.root }

    return proxy.next()
  }
}

```

## Conformance Builders for Enumerations

Enums, like structs, can conform to protocols, and mainstream protocols, such as `Codable`, synthesize enum conformances. This could be expanded to conformance builder, by first introducing a standard-library union type, such as `Either`:

```swift
enum Either<First, Second> {
  case first(First), second(Second)
}

```

With an `Either` type, we can allow conformance builders to declare an `init(root:cases:)` initializer to indicate support for enum conformance-building:

```swift
extension Either: Encodable where 
  First: Encodable, Second: Encodable { ... }

@conformanceBuilder(of: Encodable)
struct EncodableBuilder<Root> {
  private let encodable: Encodable

  init<A: Encodable>(root: Root, cases case: A) {
    encodable = case
  }

  init<A: Encodable, B: Encodable>(root: Root, cases: Either<A, B>) {
    encodable = cases
  }

  func encode(to encoder: Encoder) throws {
    encodable.encode(to: encoder)
  }
}

enum Input: @EncodableBuilder Encodable {
  case number(Double), text(String)
}

// ——————————————————— Transforms to ⬇️ ——————————————————— \\

enum Input: Encodable {
  case number(Double), text(String)

  func encode(to encoder: Encoder) throws {
    let either: Either<Double, String>

    switch either {
      case let .number(value): either = .first(value)
      case let .text(value): either = .second(value)
    }

    return EncodableBuilder(root: self, cases: either).encode(to: encoder)
  }
}

```

Some design concerns will, first, need to be resolved. Firstly, it is unclear whether struct- and enum-builders should be mandated to be declared as different types. Secondly, it is unclear whether `Either` is the best solution for our problems, which could perhaps be better solved by variadic generics. Nonetheless, enum conformance-building seems like a straightforward extension to this feature.

### Your thoughts

I am really interested to hear what you think of this proposal! All feedback is welcome.

---

<div class="post-metadata">

**Author:** ![masters3d](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@masters3d](https://forums.swift.org/u/masters3d)\
**Post date:** [March 28, 2021, 7:03pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/2 "2021-03-28T19:03:55Z")

</div>

Could you explain what the main differences are between this approach and [Automatic Requirement Satisfaction in plain Swift](https://forums.swift.org/t/automatic-requirement-satisfaction-in-plain-swift/37158) using a Structural protocol? Safe to say that the original authors of that proposal will not be pushing for that design due to Google Brain's decision to deprioritize that work but I am curious if any of their ideas can be pulled into you current pitch since from the surface seems to address the same problem.

---

<div class="post-metadata">

**Author:** ![masters3d](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@masters3d](https://forums.swift.org/u/masters3d)\
**Post date:** [March 28, 2021, 7:11pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/3 "2021-03-28T19:11:23Z")

</div>

In addition I would love to see something about the problem of [Scoped Conformances](https://forums.swift.org/t/scoped-conformances/37159) in the future directions.

---

<div class="post-metadata">

**Author:** ![masters3d](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@masters3d](https://forums.swift.org/u/masters3d)\
**Post date:** [March 28, 2021, 7:29pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/4 "2021-03-28T19:29:25Z")

</div>

> [@filip-sakel](#):
>
> ```swift
> enum MyEnum: @EncodableBuilder Encodable {
> case first, second
> }
> 
> // ——————————————————— Transforms to ⬇️ ——————————————————— \\
> 
> enum Input: Encodable {
> case number(Double), text(String)
> 
> func encode(to encoder: Encoder) throws {
> let either: Either<Double, String>
> 
> switch either {
> case let .number(value): either = .first(value)
> case let .text(value): either = .second(value)
> }
> 
> return EncodableBuilder(root: self, cases: either).encode(to: encoder)
> }
> }
> 
> ```

Im having trouble understanding this. MyEnum does not have payload but it transforms to Input enum with payloads? Maybe I am missing original Input enum?

---

<div class="post-metadata">

**Author:** ![filip-sakel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/filip-sakel/32/8697_2.png) [@filip-sakel](https://forums.swift.org/u/filip-sakel)\
**Post date:** [March 28, 2021, 9:24pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/5 "2021-03-28T21:24:29Z")

</div>

> [@masters3d](#):
>
> Could you explain what the main differences are between this approach and [Automatic Requirement Satisfaction in plain Swift](https://forums.swift.org/t/automatic-requirement-satisfaction-in-plain-swift/37158)

Good point! I am aware of that proposal, but as one author noted "[the proposal] aims to be an equivalent of _static_ or _compile-time_ reflection" in [a post](https://forums.swift.org/t/automatic-requirement-satisfaction-in-plain-swift/37158/18) of the pitch thread. Instead, this proposal aims to tackle a very specific case: conformance synthesis for structs. The other proposal also supports enums and takes a very different approach altogether.

### ABI Impact

I will add a section about ABI impact and API resilience, but first I want to answer your question.

The proposal you linked to is based on a `Structural` protocol that enables auto-synthesis of an AST-like data structure. As a result, ABI is impacted by conforming to `Structural` and `structuralRepresentation` can be overridden — which isn't always desirable.

On the contrary, this proposal offers a compile-time feature, really similar to result builders; hence, it has no ABI impact or way to override the type structure passed to the macro.

### Diagnostics

A major criticism of the `Structural` proposal is the handling of diagnostics. Namely, The AST-like structure is quite "opaque". That is, the compiler can't really understand what property maps to which `StructuralProperty` after the construction of `structuralRepresentation`, leading to very limited diagnostics.

This proposal, however, is very similar to result builders, in terms of how properties and components, respectively, are passed into the micro features. Function builders have evolved dramatically from the developmental `@_functionBuilder` attribute and now provide substantial diagnostics. For example, we get relevant diagnostics when a component does not conform to a type or when the builder can't accept more parameters.

Likewise, result builders will hook into similar mechanisms for generating targeted diagnostics at compile-time, which can be informative and indicate directly which members prevent auto-synthesis — as is currently done for synthesized conformances.

### Representation

`StructuralCons` is constructed with the name of a property, its value, and boolean indicating its mutability. This isn't very expressive, in my opinion, not to mention that Swift has `KeyPath`, which is apt for representing properties.

Furthermore, with a key path returning a `String` path, as discussed [here](https://forums.swift.org/t/can-anykeypath-be-extended-to-provide-a-path-string/21569), `Encodable`, and perhaps `Decodable` with a future addition, could be implemented with conformance builders.

### Ergonomics

This proposal directly targets conformance synthesis and tries to simplify it as much as possible. Ergo, implicit conformances are a major design aspect of the proposal. Lastly, there is the custom conformance-builder attribute, which allows for flexibility in terms of the synthesis strategy (this is very useful for custom serialization, etc.).

* * *

> [@masters3d](#):
>
> Im having trouble understanding this. MyEnum does not have payload but it transforms to Input enum with payloads? Maybe I am missing original Input enum?

This was a typo, thanks for pointing it out!. The non-transformed enum is supposed to be:

```swift
enum Inputs: @EncodableBuilder Encodable {
  case number(Double), text(String)
}

```

---

<div class="post-metadata">

**Author:** ![filip-sakel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/filip-sakel/32/8697_2.png) [@filip-sakel](https://forums.swift.org/u/filip-sakel)\
**Post date:** [March 28, 2021, 9:27pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/6 "2021-03-28T21:27:18Z")

</div>

> [@masters3d](#):
>
> In addition I would love to see something about the problem of [Scoped Conformances](https://forums.swift.org/t/scoped-conformances/37159) in the future directions.

I think scoped conformances would be an incredibly useful future, if — of course — the implementation can be worked out, but I don't see how that relates to the pitched feature. Could you elaborate?

---

<div class="post-metadata">

**Author:** ![masters3d](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@masters3d](https://forums.swift.org/u/masters3d)\
**Post date:** [March 28, 2021, 11:31pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/7 "2021-03-28T23:31:50Z")

</div>

Ah got it. The automatic requirement satisfaction is a runtime feature vs conformance builders which is a compile time feature. For scoped conformances I was thinking this proposal might be related but now I see they are not.

Thanks for the detailed explanation.

---

<div class="post-metadata">

**Author:** ![kiel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kiel/32/1392_2.png) [@kiel](https://forums.swift.org/u/kiel)\
**Post date:** [March 29, 2021, 12:14am UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/8 "2021-03-29T00:14:35Z")

</div>

> [@filip-sakel](#):
>
> ```swift
> // ——————————————————— Transforms to ⬇️ ——————————————————— \\
> 
> struct Vector: Equatable {
> let x, y: Double
> 
> static func == (lhs: Self, rhs: Self) {
> lhs == rhs // The parameters 'lhs' and 'rhs' are of type 'Self'. 
> }
> }
> 
> // ——————————————————— Transforms to ⬇️ ——————————————————— \\
> struct Vector: Equatable {
> let x, y: Double
> 
> static func == (lhs: Self, rhs: Self) {
> VectorEquatableBuilder(root: lhs, members: \Self.x, \Self.y) ==
> VectorEquatableBuilder(root: rhs, members: \Self.x, \Self.y) 
> }
> }
> 
> ```

What'd the performance implications for change be? So for example, will stack usage grow for each property checked?

---

<div class="post-metadata">

**Author:** ![George](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/george/32/37757_2.png) [@George](https://forums.swift.org/u/George)\
**Post date:** [March 29, 2021, 9:32pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/9 "2021-03-29T21:32:45Z")

</div>

The main thing this pitch gets right is using method overloading instead of types to express structural concepts ("more like result builders"). However, solving these use-cases one by one can lead to significant complexity in the language, as opposed to implementing a single mechanism for the more general concept of static structural reflection (which I mentioned in [this thread](https://forums.swift.org/t/serialization-in-swift/46641/15)).

Here are some thoughts about what a more general solution might look like:

> [@filip-sakel](#):
>
> The proposal you linked to is based on a `Structural` protocol that enables auto-synthesis of an AST-like data structure. As a result, ABI is impacted by conforming to `Structural` and `structuralRepresentation` can be overridden — which isn't always desirable.

Being able to provide custom overrides to this type of functionality is very important in Swift, functionality designed using this type of mechanism should compose well with types using custom storage (for instance, Capnproto types, which have semantic stored properties but could customize the layout of those fields). Additionally, it is important that types know when changing their structural representation might affect their usage (otherwise even something as simple as changing the order of properties may have unintended consequences).

> `struct Vector: @VectorEquatableBuilder Equatable`

We don't currently have attributes on conformances, and I'm not sure that we need them to achieve this goal. `VectorEquatable` can simply refine `Equatable` and use structural reflection to achieve the desired affect:

```swift
/// This doesn't need any new semantics, just conformance to a special protocol
public protocol VectorEquatable: Equatable, Structural {
  public static func == (lhs: Self, rhs: Self) {
    // Not necessary the best API, just conveying the general idea
    @EquatableConformanceBuilder var comparator: EquatableConformanceBuilder<Self>.Comparator
    // Hopefully, this can be optimized by the compiler
    return comparator.components.allSatisfy { $0(lhs, rhs) }
  }
}

@structuralBuilder
public struct EquatableConformanceBuilder<U: Structural> {
  public struct Component {
    /// defined as a closure for simplicity, an ideal implementation should use a form that can be properly optimized
    let compare: (U, U) -> Bool
  }
  public static func buildProperty<T: Equatable>(_ keyPath: KeyPath<U, T>) -> Component {
     Component { lhs, rhs in lhs[keyPath: keyPath] == rhs[keyPath: keyPtah] }
  }
  public struct Comparator {
     let components: [Component]
  }
  public static func buildBlock(_ components: Component...) -> Comparator {
     return Comparator(components: components)
  }
}

```

So you would end up with something like:

```swift
struct Vector: VectorEquatable {
  let x, y: Double

  /// == conformance is synthesized from `VectorEquatable`
}

```

This would also synthesize the correct conformance for `Vector3D`, as opposed to what you mentioned in your proposal:

> ```swift
> struct Vector3D: @VectorEquatableBuilder Equatable {
> // ❌ 'VectorEquatableBuilder' can't synthesize  
> // 'Equatable' conformance for struct with 3 members. 
> 
> let x, y, z: Double 
> }
> 
> ```

In the case that a property doesn't match a method overload in the builder, you would get an error similar to what we have now for string interpolation.

---

<div class="post-metadata">

**Author:** ![masters3d](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@masters3d](https://forums.swift.org/u/masters3d)\
**Post date:** [March 30, 2021, 2:30am UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/10 "2021-03-30T02:30:48Z")

</div>

> [@George](#):
>
> We don't currently have attributes on conformances, and I'm not sure that we need them to achieve this goal.

We do as of SE-0302

---

<div class="post-metadata">

**Author:** ![George](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/george/32/37757_2.png) [@George](https://forums.swift.org/u/George)\
**Post date:** [March 30, 2021, 3:06am UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/11 "2021-03-30T03:06:50Z")

</div>

> [@masters3d](#):
>
> We do as of SE-0302

I might be missing something, are you referring to `@_marker`? That is an attribute on a protocol, not a specific conformance to that protocol.

---

<div class="post-metadata">

**Author:** ![masters3d](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@masters3d](https://forums.swift.org/u/masters3d)\
**Post date:** [March 30, 2021, 3:12am UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/12 "2021-03-30T03:12:24Z")

</div>

@unchecked [SE-0302 (second review): Sendable and sendable closures - #79 by masters3d](https://forums.swift.org/t/se-0302-second-review-sendable-and-sendable-closures/45253/79)

---

<div class="post-metadata">

**Author:** ![George](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/george/32/37757_2.png) [@George](https://forums.swift.org/u/George)\
**Post date:** [March 30, 2021, 2:45pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/13 "2021-03-30T14:45:26Z")

</div>

Ah right, missed that, thanks!

---

<div class="post-metadata">

**Author:** ![filip-sakel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/filip-sakel/32/8697_2.png) [@filip-sakel](https://forums.swift.org/u/filip-sakel)\
**Post date:** [March 30, 2021, 3:22pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/14 "2021-03-30T15:22:41Z")

</div>

> [@kiel](#):
>
> What'd the performance implications for change be? So for example, will stack usage grow for each property checked?

Sorry for the delayed response.

I'm not sure if you're referring to compilerer or compiled-code performance.

Compiler performance should be similar to that of function builders, as it uses methods to pass a type's properties into the conformance builder to synthesize conformances. I'll keep an eye on that as the feature progresses, but I don't think it will be a problem for now.

As for compiled-code performance, key-paths have very little (if any) performance impact on optimized builds. I made [this simple package](https://github.com/filip-sakel/ConformanceBuildersBenchmark) to test the performance of my `VectorEquatableBuilder` against custom and synthesized conformances. They all have the same execution time of 125ns on release builds. On some other not-so-reliable, preliminary benchmarks I found that key-paths on _debug_ builds have a performance penalty of about 41%.

---

<div class="post-metadata">

**Author:** ![filip-sakel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/filip-sakel/32/8697_2.png) [@filip-sakel](https://forums.swift.org/u/filip-sakel)\
**Post date:** [March 30, 2021, 4:27pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/15 "2021-03-30T16:27:20Z")

</div>

> [@George](#):
>
> However, solving these use-cases one by one can lead to significant complexity in the language, as opposed to implementing a single mechanism for the more general concept of static structural reflection

I agree that adopting narrowly scoped features is undesirable and unsustainable for Swift. However, static reflection is, in my opinion, too abstract to address in one proposal. Not to mention that, to my knowledge, there aren't very good solutions for problems like informative diagnostics, which — I think we can agree — are integral to conformance synthesis, and genuinely useful type safety.

> [@George](#):
>
> Being able to provide custom overrides to this type of functionality is very important in Swift, functionality designed using this type of mechanism should compose well with types using custom storage (for instance, Capnproto types, which have semantic stored properties but could customize the layout of those fields). Additionally, it is important that types know when changing their structural representation might affect their usage (otherwise even something as simple as changing the order of properties may have unintended consequences).

Couldn't property wrappers be used to alter the "structural representation", or did I miss something?

> [@George](#):
>
> We don't currently have attributes on conformances, and I'm not sure that we need them to achieve this goal. `VectorEquatable` can simply refine `Equatable` and use structural reflection to achieve the desired affect:

As @masters3d pointed out, we do, and I think they offer a pretty lightweight syntax for customizing conformance synthesis.

I'm not in favor of a special, compiler protocol for this type of functionality. For one, protocols impact ABI which is a major setback of `Structural`, and undesirable for a feature targeted as a macro feature to be widely used. To be fair, we could make `Structural` a marker protocol and then offer a standard-library:

```swift
func structuralRepresentation<T: Structural>(of type: T.Type) -> ...

```

function. However, that seems limited and still gives the compiler a hard time associating properties with errors.

> [@George](#):
>
> ```swift
> /// This doesn't need any new semantics, just conformance to a special protocol
> public protocol VectorEquatable: Equatable, Structural {
> public static func == (lhs: Self, rhs: Self) {
> // Not necessary the best API, just conveying the general idea
> @EquatableConformanceBuilder var comparator: EquatableConformanceBuilder<Self>.Comparator
> // Hopefully, this can be optimized by the compiler
> return comparator.components.allSatisfy { $0(lhs, rhs) }
> }
> }
> 
> ```

In the above example, I don't understand why you would need `Structural`. All the heavy-lifting seems to be up to `EquatableConformanceBuilder`. Did I miss something?

Could you comment on your choice of `@structuralBuilder`? I don't have strong feelings about the current name, but this attribute doesn't seem to offer much either in terms of expressiveness.

> [@George](#):
>
> ```swift
> @structuralBuilder
> public struct EquatableConformanceBuilder<U: Structural> {
> public struct Component {
> /// defined as a closure for simplicity, an ideal implementation should use a form that can be properly optimized
> let compare: (U, U) -> Bool
> }
> public static func buildProperty<T: Equatable>(_ keyPath: KeyPath<U, T>) -> Component {
> Component { lhs, rhs in lhs[keyPath: keyPath] == rhs[keyPath: keyPtah] }
> }
> public struct Comparator {
> let components: [Component]
> }
> public static func buildBlock(_ components: Component...) -> Comparator {
> return Comparator(components: components)
> }
> }
> 
> ```

I really like your idea of including `buildProperty` and `buildBlock`! I just wonder how `EquatableConformanceBuilder` would access an instance of type `U` (is it through the `@EquatableConformanceBuilder` custom attribute?).

When thinking about this feature, I struggled with how something like function builders' `buildExpression` (or `buildProperty` in your example), and `buildBlock` could be implemented. But now, based on your example, I thought of another, more intricate, model for conformance builders:

```swift
// The target-protocol is inferred by the conformance
// proxy returned by 'buildBlock'.
@conformanceBuilder
enum EquatableConformanceBuilder {
  // Of course, the name can be anything.
  struct PropertyRepresentation<Root> {
    let equalityCheck: (Root, Root) -> Bool
  }

  // We provide 'Root' for customizability.
  static func buildProperty<Root, E: Equtable>(
    _ keyPath: KeyPath<Root, E>,
    of _: Root
  ) -> PropertyRepresentation<Root> { 
    ...
  } 

  static func conformanceProxy<Root>(
    for root: Root,
     _ properties: PropertyRepresentation<Root>...
  ) -> Proxy<Root> {
    Proxy(root: root, properties: properties)
  }
}

extension EquatableConformanceBuilder {
  @conformanceProxy(of: Equatable)
  struct Proxy<Root> {
    let root: Root, properties: [EquatableConformanceBuilder.PropertyRepresentation<Root>]
 
    static func == (lhs: Self, rhs: Self) -> Bool { ... }
  }
}

```

An example:

```swift
struct Vector: @EquatableConformanceBuilder Equatable {
  let x, y: Double
}

// ——————————————————— Transforms to ⬇️ ——————————————————— \\

struct Vector: Equatable {
  let x, y: Double

  static func == (lhs: Self, rhs: Self) -> Bool {
    let lhs_proxy = EquatableConformanceBuilder.conformanceProxy(
      for: self,
      EquatableConformanceBuilder.buildProperty(\Self.x, of: self),
      EquatableConformanceBuilder.buildProperty(\Self.y, of: self),
    )

    let rhs_proxy = EquatableConformanceBuilder.conformanceProxy(
      for: self,
      EquatableConformanceBuilder.buildProperty(\Self.x, of: self),
      EquatableConformanceBuilder.buildProperty(\Self.y, of: self),
    )

    return lhs_proxy == rhs_proxy
  }
}

```

---

<div class="post-metadata">

**Author:** ![George](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/george/32/37757_2.png) [@George](https://forums.swift.org/u/George)\
**Post date:** [March 30, 2021, 5:43pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/16 "2021-03-30T17:43:29Z")

</div>

> [@filip-sakel](#):
>
> As @masters3d pointed out, we do, and I think they offer a pretty lightweight syntax for customizing conformance synthesis.

Sorry, I missed that this was added. Curious, given I was one of the folks that [brought up the rationale](https://forums.swift.org/t/pitch-3-concurrentvalue-and-concurrent-closures/43947/6) for it 😄. I would mention that `@unchecked` doesn't affect synthesized code, it just indicates that you know what you are doing to suppress an error.

> [@filip-sakel](#):
>
> Couldn't property wrappers be used to alter the "structural representation", or did I miss something?

How do you mean? The scenario I was referring to is something like a packed struct. For instance something with the following API:

```swift
struct CustomLayout {
  let x: Int8
  let y: Int16
  let z: Int8
}

```

but a memory layout of 8 bits of x, immediately followed by 16 bits of y, immediately followed by 8 bits of z, resulting in a 32 bit value. I'm pretty sure the Swift compiler would add padding in this case due to memory alignment, but this type should be representable in Swift _and_ be able to participate in structural reflection. I brought up Capnproto because this will be common in binary serialization formats like Capnp and Protobuf. This makes me think that a `Structural` protocol and a customization point for modifying its behavior is the right balance. On the other hand, I'm realizing that allowing arbitrary customization of this behavior could make it very difficult to optimize the resulting code.

> [@filip-sakel](#):
>
> Could you comment on your choice of `@structuralBuilder` ? I don't have strong feelings about the current name, but this attribute doesn't seem to offer much either in terms of expressiveness.

I basically picked it out of a hat. The only thing I wanted to convey was that it was for more than just building conformances.

> [@filip-sakel](#):
>
> `@conformanceProxy(of: Equatable)`

This bit of the system still feels very awkward and special-cased to me, as it basically gives us another flavor of `extension` but with new semantics and a different `self`. If all you need is the builder's product, we could just allow you to get at that with a statement (like my unfortunately-spelt `@EquatableConformanceBuilder var comparator: EquatableConformanceBuilder<Self>.Comparator`). This would also allow the same semantics to be used outside of synthesizing a conformance (for example, at the top level in a `main.swift`).

---

<div class="post-metadata">

**Author:** ![filip-sakel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/filip-sakel/32/8697_2.png) [@filip-sakel](https://forums.swift.org/u/filip-sakel)\
**Post date:** [April 2, 2021, 10:06pm UTC](https://forums.swift.org/t/pitch-conformance-builders/46980/17 "2021-04-02T22:06:28Z")

</div>

> [@George](#):
>
> but a memory layout of 8 bits of x, immediately followed by 16 bits of y, immediately followed by 8 bits of z, resulting in a 32 bit value. I'm pretty sure the Swift compiler would add padding in this case due to memory alignment, but this type should be representable in Swift _and_ be able to participate in structural reflection. I brought up Capnproto because this will be common in binary serialization formats like Capnp and Protobuf. This makes me think that a `Structural` protocol and a customization point for modifying its behavior is the right balance. On the other hand, I'm realizing that allowing arbitrary customization of this behavior could make it very difficult to optimize the resulting code.

I firmly support synthesis customizability so long as it is the control of the API author. I'm wary of clients modifying the `structuralRepresentation` requirement without a clear indication of unsafety. (For example, `@unchecked` indicates unsafety for certain `Sendable` conformances.)

> [@George](#):
>
> This bit of the system still feels very awkward and special-cased to me, as it basically gives us another flavor of `extension` but with new semantics and a different `self` . If all you need is the builder's product, we could just allow you to get at that with a statement (like my unfortunately-spelt `@EquatableConformanceBuilder var comparator: EquatableConformanceBuilder<Self>.Comparator` ). This would also allow the same semantics to be used outside of synthesizing a conformance (for example, at the top level in a `main.swift` ).

I think I better understand your concern now.

I thought about incorporating conformance builders with extensions quite a lot and I think that the goal is to combine Swift's nominal type-system constraints with structural constraints. For example, in the following code, we want our `Root` type to have an unspecified number (structural constraint) of `Equatable`-conforming ("nominal" constraint) properties:

```swift
@structureProjector 
enum EquatableStructure<Root> {
  static func buildProperty<E: Equatable>(
    root: Root, 
    keyPath: KeyPath<Root, E>
  ) -> AnyEquatable { ... }

  static func structureProxy(
    properties: AnyEquatable...
  ) -> [AnyEquatable] { ... }
}

```

Such constraints do not currently exist in Swift, but they would allow well-defined, type-safe static reflection and synthesis:

```swift
// The compiler offers this method:
extension EquatableStructure where Root: EquatableStructure {
  /// Returns the structure proxy for the given 'Root' instance.
  static func proxy(of root: Root) {
    // The compiler knows the structure of 'Root' and uses this structure
    // projector's methods to create and return a structure proxy.
  }
}

extension Equatable where Self: EquatableStructure { 
  // ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // This is a structural constraint on 'Self'.

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

```

In the `Vector` example, the compiler would create a proxy in `EquatableStructure<Vector>.proxy(of:)`:

```swift
struct Vector { let x, y: Double }

extension EquatableStructure where Root == Vector {
  static func proxy(of root: Vector) {
    structureProxy(
      buildProperty(root: root, \.x),
      buildProperty(root: root, \.y)
    )
  }
}

```

That would be possible since a type's satisfying a structural constraint entails adequate access level and the compiler's being fully aware of a given type's layout.

Now, to declare our synthesized conformance, we'll need to tell the compiler what structure conformance to check for:

```swift
extension Vector: @EquatableStructure Equatable {}

```

I hope that made sense. I am currently working on a second pitch that incorporates some of your feedback and these new "structural" constraints, where I will explain the new behavior in further detail.
