# \[Pitch\] Nullable and Non-Optional Nullable Types

**URL:** <https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952>\
**Category:** Pitches\
**Created:** [March 24, 2023, 8:46pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952 "2023-03-24T20:46:21Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![gabrielPeart](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gabrielpeart/32/8623_2.png) [@gabrielPeart](https://forums.swift.org/u/gabrielPeart)\
**Post date:** [March 24, 2023, 8:46pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/1 "2023-03-24T20:46:21Z")

</div>

**Feature: Nullable and Non-Optional Nullable Types**

**Overview**

Swift currently provides an optional type system to handle values that may be absent. However, there are cases where a non-optional value may still be null at runtime, leading to potential bugs and crashes. This feature introduces two new type annotations, `Nullable` and `NonOptionalNullable`, that provide a way to express nullability for non-optional values.

**Goals**

The goals of this feature are to:

- Provide a clear and explicit way to handle null values for non-optional types in Swift.
- Reduce the potential for null-related bugs and crashes in Swift code.
- Integrate with existing Swift type system and syntax in a natural and intuitive way.

**Design**

**Type Annotations**

The two new type annotations, `Nullable` and `NonOptionalNullable`, are parameterized types that can be used to annotate variables, properties, and function parameters and return types.

- `Nullable<T>`: A type that can hold either a value of type `T` or a `nil` value.
- `NonOptionalNullable<T>`: A type that can hold either a value of type `T` or a `nil` value, but not a default value of `T`.

For example, a variable of type `Nullable<Int>` can hold either an integer value or a `nil` value, while a variable of type `NonOptionalNullable<String>` can hold either a non-empty string or a `nil` value.

#### Type Inference and Overload Resolution

The Swift type checker will be modified to allow `Nullable` and `NonOptionalNullable` types to be used in place of their non-nullable counterparts wherever they are expected. Type inference and overload resolution will be updated to support these types.

- `T?` will continue to represent an optional `T`.
- `T!` will continue to represent a non-optional `T`.
- `Nullable<T>` will be used to represent a non-optional value that can be null at runtime.
- `NonOptionalNullable<T>` will be used to represent a non-optional value that can be null at runtime.

**Syntax**

The syntax for `Nullable` and `NonOptionalNullable` types will be similar to the existing syntax for optional types.

- `T?` will continue to represent an optional `T`.
- `T!` will continue to represent a non-optional `T`.
- `Nullable<T>` will be written as `T?` or `Nullable<T>`.
- `NonOptionalNullable<T>` will be written as `T!` or `NonOptionalNullable<T>`.

**Runtime**

The Swift runtime will be updated to support `Nullable` and `NonOptionalNullable` types.

- A separate bit will be allocated to track whether a value is `nil` or not for each nullable and non-optional nullable type.
- Memory layout and alignment will be adjusted to accommodate the null tracking bit.
- Null-checking logic will be added to the generated code for any operations that may read or write nullable values.
- Conversion between nullable and non-nullable types will be supported.

_Pseudocode_:

```swift
func foo(x: Nullable<Int>) {
    if let value = x {
        print("x has value: \(value)")
    } else {
        print("x is nil")
    }
}

let a: Nullable<Int> = 1
foo(x: a) // Prints "x has value: 1"

```

---

<div class="post-metadata">

**Author:** ![bbrk24](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bbrk24/32/27370_2.png) [@bbrk24](https://forums.swift.org/u/bbrk24)\
**Post date:** [March 24, 2023, 8:52pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/2 "2023-03-24T20:52:06Z")

</div>

I don't understand the difference between nullable and optional. For most structs, this proposed `Nullable` type seems to behave identically to `Optional`, though `Optional` has a smaller memory footprint for classes, unsafe pointers, and most enums. (There also seems to be a special case that `String` and `Optional<String>` are the same size, and I don't fully understand why.)

I'm especially confused by `NonOptionalNullable`. What exactly does "but not a default value" mean?

---

<div class="post-metadata">

**Author:** ![gabrielPeart](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gabrielpeart/32/8623_2.png) [@gabrielPeart](https://forums.swift.org/u/gabrielPeart)\
**Post date:** [March 24, 2023, 8:58pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/3 "2023-03-24T20:58:59Z")

</div>

Thank you for reading.

I apologize if my explanation was not clear enough. I will try to clarify my idea. I hope it will be helpful.

Currently, Swift's optional type system provides a way to represent values that may be absent, but it doesn't have a way to express the idea of a non-optional value that could still be null at runtime. This can lead to bugs where developers forget to check for null values.

That is why I humbly suggest a new type annotation that indicates that a non-optional value may be null at runtime.

---

<div class="post-metadata">

**Author:** ![Jon\_Shier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_shier/32/921_2.png) [@Jon\_Shier](https://forums.swift.org/u/Jon_Shier)\
**Post date:** [March 24, 2023, 9:03pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/4 "2023-03-24T21:03:55Z")

</div>

Unless you’re bridging from another language and the bridged API is incorrect (as we see in Apple’s frameworks occasionally), how can any Swift value that isn’t an optional be null?

---

<div class="post-metadata">

**Author:** ![AlexanderM](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alexanderm/32/9781_2.png) [@AlexanderM](https://forums.swift.org/u/AlexanderM)\
**Post date:** [March 24, 2023, 9:08pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/5 "2023-03-24T21:08:15Z")

</div>

Yeah, values imported from C APIs or unsafe APIs are the only ways I can think of that this can happen

```swift
class C {}

let validObjectReference = C()
print(validObjectReference)

let nullReference = unsafeBitCast(nil as UnsafeRawPointer?, to: C.self)
print(nullReference) // Boom

```

Hence the _unsafe_ in `unsafeBitCast`.

---

<div class="post-metadata">

**Author:** ![davdroman](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/davdroman/32/46501_2.png) [@davdroman](https://forums.swift.org/u/davdroman)\
**Post date:** [March 24, 2023, 9:35pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/6 "2023-03-24T21:35:12Z")

</div>

> [@gabrielPeart](#):
>
> but it doesn't have a way to express the idea of a non-optional value that could still be null at runtime

> [@gabrielPeart](#):
>
> For example, a variable of type `Nullable<Int>` can hold either an integer value or a `nil` value, while a variable of type `NonOptionalNullable<String>` can hold either a non-empty string or a `nil` value.

I believe you're misconstruing "null" to mean "empty". An empty `String` isn't considered null in Swift, it's just a string that happens to be empty. Similarly for `Int`, 0 is not considered null. In general, primitive values in Swift don't have "defaults" like other languages do.

If you're looking for a reliable way of representing non-empty strings and arrays at runtime, I suggest you check out this library: [GitHub - pointfreeco/swift-nonempty: 🎁 A compile-time guarantee that a collection contains a value.](https://github.com/pointfreeco/swift-nonempty)

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [March 25, 2023, 12:19am UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/7 "2023-03-25T00:19:59Z")

</div>

> [@bbrk24](#):
>
> I don't understand the difference between nullable and optional.

> [@davdroman](#):
>
> I believe you're misconstruing "null" to mean "empty". An empty `String` isn't considered null in Swift, it's just a string that happens to be empty. Similarly for `Int`, 0 is not considered null. In general, primitive values in Swift don't have "defaults" like other languages do.

> [@Jon\_Shier](#):
>
> how can any Swift value that isn’t an optional be null?

i do understand the idea here, and it is useful in serialization/encoding tasks to be able to elide values that are "empty" (but non-`nil`). to avoid confusion with `Optional`, i prefer to refer to this concept as `Elidable`.

i disagree with the proposed direction, to model this a generic `Elidable<T>` type. `Elidable` should be a protocol instead.

```swift
protocol Elidable
{
    init()
    var isEmpty:Bool { get }
}

```

i think this could be very useful, surely more useful than `Identifiable`. (how often do you declare that conformance but never really use it?)

---

<div class="post-metadata">

**Author:** ![anon9791410](https://avatars.discourse-cdn.com/v4/letter/a/9fc348/32.png) [@anon9791410](https://forums.swift.org/u/anon9791410)\
**Post date:** [March 25, 2023, 12:35am UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/8 "2023-03-25T00:35:03Z")

</div>

> [@taylorswift](#):
>
> i think this could be very useful, surely more useful than `Identifiable`. (how often do you declare that conformance but never really use it?)

Pretty much every SwiftUI view relies heavily on `Identifiable`—that's why it was added, no?  
[It's often a good basis for `Hashable` as well.](https://stackoverflow.com/a/71360574/652038)

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [March 25, 2023, 1:57am UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/9 "2023-03-25T01:57:16Z")

</div>

> [@anon9791410](#):
>
> Pretty much every SwiftUI view relies heavily on `Identifiable`—that's why it was added, no?  
> [It's often a good basis for `Hashable` as well.](https://stackoverflow.com/a/71360574/652038)

that’s fair, my experience is with more of the linux ecosystem, where there are fewer large frameworks that use `Identifiable` a lot.

---

<div class="post-metadata">

**Author:** ![Pampel](https://avatars.discourse-cdn.com/v4/letter/p/3da27b/32.png) [@Pampel](https://forums.swift.org/u/Pampel)\
**Post date:** [March 25, 2023, 4:49pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/10 "2023-03-25T16:49:28Z")

</div>

I'm still not sure I get it, can you give an example?

When deserialising, for example, JSON, I've often wanted a way to distinguish between 'this field was explicitly NULL in the JSON' and 'this field was not present in the JSON' but I don't think this is the same thing, and could probably be handled with nested optionals.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [March 26, 2023, 6:06am UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/11 "2023-03-26T06:06:47Z")

</div>

> [@Pampel](#):
>
> When deserialising, for example, JSON, I've often wanted a way to distinguish between 'this field was explicitly NULL in the JSON' and 'this field was not present in the JSON'

Nulls are not preserved with JSONEncoder / JSONDecoder, but you can use JSONSerialization:

```swift
let string = #"{"foo":null}"#
let obj = try! JSONSerialization.jsonObject(with: string.data(using: .ascii)!) as! [String: Any]
let data = try! JSONSerialization.data(withJSONObject: obj)
let string2 = String(data: data, encoding: .ascii)!
print(obj) // ["foo": <null>]
print(string2) // {"foo":null}

if let value = obj["foo"] {
    if value is NSNull {
        print("nil") // prints: nil
    } else {
        print("non nil: \(value)")
    }
} else {
    print("absent")
}

```

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [March 26, 2023, 7:51pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/12 "2023-03-26T19:51:08Z")

</div>

> [@Pampel](#):
>
> I'm still not sure I get it, can you give an example?

when encoding, if an array field is empty, you often want to elide the field entirely, rather than encode an empty array.

---

<div class="post-metadata">

**Author:** ![itaiferber](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/itaiferber/32/33840_2.png) [@itaiferber](https://forums.swift.org/u/itaiferber)\
**Post date:** [March 27, 2023, 2:36pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/13 "2023-03-27T14:36:28Z")

</div>

> **I don't want to stray too far from the thread, but:**
>
> > [@tera](#):
> >
> > Nulls are not preserved with JSONEncoder / JSONDecoder
> 
> This isn't quite true. The `Codable` APIs consider `null` values first-class citizens, and do offer support for reading and writing `null` values directly:
> 
> 1. [`KeyedEncodingContainer.encodeNil(forKey:)`](https://developer.apple.com/documentation/swift/keyedencodingcontainer/encodenil(forkey:)), [`UnkeyedEncodingContainer.encodeNil()`](https://developer.apple.com/documentation/swift/unkeyedencodingcontainer/encodenil()), and [`SingleValueEncodingContainer.encodeNil()`](https://developer.apple.com/documentation/swift/singlevalueencodingcontainer/encodenil()) can all be used to explicitly write out a `null` value into an archive
> 2. [`KeyedDecodingContainer.contains(_:)`](https://developer.apple.com/documentation/swift/keyeddecodingcontainer/contains(_:))/[`.decodeNil(forKey:)`](https://developer.apple.com/documentation/swift/keyeddecodingcontainer/decodenil(forkey:)), [`UnkeyedDecodingContainer.decodeNil()`](https://developer.apple.com/documentation/swift/unkeyeddecodingcontainer/decodenil()), and [`SingleValueDecodingContainer.decodeNil()`](https://developer.apple.com/documentation/swift/singlevaluedecodingcontainer/decodenil()) can all be used to explicitly check for the presence of a value, or a `null` value
> 
> However, `Codable` synthesis _in the compiler_ opts to use the more permissive [`encodeIfPresent(_:forKey:)`](https://developer.apple.com/documentation/swift/keyedencodingcontainer/encodeifpresent(_:forkey:)-45la3) and [`decodeIfPresent(_:forKey:)`](https://developer.apple.com/documentation/swift/keyeddecodingcontainer/decodeifpresent(_:forkey:)-2hn6i) variants as defaults, which return `nil` if either the key isn't present, or the value is `null`. These are effectively shorthands for
> 
> ```swift
> if let value {
> try container.encode(value, forKey: ...)
> } else {
> try container.encodeNil(forKey: ...)
> }
> 
> ```
> 
> and
> 
> ```swift
> if container.contains(...) {
> try container.decode(..., forKey: ...)
> } else {
> try container.decodeNil(forKey: ...)
> }
> 
> ```
> 
> > [@Pampel](#):
> >
> > When deserialising, for example, JSON, I've often wanted a way to distinguish between 'this field was explicitly NULL in the JSON' and 'this field was not present in the JSON' but I don't think this is the same thing, and could probably be handled with nested optionals.
> 
> If you do care about the specifics of these cases, you can distinguish them by implementing `Encodable` and `Decodable` manually to check precisely the fields you need.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [March 27, 2023, 3:09pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/14 "2023-03-27T15:09:16Z")

</div>

> **Good to know, thanks.**
>
> Note that often times it's not convenient to do a custom encoding/decoding as you can't do it specifically for the field in question, you have to drop away all good system already did for you and start over implementing it for all fields.
> 
> I believe it could be a built-in "nil coding" strategy.
> 
> Just for encoder it's trivial, and for both encoder and decoder it could be achieved with either something like `TriStateOptional` or simply:
> 
> ```swift
> struct ExampleStruct {
> var foo: Int??
> }
> // nil - the field is absent in JSON
> // Optional(nil) - the field is present in JSON, but nil
> // Optional(Optional(42)) - the field is present in JSON and not nil
> 
> ```

---

<div class="post-metadata">

**Author:** ![AlexanderM](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alexanderm/32/9781_2.png) [@AlexanderM](https://forums.swift.org/u/AlexanderM)\
**Post date:** [March 27, 2023, 4:16pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/15 "2023-03-27T16:16:59Z")

</div>

> **straying even further :)**
>
> > [@tera](#):
> >
> > Note that often times it's not convenient to do a custom encoding/decoding as you can't do it specifically for the field in question, you have to drop away all good system already did for you and start over implementing it for all fields.
> 
> Hmmm, I though this could be done with property wrappers, but I couldn't figure it out.
> 
> ```swift
> import Foundation
> 
> @propertyWrapper struct PotentiallyMissing<T> {
> var wrappedValue: T??
> 	
> init(wrappedValue: T??) { self.wrappedValue = wrappedValue }
> }
> 
> extension PotentiallyMissing: Decodable where T: Decodable {
> init(from decoder: Decoder) throws {
> let container = try decoder.singleValueContainer()
> 		
> if let value = try? container.decode(T.self) {
> self.init(wrappedValue: value)
> } else {
> let isExplicitlyNull = container.decodeNil()
> self.init(wrappedValue: isExplicitlyNull ? .some(nil) : nil)
> }
> }
> }
> 
> extension PotentiallyMissing: Encodable where T: Codable {
> func encode(to encoder: Encoder) throws {
> switch wrappedValue {
> case .some(.some(let value)):
> var container = encoder.singleValueContainer()
> try container.encode(value)
> case .some(nil):
> var container = encoder.singleValueContainer()
> try container.encodeNil()
> case nil:
> break // no-op, don't even encode a key with null value
> }
> }
> }
> 
> struct S: Codable {
> @PotentiallyMissing var i: Int??
> }
> 
> let hasValue = S(i: 123 as Int??)
> let hasExplicitNil = S(i: .some(nil))
> let hasNoKeyAtAll = S(i: nil)
> 
> let encoder = JSONEncoder()
> print(String(decoding: try encoder.encode(hasValue), as: UTF8.self))
> print(String(decoding: try encoder.encode(hasExplicitNil), as: UTF8.self))
> print(String(decoding: try encoder.encode(hasNoKeyAtAll), as: UTF8.self)) // Not what I expcted: {"i":{}}
> 
> let decoder = JSONDecoder()
> print(try decoder.decode(S.self, from: #"{ "i": 123 }"#.data(using: .utf8)!))
> print(try decoder.decode(S.self, from: #"{ "i": null }"#.data(using: .utf8)!))
> print(try decoder.decode(S.self, from: #"{ }"#.data(using: .utf8)!)) // Boom
> 
> ```

---

<div class="post-metadata">

**Author:** ![pyrtsa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/pyrtsa/32/740_2.png) [@pyrtsa](https://forums.swift.org/u/pyrtsa)\
**Post date:** [March 27, 2023, 7:23pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/16 "2023-03-27T19:23:30Z")

</div>

> **Straying further still, but fixing it for you**
>
> @AlexanderM You can make this to work by introducing the following extensions that hook into the type's `Codable` synthesis:
> 
> ```swift
> extension KeyedDecodingContainer {
> func decode<T: Decodable>(_: PotentiallyMissing<T>.Type, forKey key: Key) throws -> PotentiallyMissing<T> {
> guard contains(key) else { return PotentiallyMissing(wrappedValue: nil) }
> guard try !decodeNil(forKey: key) else { return PotentiallyMissing(wrappedValue: .some(nil)) }
> return PotentiallyMissing(wrappedValue: try decode(T.self, forKey: key))
> }
> }
> 
> extension KeyedEncodingContainer {
> mutating func encode<T: Encodable>(_ value: PotentiallyMissing<T>, forKey key: Key) throws {
> guard let optional = value.wrappedValue else { return }
> if let value = optional {
> try encode(value, forKey: key)
> } else {
> try encodeNil(forKey: key)
> }
> }
> }
> 
> ```
> 
> …only the latter fails with `error: ambiguous use of 'encode(_:forKey:)'` unless you also loosen the conditional `Encodable` conformance requirement to what it probably should've been to start with:
> 
> ```diff
> -extension PotentiallyMissing: Encodable where T: Codable {
> +extension PotentiallyMissing: Encodable where T: Encodable {
> 
> ```
> 
> With these changes, the program prints what you'd expect:
> 
> ```swift
> {"i":123}
> {"i":null}
> {}
> S(_i: main.PotentiallyMissing<Swift.Int>(wrappedValue: Optional(Optional(123))))
> S(_i: main.PotentiallyMissing<Swift.Int>(wrappedValue: Optional(nil)))
> S(_i: main.PotentiallyMissing<Swift.Int>(wrappedValue: nil))
> 
> ```

---

<div class="post-metadata">

**Author:** ![itaiferber](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/itaiferber/32/33840_2.png) [@itaiferber](https://forums.swift.org/u/itaiferber)\
**Post date:** [March 28, 2023, 6:28pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/17 "2023-03-28T18:28:35Z")

</div>

> **One last (🚨 important 🚨) note:**
>
> > [@AlexanderM](#):
> >
> > Hmmm, I though this could be done with property wrappers, but I couldn't figure it out.
> 
> The reason a property wrapper can't directly handle this case is because the check for the presence of a key is done one level _up_ in the containing type, and when you wrap a variable in a property wrapper, it's the type of the _property wrapper_ that gets encoded and decoded.
> 
> In the case of `S.i`, the actual type being encoded and decoded is `PotentiallyMissing<Int>`, _not_ the `Int??` wrapped value. This means that when the compiler synthesizes `Encodable` and `Decodable` conformances, the calls being made are `encode(_:forKey:)` and `decode(_:forKey:)`, _not_ the `IfPresent` variants, because the type isn't actually `Optional`.
> 
> This means that `struct S` actually looks like:
> 
> ```swift
> struct S: Codable {
> @PotentiallyMissing var i: Int??
> 
> private enum CodingKeys: String, CodingKey {
> case i
> }
> 
> init(from decoder: Decoder) throws {
> let container = try decoder.container(keyedBy: CodingKeys.self)
> _i = try container.decode(PotentiallyMissing<Int>.self, forKey: .i)
> }
> 
> func encode(to encoder: Encoder) throws {
> var container = try encoder.container(keyedBy: CodingKeys.self)
> try container.encode(_i, forKey: .i)
> }
> }
> 
> ```
> 
> If you want additional justification for why this behavior is necessary, consider:
> 
> 1. If the compiler encoded and decoded the _wrapped_ value instead of the property wrapper itself, the property wrapper's own `init(from:)` and `encode(to:)` would never get called, preventing the possibility of using a property wrapper from customizing `Codable` conformance in the first place
> 2. Even if a property wrapper wraps an `Optional` value, the property wrapper _itself_ is not optional — if you were to `decodeIfPresent(PotentiallyMissing<Int>.self, forKey: .i)` and got back `nil`, what value could be reasonably assigned to `_i`? (The compiler _could_ theoretically know to try to assign `PotentiallyMissing(wrappedValue: nil)`, but this gets really subtle and tricky)
> 
> With this in mind, you can see that:
> 
> 1. On decode, the field is asserted to be present (even if `nil`): the `decode` call checks for the `.i` key before ever calling into `PotentiallyMissing<T>.init(from:)`, so an error is thrown before any decoding actually happens
> 2. On encode, the field is also asserted to be present (even if `nil`), which means that if nothing at all is encoded by `PotentiallyMissing<T>.encode(to:)`, the key still needs to be written out, and so an empty object is inserted to allow the key to be present
> 
> The reason @pyrtsa's suggestion works is that it interjects an overload for `PotentiallyMissing<T>` one level _up_ at the actual `encode`/`decode` callsites, and does the work there, so that you can map a missing key to an actual `PotentiallyMissing<T>` value and vice versa.
> 
> ## ⚠ HOWEVER: ⚠
> 
> You must be _extremely_ careful with this approach — both in using it, and suggesting it to others. These method additions are _statically dispatched_, and so will _only_ work for `PotentiallyMissing<T>` within the modules where these overloads are visible (and cannot work "retroactively"). In other words, they're likely to _only_ work within your module.
> 
> Consider:
> 
> 1. Module A, provides `PotentiallyMissing<T>`
> 2. Module B imports Module A, and has a type which encodes and decodes using `PotentiallyMissing<T>`
> 3. Module C (your module) imports Module B, and also has a type which encodes and decodes using `PotentiallyMissing<T>`, _and adds the listed overloads_
> 
> Code from Module B will encode `PotentiallyMissing<T>` values one way, and your module will encode those same values another way! This is extraordinarily subtle and fragile, and can lead to inconsistent results, even within the same type hierarchy.
> 
> # Use at your own risk.

---

<div class="post-metadata">

**Author:** ![pyrtsa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/pyrtsa/32/740_2.png) [@pyrtsa](https://forums.swift.org/u/pyrtsa)\
**Post date:** [March 28, 2023, 7:20pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/18 "2023-03-28T19:20:01Z")

</div>

> **Clarification**
>
> > [@itaiferber](#):
> >
> > 1. Module A, provides `PotentiallyMissing<T>`
> > 2. Module B imports Module A, and has a type which encodes and decodes using `PotentiallyMissing<T>`
> > 3. Module C (your module) imports Module B, and also has a type which encodes and decodes using `PotentiallyMissing<T>`, _and adds the listed overloads_
> 
> Does the issue still remain if `PotentiallyMissing<T>` and the listed overloads are all made `public` and defined in A?
> 
> I can't see how that would make B and C behave differently anymore.

---

<div class="post-metadata">

**Author:** ![itaiferber](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/itaiferber/32/33840_2.png) [@itaiferber](https://forums.swift.org/u/itaiferber)\
**Post date:** [March 28, 2023, 8:20pm UTC](https://forums.swift.org/t/pitch-nullable-and-non-optional-nullable-types/63952/19 "2023-03-28T20:20:42Z")

</div>

That's correct. Static overloads can be used from any module where those overloads are visible — if they are exposed publicly from Module A, and modules B and C are compiled with those overloads present, they can be used.

However, the scenario I posed is far from hypothetical:

1. Module A is the stdlib, and the type in question is an stdlib type
2. Module B is a package you use, which uses the stdlib
3. Module C is your app, which uses both the stdlib and that package

If you're not careful, one archive can contain multiple subtly- (or not so subtly-!) different representations of the same type.
