# More problems with Swift's type system

**URL:** <https://forums.swift.org/t/more-problems-with-swifts-type-system/60231>\
**Category:** Using Swift\
**Tags:** associatedtype, opaque-types, identifiable\
**Created:** [September 11, 2022, 4:23pm UTC](https://forums.swift.org/t/more-problems-with-swifts-type-system/60231 "2022-09-11T16:23:28Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![realh](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/realh/32/15275_2.png) [@realh](https://forums.swift.org/u/realh)\
**Post date:** [September 11, 2022, 4:23pm UTC](https://forums.swift.org/t/more-problems-with-swifts-type-system/60231/1 "2022-09-11T16:23:28Z")

</div>

I want to define a set of types like this:

```swift
protocol UserProfile {
    var userId: String? { get set }
    // ...
}

// UserProfile also has several extensions

protocol AvatarImageCache: NSObject {
    var imageURL: String? { get set }
    var imageLoadError: Bool { get set }
    var image: Image? { get set }
}

protocol UserProfileWithAvatar: UserProfile, AvatarImageCache, Identifiable where ID == String {
    var id: String { get }
}

extension UserProfileWithAvatar {
    var id: String { userId ?? "" }
}

struct GroupMember {
    let user: UserProfileWithAvatar // error here
    let addedAt: Date
}

```

This gives the dreaded error, `Protocol 'UserProfileWithAvatar' can only be used as a generic constraint because it has Self or associated type requirements`. If I remove the `Identifiable` clause from UserProfileWithAvatar, that error goes away, so it seems like `Identifiable` is the source of the problem. But why? I've declared the type of ID in the way XCode recommends, so what's the problem? If I need to redeclare it in the struct, how? Adding a similar where clause there gives another error.

There's more. I also tried moving the `Identifiable` conformance/inheritance clause to the extension:

```swift
extension UserProfileWithAvatar: Identifiable {
    typealias ID = String
    var id: String { userId ?? "" }
}

```

For some reason I can't use `where ID == String` in this context, but even after fixing that error, I get a new one: `Extension of protocol 'UserProfileWithAvatar' cannot have an inheritance clause`. Declaring conformance to other protocols in extensions is usually allowed, so what's special about this one? I've also tried removing `AvatarImageCache` in case its inheritance of `NSObject` was clashing with some undocumented part of `Identifiable`, but that didn't change these errors either.

Perhaps I don't even need to declare conformance to `Identifiable` anyway? I want it so I can display a SwiftUI `ForEach` view that iterates over a collection of `UserProfileWithAvatar` (FWIW the protocol is implemented by two classes, one for the local user and one for remote users). `ForEach` requires that elements conform to `Identifiable`. ['Class types' have a default implementation of Identifiable](https://developer.apple.com/documentation/Swift/Identifiable#Conforming-to-the-Identifiable-Protocol) but even that's slightly ambiguous. Do they mean any object instances, or only instances of SomeClass.self? If it's all class objects, that should work for me, because `AvatarImageCache` forces conformance with `NSObject` (for the sake of mutability), but I doubt it will be that easy, because Swift always seems to throw obstructions in my path.

If the previous paragraph doesn't hold the solution, I suppose I could move the `Identifiable` to `struct GroupMember`, but I'd rather keep that as a private implementation detail.

---

<div class="post-metadata">

**Author:** ![suyashsrijan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/suyashsrijan/32/5292_2.png) [@suyashsrijan](https://forums.swift.org/u/suyashsrijan)\
**Post date:** [September 11, 2022, 4:32pm UTC](https://forums.swift.org/t/more-problems-with-swifts-type-system/60231/2 "2022-09-11T16:32:44Z")

</div>

Your original code compiles fine in Swift 5.7, with one small modification:

```swift
struct GroupMember {
    let user: any UserProfileWithAvatar // Adding ‘any’ prefix
   …
}

```

The “self or associatedtype” restriction was lifted by SE-0309 and SE-0335.

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [September 11, 2022, 7:19pm UTC](https://forums.swift.org/t/more-problems-with-swifts-type-system/60231/3 "2022-09-11T19:19:16Z")

</div>

> [@realh](#):
>
> I get a new one: `Extension of protocol 'UserProfileWithAvatar' cannot have an inheritance clause`. Declaring conformance to other protocols in extensions is usually allowed, so what's special about this one?

Declaring that one protocol refines another in an extension has never been allowed.

---

<div class="post-metadata">

**Author:** ![realh](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/realh/32/15275_2.png) [@realh](https://forums.swift.org/u/realh)\
**Post date:** [September 11, 2022, 7:54pm UTC](https://forums.swift.org/t/more-problems-with-swifts-type-system/60231/4 "2022-09-11T19:54:00Z")

</div>

> [@xwu](#):
>
> Declaring that one protocol refines another in an extension has never been allowed.

Oh. Do you mean:

```swift
extension Something: SomethingElse {
    // ...
}

```

is only valid if the first `Something` is a concrete type, and invalid if it's a protocol?

---

<div class="post-metadata">

**Author:** ![realh](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/realh/32/15275_2.png) [@realh](https://forums.swift.org/u/realh)\
**Post date:** [September 11, 2022, 7:59pm UTC](https://forums.swift.org/t/more-problems-with-swifts-type-system/60231/6 "2022-09-11T19:59:03Z")

</div>

> [@suyashsrijan](#):
>
> our original code compiles fine in Swift 5.7, with one small modification:
> 
> ```swift
> struct GroupMember {
> let user: any UserProfileWithAvatar // Adding ‘any’ prefix
> …
> }
> 
> ```

That's good to know. I think I have encountered the `any` keyword in an article or tutorial, but I forgot about it.

---

<div class="post-metadata">

**Author:** ![tgoyne](https://avatars.discourse-cdn.com/v4/letter/t/5e9695/32.png) [@tgoyne](https://forums.swift.org/u/tgoyne)\
**Post date:** [September 11, 2022, 9:16pm UTC](https://forums.swift.org/t/more-problems-with-swifts-type-system/60231/7 "2022-09-11T21:16:39Z")

</div>

> [@realh](#):
>
> Oh. Do you mean:
> 
> ```swift
> extension Something: SomethingElse {
> // ...
> }
> 
> ```
> 
> is only valid if the first `Something` is a concrete type, and invalid if it's a protocol?

Correct. This is one of the places where Swift using the same syntax for inheritance and protocol conformance is confusing. `Foo: Bar` is inheritance if both `Foo` and `Bar` are either protocols or classes, and it's protocol conformance if `Foo` is a class and `Bar` is a protocol (and an error if `Foo` is a protocol and `Bar` is a class). You can't inherit in an extension for either classes or protocols.
