Protocol typed property in protocols

Currently the following piece of code does not compile :

protocol P {}
struct A: P {}
protocol Q {
    var p: P { get }
struct B: Q {
    var p = A()

The compiler raise the error: Type 'B' does not conform to protocol 'Q'
One way to workAround this problem is to declare a private variable of type A and for the variable p to dynamically return a

struct B: Q {
    private var a = A()
    var p: P { return a }

It would be awesome if the compiler could recognize A implements P and recognize the first writting.

1 Like

Explicitly writing the type var p: P = A() will do for now.

1 Like

It would enable to satisfy the compiler but it would not enable to use p as an instance of type A
It can of course be used by casting to A each time we need it, but it would be great if the compiler handle all this by unederstanding A is implementing P

That is because you specified P as the concrete type of the variable. Writing

protocol P { ... }
struct Foo: P { ... }

protocol P1 {
    var foo: P { get }

doesn’t mean you can conform to P1 like this:

class Foo1: P1 {
    var foo: AnyTypeConformingToP = ...

since var p isn’t generic. It’s of type P.


if you want to do it that way, you have to go “generic”:

protocol P {}
struct A: P {}

protocol Q {
    associatedtype Type1: P
    var p: Type1 { get }

struct B: Q {
    typealias Type1 = A
    var p = A() // no problem

Maybe I am missing the obvious but what prevents the compiler to understand A is implmenting P kind of like polymorphism.

Your solution using protocol with associated type would work but defeat the purpose of anonymising B with a protocol since B cannot be casted as Q which "Can only be used a type constraint"
It could be stored using type erasure but we would have to specify the type of A and thus the variable could not be anonymised by the protocol P.
Maybe at this point there is another work around to anonymise the type A but it’s getting awfully complicated for something that should be that much don’t you agree?

If you’re asking why the compiler doesn’t infer var p = A() as P, it simply isn’t smart enough.

You can anonymize B if you don’t need to store it as Q.

Because Q declares “Any type conforming to me, will have a property p whose type is an existential that can store any value conforming to P.”

Suppose we make a protocol R that refines Q to require p is mutable:

protocol R: Q {
  var p: P { get set }

Then we can write an extension method on R that sets p to something:

struct C: P {}

extension R {
  mutating func foo() {
    p = C()

And now, to bring it all together, we can retroactively conform B to R:

extension B: R {}

This all works exactly as it says, and it means we can set the value of B.p to an instance of C.

1 Like

It much clearer to me why it’s not possible.
Thanks a lot for taking the time of explaining it to me.

This is a reasonable in request. In general, it makes sense for the witness to be a subtype of the protocol requirement. For example, if the protocol requires a method returning Any, it makes sense for the conforming type to provide a method returning Int, since every method returning Int is also a method returning Any, etc.

The canonical JIRA bug for this is A contributor started working on implementing this, but unfortunately it was abandoned:

If someone is interested in dusting this off though, it should probably go through evolution discussion, and would need to be gated on -swift-version <N> since it’s source breaking. There are also some subtle issues to resolve, for example if multiple witnesses match a single requirement, how do you rank them? Or what if a default in an extension matches exactly, but another method in the type itself is an inexact match?


If B defines a property whose type is a subtype of P, then B cannot conform to R, because the property requirement is mutable. However for an immutable property requirement there is no such difficulty, and the conformance could be allowed.


It does make sense, but it violates Liskov substitution.

protocol P {
    var foo: UIView { get set }

class A: P {
    var foo: UIButton = UIButton()

let a = A()
var p: P = a = UIView() // or UIDatePickerView for instance ?

It’s fine if it’s a get-only though ;)


If the property is settable, sure. If the property requirement in the protocol is read-only, its equivalent to a method returning a value of that type.

Hello @Slava_Pestov I would like to give it a try but unfortunatelly the closest I’ve come to C++ is programming in C and I am not really familar with the swift compiler project, however I am quite tenacious, if you could pinpoint me to something that could help me understand how the compiler handle this issue, I will gladly give it a go.