Restricting a protocol's associated type to protocols

Given


protocol P {
   typealias T
   func foo(t: T) // e.g.
}


I can do:


struct Baz<Y> {
    let action: (Y) -> Void
}

extension P {
    func bar(t: T) -> (baz: Baz<T>) -> Void  {
        return { baz in baz.action(t) }
    }
}


Is it possible to restrict T to being any protocol (AnyProtocol?) so that I can say


extension P {
    func bar<U where U: T, U: AnyObject>(u: U) -> (baz: Baz<T>) -> Void  {
        return { [unowned u = u] baz in baz.action(u) }
    }
}

Would the following conditional extension of P work for your use case?


extension P where T: AnyObject {
  func bar(u: T) -> (Baz<T>) -> Void  {
    return { [unowned u = u] baz in baz.action(u) }
  }
}

ObjectHub's solution seems like the way to go, but this is an interesting question for other reasons, too.


Even if there were an AnyProtocol constraint you could apply, I don't think it would help. Consider:


class Foo {}

protocol Bar {
    typealias T: Foo
    func bar<U: T>(u: U) // Err: Inheritance from non-protocol, non-class type Self.T
}


The compiler does enforce the "kind-of Foo" constraint, but only by checking it when a specific type declares conformity to P. When parsing the rest of the protocol, it doesn't seem to make the connection that Ts will always be Foos. The typealias is always going to be treated like an unkown type from the perspective of the protocol itself.


(In this particular case, you could just declare u as a T, since that would accept subclasses of T and thereby achieve the same result. But syntactically, the form shown ought to be valid.)

Unfortunately not, because that forces the T in Baz<T> to also be constrained to AnyObject, which is not the case in my case.


I solved my problem by checking at run time for object parameters and routing them through code that included [unowned u = u].

It just so happened that in my case the T in P would always be a protocol, and I was looking for a way to prevent a memory leak in closures. I resorted to checking at run time, which seems to have worked.

Restricting a protocol's associated type to protocols
 
 
Q