# Additional type constraint for the \`where\` clause

**URL:** <https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844>\
**Category:** Pitches\
**Created:** [November 9, 2018, 11:08am UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844 "2018-11-09T11:08:14Z")\
**Posts on this page:** 13\
**Page:** 1

<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 9, 2018, 11:08am UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844/1 "2018-11-09T11:08:14Z")

</div>

In the "[SE-0235 - Add Result to the Standard Library](https://forums.swift.org/t/se-0235-add-result-to-the-standard-library/17752/119)" review process @Slava_Pestov [pitched](https://forums.swift.org/t/se-0235-add-result-to-the-standard-library/17752/3) an exclusive exception for the behavior of protocols in case of the empty `Error` protocol. While it might solve the general limitations for `Error`, it does not for any other protocol that has no associated types.

Moreover I'm concerned that it might create more harm than good in the long run. This change must be carefully crafted and tested before including it into the language. Besides that, such behavior for a protocol becomes very special when you want to create custom constraints in regard to the `Error` protocol. Should we use conformance-requirement or same-type-requirement? The latter is obviously confusing, at least it is confusing to me.

I would like to pitch a different approach that comes to my mind which is trying to solve the more general problem.

- Add a new type constraint operator `:==` (or maybe `:=`)
- Extend the grammar of a generic parameter clause:
  - generic-where-clause -\> where requirement-list
  - requirement-list -\> requirement | requirement , requirement-list
  - requirement -\> conformance-requirement | same-type-requirement **| conformance-or-same-type-requirement**
  - conformance-requirement -\> type-identifier : type-identifier
  - conformance-requirement -\> type-identifier : protocol-composition-type
  - same-type-requirement -\> type-identifier == type
  - **conformance-or-same-type-requirement -\> type-identifier :== type-identifier**
  - **conformance-or-same-type-requirement -\> type-identifier :== protocol-composition-type**
  - **conformance-or-same-type-requirement -\> type-identifier :== type**

The new constraint will allow to describe that one would like to either have a concrete existential / superclass, a concrete type that conforms to the existential / protocol or is a subclass of a specific superclass (in cases of classes the `:` operator already allows the pitched behavior).

In case of `Result` we could limit the generic `Error` parameter to be either `Swift.Error` or a concrete type that conforms to that protocol.

```swift
public enum Result<Value, Error> where Error :== Swift.Error { ... }

```

In other cases where people struggled with that limitation and were forced to create overloads for the same function to have the same type requirement to an existential can be merged into single generic representation by using the new `:==` operator.

Feedback is very much welcome.

---

<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:** [November 9, 2018, 2:49pm UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844/2 "2018-11-09T14:49:25Z")

</div>

Doesn't this fall under the umbrella of "disjunctions in constraints are bad"?

---

<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 9, 2018, 3:16pm UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844/3 "2018-11-09T15:16:59Z")

</div>

Why do think it would be?

This pitch really isn't the same as `Int | String`, obviously. All I'm trying to solve with this is to express a constraint that allows you to say I want the generic type to be either of type `A` or it should be a subtype of type `A`. Then the compiler is always free to treat the type as `A`.

For functions we can create overloads to workaround that issue, but for type declarations there is simply no way to do so which leaves as like in a corner of unconstrained types like the proposed generic `Error` type of `Result` which in nearly any case should be either `Swift.Error` or a type conforming to `Swift.Error`. The pitched functionality would generalize that and allow more flexibility on type declaration and potentially fold quite a lot of functions.

I cannot tell for sure, but wouldn't this even simplify the bridging to Objective-C? Since the error is always correlated to `Swift.Error` it can simply transform the error to `Swift.Error` in case of `Result<T, Error : Swift.Error>`.

Besides that we don't have to introduce hacks for weirdly self conforming protocols, and I also think this would play really well with your generalized supertype constraint.

---

<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:** [November 9, 2018, 4:09pm UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844/4 "2018-11-09T16:09:26Z")

</div>

> [@DevAndArtist](#):
>
> All I'm trying to solve with this is to express a constraint that allows you to say I want the generic type to be either of type `A` or it should be a subtype of type `A` . Then the compiler is always free to treat the type as `A` .

_or_ is a disjunction and you are putting it in a constraint. The core team has spoken against disjunctions in constraints, not just in types (i.e. unions).

> [@DevAndArtist](#):
>
> Besides that we don't have to introduce hacks for weirdly self conforming protocols, and I also think this would play really well with your generalized supertype constraint.

Isn't the plan to eventually lift the limitation of self conformance in some way? I view the discussion of doing that for `Error` as jumping ahead, similar to `AnyHashable` jumping ahead of generalized existentials. I don't view it as inconsistent with the direction of the language.

---

<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 9, 2018, 4:17pm UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844/5 "2018-11-09T16:17:23Z")

</div>

> [@anandabits](#):
>
> The core team has spoken against disjunctions in constraints, not just in types (i.e. unions).

As I mentioned in my original post, this type of constraint already exists for classes (obviously because they're subtypes of themselves, but the point is that `B` with `B : A` constraint can be `A` with the `:` operator for classes). `:==` would be the same as `:` for classes but also lift the limitations of expressibility for existentials and protocols.

> [@anandabits](#):
>
> Isn't the plan to eventually lift the limitation of self conformance in some way? I view the discussion of doing that for `Error` as jumping ahead, similar to `AnyHashable` jumping ahead of generalized existentials. I don't view it as inconsistent with the direction of the language.

Well I might be short-sighted, because I cannot even imagine how they will eventually lift that restriction. It starts to hurt my brain if I think about self conforming protocols with associated types or inits.

That said, it's a pitch, so we can see where it goes. If it gets rejected, so be it. ;)

---

<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:** [November 9, 2018, 4:21pm UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844/6 "2018-11-09T16:21:07Z")

</div>

> [@DevAndArtist](#):
>
> As I mentioned in my original post, this type of constraint already exists for classes (obviously because they're subtypes of themselves, but the point is that `B` with `B : A` constraint can be `A` with the `:` operator for classes). `:==` would be the same as `:` for classes but also lift the limitations of expressibility for existentials and protocols.

I think what you are proposing is substantially different than superclass constraints but I'll let those more knowledgable than I am speak to it. 🙂

> [@DevAndArtist](#):
>
> Well I might be short-sighted, because I cannot even imagine how they will eventually lift that restriction. It starts to hurt my brain if I think about self conforming protocols with associated types or inits.

By "in some way" I meant in some contexts. It isn't possible to lift the limitation across the board. I think generalized existentials will help in some contexts.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [November 9, 2018, 4:41pm UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844/7 "2018-11-09T16:41:03Z")

</div>

I'll note that unlike general disjunctions this one is probably more well-behaved, and not too difficult to implement. But I think it's dodging the real problem, which is that `Error`-the-protocol-value-type doesn't conform to `Error`-the-protocol (see [SE-55](https://bugs.swift.org/browse/SR-55)). If and when we are able to make that work—which is similar to generalized existentials—then we should be able to use a normal `:` constraint here without modification.

---

<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 9, 2018, 4:50pm UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844/8 "2018-11-09T16:50:13Z")

</div>

I tried to understand the issue-ticket, but I failed to see your point in it. I learned that protocols do not conform to themselves, nor do (composed) existentials which is totally fine by me to this date. However it does not mean I don't know the limitations it creates, I've been there myself. Can you clarify for me what you meant by `Error-the-protocol-value-type`?

Here is a simple example:

```swift
protocol P { func bar() }

// Before (2 functions):
func foo<T>(_ value: T) -> T where T : P {
  value.bar()
  return value
}
func foo(_ value: P) -> P { ... }

// After:
func foo<T>(_ value: T) -> T where T :== P {
  value.bar()
  return value
}

struct S : P { 
  func bar() {
    print(type(of: self))
  }
}
let s = S()
let p: P = s
foo(s) // prints "S" returns `S`
foo(p) // prints "S" returns `P`

```

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [November 9, 2018, 5:04pm UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844/9 "2018-11-09T17:04:23Z")

</div>

> [@DevAndArtist](#):
>
> I learned that protocols do not conform to themselves, nor do (composed) existentials which is totally fine by me to this date. However it does not mean I don't know the limitations it creates, I've been there myself.

I just think trying to find a solution to that is a better long-term answer to this problem, rather than a special kind of generic to work around it. The work to implement this special case seems like it'd be nearly the same as the general thing.

That said, if we end up _not_ doing self-conforming protocols (because they have problems too, like how `init` requirements should work), this or something else might be necessary to say "no, it's okay, I promise to only use this like an existential even though I want to be able to preserve the type when I have it".

> [@DevAndArtist](#):
>
> Can you clarify for me what you meant by `Error-the-protocol-value-type` ?

I was trying very hard not to say "existential". The distinction between the `Error` in `let x: Error` and the error in `enum Foo: Error`.

---

<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 9, 2018, 5:09pm UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844/10 "2018-11-09T17:09:43Z")

</div>

> [@jrose](#):
>
> That said, if we end up _not_ doing self-conforming protocols (because they have problems too, like how `init` requirements should work), this or something else might be necessary to say "no, it's okay, I promise to only use this like an existential even though I want to be able to preserve the type when I have it".

If I got your point now correctly, then basically you meant to say this approach or maybe another can be considered as an alternative if self conforming protocols / existentials will fail or impossible to achieve?!

> [@jrose](#):
>
> I was trying very hard not to say "existential". The distinction between the `Error` in `let x: Error` and the error in `enum Foo: Error` .

That is totally fine by me, because I understand it. :)

Thank you for your feedback.

---

<div class="post-metadata">

**Author:** ![Slava\_Pestov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/slava_pestov/32/30204_2.png) [@Slava\_Pestov](https://forums.swift.org/u/Slava_Pestov)\
**Post date:** [November 9, 2018, 6:17pm UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844/11 "2018-11-09T18:17:32Z")

</div>

> [@jrose](#):
>
> If and when we are able to make that work—which is similar to generalized existentials—then we should be able to use a normal `:` constraint here without modification.

I think it's simpler because the representational issue is not there. Error is a single retainable pointer, just like @objc protocol existentials, so it can self-conform.

---

<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:** [November 9, 2018, 6:40pm UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844/12 "2018-11-09T18:40:27Z")

</div>

> [@Slava\_Pestov](#):
>
> I think it's simpler because the representational issue is not there. Error is a single retainable pointer, just like @objc protocol existentials, so it can self-conform.

It's simpler for `Error` but how far does that generalize? Aren't we talking about a general feature here and not something specific to `Error`?

---

<div class="post-metadata">

**Author:** ![L\_Mihalkovic](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/l_mihalkovic/32/5802_2.png) [@L\_Mihalkovic](https://forums.swift.org/u/L_Mihalkovic)\
**Post date:** [February 28, 2019, 8:12am UTC](https://forums.swift.org/t/additional-type-constraint-for-the-where-clause/17844/13 "2019-02-28T08:12:54Z")

</div>

8 years into the marvellous innovation of Protocol Oriented Programming and protocols still do not conform to self .. I know .. pride and all .. but you have to be able to laugh about it sometimes, no?!? 🙂 for the 10y anniversary, perhaps? 🙂  
(self irony is healthy)
