# Errors When Working with Generic Types

**URL:** <https://forums.swift.org/t/errors-when-working-with-generic-types/40522>\
**Category:** Using Swift\
**Created:** [September 23, 2020, 3:23am UTC](https://forums.swift.org/t/errors-when-working-with-generic-types/40522 "2020-09-23T03:23:59Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Wildchild9](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wildchild9/32/9397_2.png) [@Wildchild9](https://forums.swift.org/u/Wildchild9)\
**Post date:** [September 23, 2020, 3:23am UTC](https://forums.swift.org/t/errors-when-working-with-generic-types/40522/1 "2020-09-23T03:23:59Z")

</div>

I have been working on some generic code recently and encountered two issues. Here is a generalized version of the code:

```swift
protocol B: A where T == Self { }

extension B {
    func bar() -> [T]? {
        return [self]
    }
}

protocol A {
    associatedtype T: B
    func bar() -> [T]?
}

struct C<L, R>: A where L: A, R: A, L.T == R.T {
    var l: L
    var r: R
    typealias T = L.T
    
    func bar() -> [T]? {
        if let x = l.bar() {
            return x
        } else if let y = r.bar() {
            return y
        }
        return nil
    }
}

```

The above code builds like one would expect.

My first problem arose when I tried to add another conformance to `B`. I changed its declaration line to the following.

```swift
protocol B: A, CaseIterable where T == Self { } 

```

After doing this, for some reason on the line where I try to return `y`, I now get the error "Type of expression is ambiguous without more context". This is super confusing to me as I cannot understand why adding the requirement that `B` also be `CaseIterable` would cause Swift not to know the type of `y`.

Secondly, whenever I try to create a type to conform to `B`, as shown in the code below, I receive two error.

```swift
// Error: Type 'Foo' does not conform to protocol 'A'
// Error: Type 'Foo' does not conform to protocol 'B'
enum Foo: B { }  

```

If I add to `Foo` the line `typealias T = Self`, it builds properly, but I don't understand why Swift doesn't already know this as I state it in the definition of `B`. This problem can also be remedied by removing `where T == Self` in the declaration of `B` and adding `typealias T = Self` in the extension on `B`, but this produces an annoying warning that says "Typealias overriding associated type 'T' from protocol 'A' is better expressed as same-type constraint on the protocol" with a fix-it for its suggestion. Although when I click the fix-it, it changes it back to what I had originally and pops up the error for `Foo` again.

Any help to these problems would be appreciated. Thank you!

---

<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:** [September 23, 2020, 5:27am UTC](https://forums.swift.org/t/errors-when-working-with-generic-types/40522/2 "2020-09-23T05:27:21Z")

</div>

> [@Wildchild9](#):
>
> The above code builds like one would expect.

I’m not so sure I do expect that code to build.

Let’s simplify things a little by getting rid of the `bar()` method:

```swift
protocol B: A where T == Self { }
protocol A {
    associatedtype T: B
}

struct C<L, R>: A where L: A, R: A, L.T == R.T {
    var l: L
    var r: R
    typealias T = L.T
}

```

`C: A` requires `C.T: B`. This means for `typealias T ` to work, you need `L.T: B`. `B` requires `T == Self`. So `L.T == L`. Same goes for `R.T`.

Which is to say, the constraint `L.T == R.T` on `C` is the same as saying `L == R`, which is pointless and the compiler should tell you so:

```swift
struct S<L,R> where L == R { }
// error: Same-type requirement makes generic parameters ‘L’ and ‘R’ equivalent

```

And indeed, if you update the constraints on `L` and `R` to require `B` Instead of `A`, you get this error. Alternatively, you could try and define a concrete `C` and get a similar error:

```swift
struct SA: B { typealias T = SA }
struct SB: B { typealias T = SB }

let c: C<SA,SB>
// error: ‘C’ requires the types ‘SA.T’ (aka ‘SA’) and ‘SB.T’ (aka ‘SB’) be equivalent

```

So, I think the original code is malformed, but managed to slip through the compiler. Adding the `CaseIterable` stirs up this nonfunctional state a bit, getting it to spit out some other errors.

---

<div class="post-metadata">

**Author:** ![Wildchild9](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wildchild9/32/9397_2.png) [@Wildchild9](https://forums.swift.org/u/Wildchild9)\
**Post date:** [September 23, 2020, 1:38pm UTC](https://forums.swift.org/t/errors-when-working-with-generic-types/40522/3 "2020-09-23T13:38:27Z")

</div>

I don't think that it is correct that `L.T == R.T` is the same as saying `L == R`. You stated that `L.T == L` which is not true since `L` conforms to `A`, not `B`. I think it would be true to say though that `L.T.T == L.T` since `L.T: B`. In the actual example that this corresponds to `L` and `R` have different types all around my code, but `C`, `L`, and `R` do all share the same `T` value. And also since `T: B`, `T` also has the same `T` value, that is to say that `T == T.T`. I've written the rest of my code with the structure I initially outlined successfully when I removed the requirement that `B` also be `CaseIterable`, but when I add it in, it still creates the error highlighted above in `C.bar()`.

---

<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:** [September 23, 2020, 2:00pm UTC](https://forums.swift.org/t/errors-when-working-with-generic-types/40522/4 "2020-09-23T14:00:37Z")

</div>

> [@Wildchild9](#):
>
> I don't think that it is correct that `L.T == R.T` is the same as saying `L == R` . You stated that `L.T == L` which is not true since `L` conforms to `A` , not `B` . I think it would be true to say though that `L.T.T == L.T` since `L.T: B` .

edit: nope ~~If `L.T: B` then `L == L.T` because that is what `B` requires~~

---

<div class="post-metadata">

**Author:** ![Wildchild9](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wildchild9/32/9397_2.png) [@Wildchild9](https://forums.swift.org/u/Wildchild9)\
**Post date:** [September 23, 2020, 2:46pm UTC](https://forums.swift.org/t/errors-when-working-with-generic-types/40522/5 "2020-09-23T14:46:35Z")

</div>

In the following example, `L.T` and `L` are different types, but `L.T` and `L.T.T` are always the same type. As well `L` does not equal `R`, but as stipulated `L.T == R.T == C.T`.

```swift
protocol B: A where T == Self { }
extension B {
    func bar() -> T {
        return self
    }
}
protocol A {
    associatedtype T: B
    func bar() -> T
}

struct C<L, R>: A where L: A, R: A, L.T == R.T {
    var l: L
    var r: R
    typealias T = L.T
    
    func bar() -> T {
        return [l.bar(), r.bar()].randomElement()!
    }
}
struct D<P>: A where P: A {
    var p: P
    typealias T = P.T
    
    func bar() -> P.T {
        return p.bar()
    }
}
struct E<P>: A where P: A {
    var p: P
    typealias T = P.T
    
    func bar() -> P.T {
        return p.bar()
    }
}
enum Foo: B {
    typealias T = Self
    case a
}

let thing = C(l: E(p: D(p: Foo.a)), r: Foo.a)
print("C == \(type(of: thing))") // Type of C
print("C.T == \(type(of: thing.bar()))") // Type of C.T
print("C.T.T == \(type(of: thing.bar().bar()))") // Type of C.T.T
print("L == \(type(of: thing.l))") // Type of L
print("L.T == \(type(of: thing.l.bar()))") // Type of L.T
print("L.T.T == \(type(of: thing.l.bar().bar()))") // Type of L.T.T
print("R == \(type(of: thing.r))") // Type of R
print("R.T == \(type(of: thing.r.bar()))") // Type of R.T
print("R.T.T == \(type(of: thing.r.bar().bar()))") // Type of R.T.T

// Prints:
// C == C<E<D<Foo>>, Foo>
// C.T == Foo
// C.T.T == Foo
// L == E<D<Foo>>
// L.T == Foo
// L.T.T == Foo
// R == Foo
// R.T == Foo
// R.T.T == Foo

```

As you can see in this demonstration, for all the types `*.T == *.T.T`, although, `*` does not necessarily equal `*.T`, except when `*: B` (which it does in the case of `Foo` and subsequently `R`). Is there something wrong with this code @Ben_Cohen?

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [September 23, 2020, 3:11pm UTC](https://forums.swift.org/t/errors-when-working-with-generic-types/40522/6 "2020-09-23T15:11:19Z")

</div>

A much smaller example:

```swift
protocol A {
  associatedtype T: CaseIterable
}

extension A where Self == T {
  // Error: Cannot convert return expression
  // of type 'Self' to return type 'Self.T'
  func bar() -> T { self }
}

```

Looks like all that's needed is the `T: CaseIterable`. I tried `Equatable` and `Hashable` so PAT is probably not the problem here.

Note:

Ran on Swift Playground (v. 3.3.1), so Swift 5.1.

---

<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:** [September 23, 2020, 3:20pm UTC](https://forums.swift.org/t/errors-when-working-with-generic-types/40522/7 "2020-09-23T15:20:06Z")

</div>

Yeah, I was mixed up about the `B` self constraint.

Here's a different reduction:

```swift
protocol B: CaseIterable { }
protocol A {
    associatedtype T: B
    func bar() -> T
}

struct C<L: A, R: A>: A where L.T == R.T {
    var l: L
    var r: R
    typealias T = L.T
    
    func bar() -> T {
      r.bar()
    }
}

```

Which prints "error: cannot convert return expression of type 'R.T' to return type 'C\<L, R\>.T' (aka 'L.T')", which directly contradicts the constraint.

Whatever it is, it does seem specific to something about `CaseIterable`.

---

<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:** [September 23, 2020, 3:28pm UTC](https://forums.swift.org/t/errors-when-working-with-generic-types/40522/8 "2020-09-23T15:28:26Z")

</div>

Here's @Lantua's version replacing `CaseIterable` with a simpler protocol...

```swift
public protocol P {
    associatedtype T: Sequence where Self == Self.T.Element
}

protocol A {
  associatedtype T: P
}

extension A where Self == T {
  // Error: Cannot convert return expression
  // of type 'Self' to return type 'Self.T'
  func bar() -> T { self }
}

```

---

<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:** [September 23, 2020, 3:33pm UTC](https://forums.swift.org/t/errors-when-working-with-generic-types/40522/9 "2020-09-23T15:33:53Z")

</div>

And here it is fully contained:

```swift
protocol I {
  associatedtype E
}

protocol S {
    associatedtype E where Self.E == Self.It.E
    associatedtype It: I
}

protocol P {
    associatedtype T: S where Self == Self.T.E
}

protocol A {
  associatedtype T: P
}

extension A where Self == T {
  // Error: Cannot convert return expression
  // of type 'Self' to return type 'Self.T'
  func bar() -> T { self }
}

```

---

<div class="post-metadata">

**Author:** ![Wildchild9](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wildchild9/32/9397_2.png) [@Wildchild9](https://forums.swift.org/u/Wildchild9)\
**Post date:** [September 24, 2020, 12:48am UTC](https://forums.swift.org/t/errors-when-working-with-generic-types/40522/10 "2020-09-24T00:48:57Z")

</div>

So just to be clear, this is definitely a bug since the code seems to clearly be ignoring the `Self == T` constraint.
