# State of the Memberwise Initializer

**URL:** <https://forums.swift.org/t/state-of-the-memberwise-initializer/17168>\
**Category:** Discussion\
**Created:** [October 19, 2018, 3:33am UTC](https://forums.swift.org/t/state-of-the-memberwise-initializer/17168 "2018-10-19T03:33:48Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alejandro](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alejandro/32/46197_2.png) [@Alejandro](https://forums.swift.org/u/Alejandro)\
**Post date:** [October 19, 2018, 3:33am UTC](https://forums.swift.org/t/state-of-the-memberwise-initializer/17168/1 "2018-10-19T03:33:48Z")

</div>

# State of the Memberwise Initializer

## Prolog

Hello Evolution,

I want to discuss where we are with the current memberwise initializer for structures and where I wish to see this initializer evolve.

Refer to [SE-0018](https://github.com/apple/swift-evolution/blob/master/proposals/0018-flexible-memberwise-initialization.md) and [SE-0018 Rationale](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160111/006469.html). I do not speak for the author here, but I'm rathering pulling ideas and references from SE-0018 to formulate this post.

_From here on out I'm going to refer to the memberwise initializer as MWI_

_Note that this is not technically a complete resurrection of SE-0018 because I will be stating my opinion on where we should go with the MWI._

_Also, forgive me for restraining myself from saying "State of the Memberwise Initializer Address"_

## What is this memberwise initializer?

For those that don't know what exactly the MWI is, at the most basic level, the MWI is just a special compiler synthesized initializer for structures.

Given:

```swift
struct Dog {
  var age: Int
  var name: String
}

```

The compiler synthesizes a MWI for this structure which looks like this:

```swift
init(age: Int, name: String)

```

This initializer allows users to be able to initialize and instance of type `Dog` like `Dog(age: 2, name: "sparky")`. The MWI is a pretty fantastic initializer which frees the user of having to write boiler plate initializers which effectively do the same thing.

## What's the problem with the memberwise initializer?

While the MWI is a fantastic gift from the compiler, it has a number of limitations which hold it back from being an even greater initializer. In SE-0018, it quotes [Chris Lattner](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151130/000518.html) who spelled out some limitations that the MWI currently has:

> The default memberwise initializer behavior of Swift has at least these deficiencies (IMO):
> 
> 1. Defining a custom init in a struct disables the memberwise initializer, and there is no easy way to get it back.
> 2. Access control + the memberwise init often requires you to implement it yourself.
> 3. We don’t get memberwise inits for classes.
> 4. var properties with default initializers should have their parameter to the synthesized initializer defaulted.
> 5. lazy properties with memberwise initializers have problems (the memberwise init eagerly touches it).

To this day, each of those 5 limitations are still in existance for the MWI. Below I have made examples excercising these limitations.

### Limitation 1: Custom init disables the MWI

```swift
struct Dog {
  var age: Int
  var name: String
	
  init(ageInYears: Int, legalName: String) {
    ...
  }
}

let sparky = Dog(age: 2, name: "sparky") // Incorrect argument labels in call (have 'age:name:', expected 'ageInYears:legalName:')

```

### Limitation 2: Access Control

```swift
public struct Dog {
  public var age: Int
  public var name: String
}

let sparky = Dog(age: 2, name: "sparky") // 'Dog' initializer is inaccessible due to 'internal' protection level

```

### Limitation 3: No class support

```swift
class Dog { // Class 'Dog' has no initializers
  var age: Int // stored property 'age' without initial value prevents synthesized initializers
  var name: String // stored property 'name' without initial value prevents synthesized initializers
}

let sparky = Dog(age: 2, name: "sparky") // 'Dog' cannot be constructed because it has no accessible initializers

```

### Limitation 4: No default values for vars with default initializers

```swift
struct Dog {
  var age: Int = 0
  var name: String
}

// Let's use the default age and just assign name
let sparky = Dog(name: "sparky") // Missing argument for parameter 'age' in call

```

### Limitation 5: Lazy properties

In order to fully understand this one, it's best to understand how lazy properties work under the hood.

Given:

```swift
struct DogInfo {
  var age: Int
  var name: String
	
  init(age: Int, name: String) {
    print("Making dog info...")
	
    self.age = age
    self.name = name
  }
}

struct Dog {
  lazy var info: DogInfo = DogInfo(age: 0, name: "")
}

```

The compiler synthesizes something like this:

```swift
struct Dog {
  lazy var info: DogInfo {
    mutating get {
      if let storage = info.storage { return storage }

      let initialValue = DogInfo(age: 0, name: "")
      info.storage = initialValue
      return initialValue
    }

    set {
      info.storage = newValue
    }
  }

  private var info.storage: DogInfo?
}

```

Now that we understand how lazy properties work, where does the MWI come into this? The synthesized MWI for the example above looks something like this:

```swift
init(info: DogInfo?)

```

Seems easy enough, lets try using it in action.

```swift
let sparky = Dog(info: DogInfo(age: 2, name: "sparky"))
// Making dog info...

```

What? I haven't even accessed the info property yet? What's going on? Well, what's really happening is that the value passed for `info` is actually setting the `info.storage` property with immediate execution of the expression. Effectively taking the "lazy" out of the lazy. (If I got anything wrong here, please feel free to correct me.)

## What can we do to solve these limitations?

SE-0018 was a good first step towards abolishing these limitations, but unfortunately the proposal was premature for its time. It was deferred for good reasons that the Rationale lays out. I think it's best to split SE-0018 into 2 parts for what it wants to accomplish: "Powerful MWI" and "Flexible MWI". I'm only going to discuss the first half, "Powerful MWI".

### Powerful Memberwise Initializer

What in the world is a "Powerful MWI"? My idea of what a powerful MWI is is a future MWI in which it solves 4/5 current limitations. I'm excluding class support for now. Read [Tweet #1](https://twitter.com/slava_pestov/status/1052396635894870017) and [Tweet #2](https://twitter.com/dgregor79/status/1052402962427871232) for why class support has a number of lingering questions to be asked/answered. Solving some of these limitations like default values for variables that have default initialers, access control, and disabling the MWI with presence of a custom init are all problems my "Powerful MWI" aim to solve. Other features like opting in/out for this MWI and opting properties in/out are out of scope for my "Powerful MWI" and should be reserved for "Flexible MWI".

## Epilog

This isn't exactly a proposal, but I simply wanted to get this topic discussed again because as we inch closer and closer to Swift 5, I think it might be worth to get some of these limitations solved. I'm curious what everyone thinks about my "Powerful MWI" idea.

### Implementing default values for variables with default initializers

I've actually already implemented a solution for Limitation 4 (No default values for variables with default initializers) here: [apple/swift#19743](https://github.com/apple/swift/pull/19743). I would love to propose this to start solving these limitations if evolution deems that this is the way to go.

---

<div class="post-metadata">

**Author:** ![woolsweater](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/woolsweater/32/2402_2.png) [@woolsweater](https://forums.swift.org/u/woolsweater)\
**Post date:** [October 19, 2018, 2:14pm UTC](https://forums.swift.org/t/state-of-the-memberwise-initializer/17168/2 "2018-10-19T14:14:12Z")

</div>

I usually consider Limitation 1 to be a feature. I like having a succinct way to restrict the initialization of some properties.\* Broadly agreed with the pitch, but I'd hope that the ability to easily express "I don't want the full memberwise initializer" be preserved (somehow -- doesn't have to be the current way).

\*Note that the way to keep the MWI is just to declare the other initializer in an extension, which I've never found onerous.

---

<div class="post-metadata">

**Author:** ![lancep](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lancep/32/1509_2.png) [@lancep](https://forums.swift.org/u/lancep)\
**Post date:** [October 19, 2018, 8:10pm UTC](https://forums.swift.org/t/state-of-the-memberwise-initializer/17168/3 "2018-10-19T20:10:53Z")

</div>

Limitation #2: It would be nice to have a way to signal to the compiler that you want the default generated publicly, but I don't think it should do it by default. Public API should be explicitly written.

I would love to see #4 behave as one would expect.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [October 22, 2018, 3:06pm UTC](https://forums.swift.org/t/state-of-the-memberwise-initializer/17168/4 "2018-10-22T15:06:11Z")

</div>

As the author of SE-0018 I obviously have a lot of interest in this topic! I've been very busy and haven't had a chance to reply until now.

As I mentioned in your pitch thread, I think you chose the right place to start for a small enhancement that might have a chance to make it in the Swift 5 timeframe. I also agree with the choice you mention in this post to omit support for classes. SE-0018 was the first proposal I worked on. Trying to include support for classes in that proposal was a mistake.

I believe addressing the first two limitations you discuss requires committing to a direction for the final solution as both will require introducing new syntax. SE-0018 received an _enormous_ amount of feedback and I would expect the same next time around. For that reason, I think we should wait to wait to have the discussion until this feature falls within the scope of a Swift release _and_ there are implementers willing to participate (a proposal won't be reviewed without a draft implementation).

---

<div class="post-metadata">

**Author:** ![JetForMe](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jetforme/32/482_2.png) [@JetForMe](https://forums.swift.org/u/JetForMe)\
**Post date:** [May 29, 2026, 2:06am UTC](https://forums.swift.org/t/state-of-the-memberwise-initializer/17168/5 "2026-05-29T02:06:44Z")

</div>

What's the state of this these days? I keep running into Limitation #1, specifically in this context. It has forced me to fork the [swift-webauthn](https://github.com/brokenhandsio/swift-webauthn) library, and being security code, I don’t like having to maintain my own fork.

I need to create this object (and others) from individual member values. The `init(from:)` makes the memberwise init `internal`. The package’s own test code creates these, but I can’t.

```swift
public struct RegistrationCredential: Sendable {
    /// The credential ID of the newly created credential.
    public let id: URLEncodedBase64

    /// Value will always be ``CredentialType/publicKey`` (for now)
    public let type: CredentialType

    /// The raw credential ID of the newly created credential.
    public let rawID: [UInt8]

    /// The attestation response from the authenticator.
    public let attestationResponse: AuthenticatorAttestationResponse
}

extension RegistrationCredential: Codable {
    public init(from decoder: any Decoder) throws {
        ...
    }
}

```

All the properties are public. I think Swift should synthesize a public `init()` when that’s the case. If the library author wants to prevent that, they can make the members `private(set)`, or just define the `init` as `internal` or `private`.

Now, I can fork, and maaaybe even convince the maintainers to accept a PR. But this seems like an unnecessarily harsh restriction by default.

---

<div class="post-metadata">

**Author:** ![sisoje](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sisoje/32/6120_2.png) [@sisoje](https://forums.swift.org/u/sisoje)\
**Post date:** [June 23, 2026, 3:14pm UTC](https://forums.swift.org/t/state-of-the-memberwise-initializer/17168/6 "2026-06-23T15:14:47Z")

</div>

I still think disabling synthesized memberwise initializers for `public` structs was a mistake. In modern Swift, and especially in SwiftUI’s data-driven style, `public` structs are often simple value containers. Requiring developers to manually restate the same initializer over and over just creates boilerplate and makes refactoring more tedious.
