# SE-0328: Structural opaque result types

**URL:** <https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248>\
**Category:** Proposal Reviews\
**Created:** [November 2, 2021, 6:33pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248 "2021-11-02T18:33:53Z")\
**Posts on this page:** 18\
**Page:** 3

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [November 9, 2021, 2:29pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/42 "2021-11-09T14:29:35Z")

</div>

> [@ensan-hcl](#):
>
> With SE-0328, you can create `some P` in parameter position easily with `typealias` , even if we ban bare `some P` in that position.

Good callout. I would _hope_ that if we did defer `some P` in parameter position as part of this proposal, we would be able to ban it a bit more comprehensively than a purely syntactic rule like "`some P` may not appear inside the parameter list of a written function type." Ideally, the rule would be something like, "a user-written `some P` may not be resolved in a way such that the underlying type is contained within the parameter list of a function type." I am not quite knowledgeable enough about opaque type resolution to know how feasible that sort of rule would be from an implementation standpoint, though.

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [November 9, 2021, 5:18pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/43 "2021-11-09T17:18:01Z")

</div>

> [@Jumhyn](#):
>
> I am not quite knowledgeable enough about opaque type resolution to know how feasible that sort of rule would be from an implementation standpoint, though.

With the implementation of this proposal, it works just like any other type parameter - a `some` type is opened and replaced with a type variable in the constraint system, and bindings are inferred in the same way as usual. We could easily track that the type variable originated from an opaque type with a locator (the implementation might already do that, I remember discussing that approach with @bdriscoll a while back)

EDIT: The implementation does indeed already do that:

```swift
/// This is referring to a type produced by opening an opaque type archetype
/// type at the base of the locator.
CUSTOM_LOCATOR_PATH_ELT(OpenedOpaqueArchetype)

```

---

<div class="post-metadata">

**Author:** ![ksluder](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@ksluder](https://forums.swift.org/u/ksluder)\
**Post date:** [November 9, 2021, 6:53pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/44 "2021-11-09T18:53:28Z")

</div>

> [@Zollerboy1](#):
>
> I could imagine some syntax like
> 
> ```swift
> func foo(_ bar: some BinaryInteger) where bar: Int {}
> 
> ```
> 
> but this feels a bit strange, because normally everything in the where clause is part of a function's signature, but here it would be not.

I don’t completely understand the goal of this. What does it mean for a callee to choose the type of its parameters? At the call site, the compiler needs to prepare the arguments and jump to `foo()`’s implementation. In your scheme, what precisely are the concrete types of the values on the stack at the point that execution jumps to `foo`?

---

<div class="post-metadata">

**Author:** ![Zollerboy1](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/zollerboy1/32/12997_2.png) [@Zollerboy1](https://forums.swift.org/u/Zollerboy1)\
**Post date:** [November 9, 2021, 8:36pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/45 "2021-11-09T20:36:23Z")

</div>

> [@ksluder](#):
>
> In your scheme, what precisely are the concrete types of the values on the stack at the point that execution jumps to `foo` ?

Counter-question: What is the concrete type of `bar` in the following code snippet?

```swift
func foo() -> some BinaryInteger { 5 }

let bar = foo()

```

---

<div class="post-metadata">

**Author:** ![ksluder](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@ksluder](https://forums.swift.org/u/ksluder)\
**Post date:** [November 9, 2021, 8:41pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/46 "2021-11-09T20:41:02Z")

</div>

> [@Zollerboy1](#):
>
> What is the concrete type of `bar` in the following code snippet?
> 
> ```swift
> func foo() -> some BinaryInteger { 5 }
> 
> let bar = foo()
> 
> ```

An opaque BinaryInteger archetype. Swift code cannot directly construct instances of such a type. Therefore such a type cannot be the type of a function parameter.

---

<div class="post-metadata">

**Author:** ![Zollerboy1](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/zollerboy1/32/12997_2.png) [@Zollerboy1](https://forums.swift.org/u/Zollerboy1)\
**Post date:** [November 9, 2021, 8:43pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/47 "2021-11-09T20:43:19Z")

</div>

How does that work then?

> [@Zollerboy1](#):
>
> ```swift
> func foo() -> some BinaryInteger { 5 }
> 
> let bar = foo() // type of bar is 'some BinaryInteger'
> 
> let baz = bar.isMultiple(of:) // type of baz is '(some BinaryInteger) -> Bool
> 
> print(baz(7)) // prints '2'
> 
> ```

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [November 9, 2021, 8:54pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/48 "2021-11-09T20:54:31Z")

</div>

> [@ksluder](#):
>
> An opaque BinaryInteger archetype. Swift code cannot directly construct instances of such a type. Therefore such a type cannot be the type of a function parameter.

You can still construct instances of archetypes as long as you have an initializer requirement. Opaque types are trickier to construct because you can't actually spell the archetype in a type expression context, but the `ExpressibleBy*Literal` protocols still allow you to construct instances of opaque types from literals.

---

<div class="post-metadata">

**Author:** ![Zollerboy1](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/zollerboy1/32/12997_2.png) [@Zollerboy1](https://forums.swift.org/u/Zollerboy1)\
**Post date:** [November 9, 2021, 9:02pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/49 "2021-11-09T21:02:57Z")

</div>

> [@hborla](#):
>
> the `ExpressibleBy*Literal` protocols still allow you to construct instances of opaque types from literals.

And you can also use initializer requirements and static member expressions, e.g. if you have a function `foo` with type `(some BinaryInteger) -> ()` you can call it with `foo(.zero)`, or `foo(.init(truncatingIfNeeded: 5))`.

---

<div class="post-metadata">

**Author:** ![ksluder](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@ksluder](https://forums.swift.org/u/ksluder)\
**Post date:** [November 9, 2021, 10:01pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/50 "2021-11-09T22:01:31Z")

</div>

But you aren’t constructing values whose _concrete type_ is opaque:

```swift
func foo() -> some BinaryInteger { 5 }

let bar = foo() // type of bar is 'some BinaryInteger'

print(type(of: bar)) // prints "Int"

```

The value stored in the memory location named by `bar` is an `Int`. The type of the `bar` variable within the type system at compile time is `some BinaryInteger`.

You have expressed a desire that `foo(_ arg: some P)` “means what it already means today”. I am trying to understand what you think it “already means”, because I cannot come up with a definition of opaque return types as they exist today in which the callee exerts influence over the types of its arguments.

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [November 10, 2021, 12:35am UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/51 "2021-11-10T00:35:33Z")

</div>

> [@Jumhyn](#):
>
> Visually, these two declarations appear very similar. Were I coming to the language without the benefit of these discussions around opaque types, I would expect them to behave (near) identically, especially because the existing return-type equivalents:
> 
> ```swift
> let x: some P = ...
> func x() -> some P = ...
> 
> ```
> 
> mean basically the same thing. We'd also have a situation where `(some P) -> Int` is a valid type, but the type of `func f(_: some P) -> Int` is not, in fact `(some P) -> Int` . In fact, users can't even _write_ the type of `func f(_: some P) -> Int` in source.

I think this framing of the problem with "overloading" the meaning of `some P` in parameter position makes a lot of sense; thank you for taking the time to explain in depth.

I've also been thinking more about the case where an inferred opaque type in parameter position _is_ useful, and I'm slowly coming to the conclusion that the `some` spelling isn't really the best syntax anyway a few reasons:

- It doesn't properly express its relationship to the opaque type that it was inferred from, which is going to inform how you use that type/what type of value your'e allowed to pass in
- The spelling only possible if that opaque type is constrained to a protocol

In the example from upthread:

```swift
func foo() -> some BinaryInteger { 5 }

let bar = foo() // type of bar is 'some BinaryInteger'

let baz = bar.isMultiple(of:) // type of baz is '(some BinaryInteger) -> Bool

```

Spelling the type of `baz` as `(some BinaryInteger) -> Bool` is...actually kind of misleading. It's not a random `some BinaryInteger`. The type of this thing would better be expressed with some static variant of `type(of: bar)`. Then, it would be clear that you don't have to guess at the type of value to pass in - you can pass in anything that has the same type as `bar`, such as the result of calling `foo()` again.

---

<div class="post-metadata">

**Author:** ![ensan-hcl](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ensan-hcl/32/15186_2.png) [@ensan-hcl](https://forums.swift.org/u/ensan-hcl)\
**Post date:** [November 10, 2021, 12:45am UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/52 "2021-11-10T00:45:37Z")

</div>

> [@hborla](#):
>
> - The spelling only possible if that opaque type is constrained to a protocol

Just a question... In what situation isn't an opaque type constrained to a protocol?

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [November 10, 2021, 12:52am UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/53 "2021-11-10T00:52:37Z")

</div>

When it's inferred from an unconstrained associated type of an opaque type:

```swift
protocol P {
  associatedtype A
  func f(a: A) -> Void
}

struct S: P {
  func f(a: Int) { }
}

func someP() -> some P { S() }

let p = someP() // this type is `some P`
let fn = p.f // this type is... `(type(of: p).A) -> Void`?

```

I suppose you could express the input type of `p.f` with `some Any` but that doesn't seem particularly helpful either 🙂

---

<div class="post-metadata">

**Author:** ![xAlien95](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/xalien95/32/12558_2.png) [@xAlien95](https://forums.swift.org/u/xAlien95)\
**Post date:** [November 10, 2021, 2:13am UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/54 "2021-11-10T02:13:56Z")

</div>

> [@hborla](#):
>
> Spelling the type of `baz` as `(some BinaryInteger) -> Bool` is...actually kind of misleading. It's not a random `some BinaryInteger` . The type of this thing would better be expressed with some static variant of `type(of: bar)` .

I agree and the diagnostics, in the easiest cases, are complete in that regard. An opaque type isn't diagnosed just as `some P`, but as `some P (result of 'foo()')` or `some P (type of 'bar')` depending on the situation, which is great.

 ![image](https://global.discourse-cdn.com/swift/original/3X/9/e/9e4f92e7b998399d453c63cdae01d3aae3b8c598.png)  
Okay, okay... the fix-it is horrible, but the error is complete and on point!

However, there can be cases in which the referenced variable or function is too convoluted to be spelled in quick help pop-ups or even in errors. In those cases, the spelling `some P` seems to be the best one IMHO. One of such examples may be this one

```swift
func foo() -> some Collection { "s" }
foo().index(after: 5)
// error@-1: Cannot convert value of type 'Int' to expected argument type '(some Collection).Index'

```

The error shows up because the returned `Collection` may not have `Int` indices. The complete spelling would have been `(some Collection (result of 'foo()')).Index`, which is acceptable in this particular instance, but it wouldn't have been anymore if e.g. `foo()` had showed up in a method chain. (As a side note, in your last example, `fn` is `((some P).A) -> Void`, so no need to fallback to `(some Any) -> Void` 🙂)

That to say that `some P` in parameter position (relatively to structural opaque result types) is the most appropriate spelling which can be applied in the general case.

---

<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:** [November 18, 2021, 12:07am UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/55 "2021-11-18T00:07:11Z")

</div>

The `some` keyword, while never advertised as doing this, allows for patterns that had been previously reserved for class hierarchies, and protocol hierarchies without associated types. One of the ramifications of that is in my previous post. Another other is that you can now utilize base members in "overrides". E.g.

```swift
protocol Super {
  associatedtype Associatedtype = Any
}

extension Super {
  var property: Int { 1 }
}

protocol Sub: Super { }

extension Sub {
  var `super`: some Super { self }
  
  // Returns 2.
  var property: Int { `super`.property + 1 }
}

```

If `Super` had no associated type, `(self as Super).property + 1` would compile, but it's not as good of a solution. So `self as some Super` should compile regardless of whether `Super` has an associated type.

* * *

Interestingly and sadly, it's possible to use type members as well, but only if you have an instance to work with. 🧐 I don't think this proposal is going to help with that, but I hope I'm wrong!

```swift
extension Super {
  static var property: Int { 1 }
}

extension Sub {
  var property: Int {
    type(of: `super`).property
  }
}

```

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [November 22, 2021, 1:40pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/56 "2021-11-22T13:40:29Z")

</div>

@hborla quick question:

Why is this an invalid position?

> <https://github.com/willtunnels/swift/blob/b54e518741ee761afbda39cc7976998c5dc7ac05/test/type/opaque.swift#L156>

Wouldn't the usage inside generic context allow the same usage inside a generic type alias which in other words could be just substituted to just `some P`?

```swift
typealias G<T> = T
typealias SomeP = G<some P>

```

I understand that an opaque type needs to be resolved from a return type, but so can the aliased opaque type only be resolved at the point of its use in for an opaque type valid position.

---

<div class="post-metadata">

**Author:** ![ensan-hcl](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ensan-hcl/32/15186_2.png) [@ensan-hcl](https://forums.swift.org/u/ensan-hcl)\
**Post date:** [November 22, 2021, 1:56pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/57 "2021-11-22T13:56:32Z")

</div>

> [@DevAndArtist](#):
>
> I understand that an opaque type needs to be resolved from a return type, but so can the aliased opaque type only be resolved at the point of its use in for an opaque type valid position.

It's a totally new rule. I think this should be discussed as generalized `some` syntax, not as structural opaque result types.

In addition, you can just do this:

```swift
// instead of
typealias SomeP = SomeComplexStructure<some P>

// use this ... Some<some P> can be used for SomeComplexStructure<some P>
typealias Some<T> = SomeComplexStructure<T>

```

---

<div class="post-metadata">

**Author:** ![ben-cohen](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ben-cohen/32/296_2.png) [@ben-cohen](https://forums.swift.org/u/ben-cohen)\
**Post date:** [November 30, 2021, 6:33pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/58 "2021-11-30T18:33:11Z")

</div>

## Review Conclusion

The proposal has been [accepted](https://forums.swift.org/t/accepted-with-modifications-se-0328-structural-opaque-result-type/53789).

---

<div class="post-metadata">

**Author:** ![ben-cohen](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ben-cohen/32/296_2.png) [@ben-cohen](https://forums.swift.org/u/ben-cohen)\
**Post date:** [December 6, 2021, 9:18pm UTC](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/59 "2021-12-06T21:18:50Z")

</div>

Closed on December 6, 2021, 9:18pm UTC



[Previous page](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248.md?page=2)
