<commit_before># Property Wrappers

* Proposal: [SE-0258](0258-property-wrappers.md)
* Authors: [<NAME>](https://github.com/DougGregor), [<NAME>](https://github.com/jckarter)
* Review Manager: [<NAME>](https://github.com/rjmccall)
* Status: **Active Review (June 27th...July 3rd, 2019)**
* Implementation: [Linux toolchain](https://ci.swift.org/job/swift-PR-toolchain-Linux/251//artifact/branch-master/swift-PR-25781-251-ubuntu16.04.tar.gz), [macOS toolchain](https://ci.swift.org/job/swift-PR-toolchain-osx/327//artifact/branch-master/swift-PR-25781-327-osx.tar.gz)
* Review: ([review #1](https://forums.swift.org/t/se-0258-property-delegates/23139)) ([revision announcement #1](https://forums.swift.org/t/returned-for-revision-se-0258-property-delegates/24080)) ([review #2](https://forums.swift.org/t/se-0258-property-wrappers-second-review/25843)) ([review #3](https://forums.swift.org/t/se-0258-property-wrappers-third-review/26399))
* Previous versions: [Revision #2](https://github.com/apple/swift-evolution/blob/bb8709c2ddca25c21a3c1e0298ce9457911dbfba/proposals/0258-property-wrappers.md), [Revision #1](https://github.com/apple/swift-evolution/commit/8c3499ec5bc22713b150e2234516af3cb8b16a0b)

## Introduction

There are property implementation patterns that come up repeatedly.
Rather than hardcode a fixed set of patterns into the compiler (as we have done for `lazy` and `@NSCopying`),
we should provide a general "property wrapper" mechanism to allow
these patterns to be defined as libraries.

This is an alternative approach to some of the problems intended to be addressed by the [2015-2016 property behaviors proposal](https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md). Some of the examples are the same, but this proposal takes a completely different approach designed to be simpler, easier to understand for users, and less invasive in the compiler implementation. There is a section that discusses the substantive differences from that design near the end of this proposal.

[Pitch #1](https://forums.swift.org/t/pitch-property-delegates/21895)<br/>
[Pitch #2](https://forums.swift.org/t/pitch-2-property-delegates-by-custom-attributes/22855)<br/>
[Pitch #3](https://forums.swift.org/t/pitch-3-property-wrappers-formerly-known-as-property-delegates/24961)<br/>

## Motivation

We've tried to accommodate several important patterns for properties with
targeted language support, like `lazy` and `@NSCopying`, but this support has been narrow in scope and utility.  For instance, Swift provides `lazy` properties as a primitive language feature, since lazy initialization is common and is often necessary to avoid having properties be exposed as `Optional`. Without this language support, it takes a lot of boilerplate to get the same effect:

```swift
struct Foo {
  // lazy var foo = 1738
  private var _foo: Int?
  var foo: Int {<commit_msg>[SE-0258] Add a table of contents (#1056)<commit_after># Property Wrappers

* Proposal: [SE-0258](0258-property-wrappers.md)
* Authors: [<NAME>](https://github.com/DougGregor), [<NAME>](https://github.com/jckarter)
* Review Manager: [<NAME>](https://github.com/rjmccall)
* Status: **Active Review (June 27th...July 3rd, 2019)**
* Implementation: [Linux toolchain](https://ci.swift.org/job/swift-PR-toolchain-Linux/251//artifact/branch-master/swift-PR-25781-251-ubuntu16.04.tar.gz), [macOS toolchain](https://ci.swift.org/job/swift-PR-toolchain-osx/327//artifact/branch-master/swift-PR-25781-327-osx.tar.gz)
* Review: ([review #1](https://forums.swift.org/t/se-0258-property-delegates/23139)) ([revision announcement #1](https://forums.swift.org/t/returned-for-revision-se-0258-property-delegates/24080)) ([review #2](https://forums.swift.org/t/se-0258-property-wrappers-second-review/25843)) ([review #3](https://forums.swift.org/t/se-0258-property-wrappers-third-review/26399))
* Previous versions: [Revision #2](https://github.com/apple/swift-evolution/blob/bb8709c2ddca25c21a3c1e0298ce9457911dbfba/proposals/0258-property-wrappers.md), [Revision #1](https://github.com/apple/swift-evolution/commit/8c3499ec5bc22713b150e2234516af3cb8b16a0b)

## Contents

+ [Introduction](#introduction)
+ [Motivation](#motivation)
+ [Proposed solution](#proposed-solution)
+ [Examples](#examples)
  - [Delayed Initialization](#delayed-initialization)
  - [`NSCopying`](#nscopying)
  - [`Atomic`](#atomic)
  - [Thread-specific storage](#thread-specific-storage)
  - [User defaults](#user-defaults)
  - [Copy-on-write](#copy-on-write)
  - [`Ref` / `Box`](#ref--box)
  - ["Clamping" a value within bounds](#clamping-a-value-within-bounds)
  - [Property wrapper types in the wild](#property-wrapper-types-in-the-wild)
+ [Composition of property wrappers](#composition-of-property-wrappers)
+ [Detailed design](#detailed-design)
  - [Property wrapper types](#property-wrapper-types)
  - [Initialization of synthesized storage properties](#initialization-of-synthesized-storage-properties)
  - [Type inference with property wrappers](#type-inference-with-property-wrappers)
  - [Custom attributes](#custom-attributes)
  - [Mutability of properties with wrappers](#mutability-of-properties-with-wrappers)
  - [Out-of-line initialization of properties with wrappers](#out-of-line-initialization-of-properties-with-wrappers)
  - [Memberwise initializers](#memberwise-initializers)
  - [Codable, Hashable, and Equatable synthesis](#codable-hashable-and-equatable-synthesis)
  - [$ identifiers](#-identifiers)
  - [Projections](#projections)
  - [Restrictions on the use of property wrappers](#restrictions-on-the-use-of-property-wrappers)
+ [Impact on existing code](#impact-on-existing-code)
+ [Backward compatibility](#backward-compatibility)
+ [Alternatives considered](#alternatives-considered)
  - [Composition](#composition)
  - [Composition via nested type lookup](#composition-via-nested-type-lookup)
  - [Composition without nesting](#composition-without-nesting)
  - [Using a formal protocol instead of `@propertyWrapper`](#using-a-formal-protocol-instead-of-propertywrapper)
  - [Kotlin-like `by` syntax](#kotlin-like-by-syntax)
  - [Alternative spellings for the `$` projection property](#alternative-spellings-for-the--projection-property)
  - [The 2015-2016 property behaviors design](#the-2015-2016-property-behaviors-design)
+ [Future Directions](#future-directions)
  - [Finer-grained access control](#finer-grained-access-control)
  - [Referencing the enclosing 'self' in a wrapper type](#referencing-the-enclosing-self-in-a-wrapper-type)
  - [Delegating to an existing property](#delegating-to-an-existing-property)
+ [Revisions](#revisions)
  - [Changes from the second reviewed version](#changes-from-the-second-reviewed-version)
  - [Changes from the first reviewed version](#changes-from-the-first-reviewed-version)
+ [Acknowledgments](#acknowledgments)

## Introduction

There are property implementation patterns that come up repeatedly.
Rather than hardcode a fixed set of patterns into the compiler (as we have done for `lazy` and `@NSCopying`),
we should provide a general "property wrapper" mechanism to allow
these patterns to be defined as libraries.

This is an alternative approach to some of the problems intended to be addressed by the [2015-2016 property behaviors proposal](https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md). Some of the examples are the same, but this proposal takes a completely different approach designed to be simpler, easier to understand for users, and less invasive in the compiler implementation. There is a section that discusses the substantive differences from that design near the end of this proposal.

[Pitch #1](https://forums.swift.org/t/pitch-property-delegates/21895)<br/>
[Pitch #2](https://forums.swift.org/t/pitch-2-property-delegates-by-custom-attributes/22855)<br/>
[Pitch #3](https://forums.swift.org/t/pitch-3-property-wrappers-formerly-known-as-property-delegates/24961)<br/>

## Motivation

We've tried to accommodate several important patterns for properties with
targeted language support, like `lazy` and `@NSCopying`, but this support has been narrow in scope and utility.  For instance, Swift provides `lazy` properties as a primitive language feature, since lazy initialization is common and is often necessary to avoid having properties be exposed as `Optional`. Without this language support, it takes a lot of boilerplate to get the same effect:

```swift
struct Foo {
  // lazy var foo = 1738
  private var _foo: Int?
  var foo: Int {
{'fraction_non_alphanumeric': 0.13557737260402056, 'fraction_numerical': 0.042776998597475455, 'mean_word_length': 5.324464153732446, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 30, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5918852', 'n_tokens_mistral': 2992, 'n_tokens_neox': 2597, 'n_words': 642}