I think we want path-dependent types here.
protocol P {
associatedtype B: Class
var b: B { get }
func takesB(_: B)
}
func takesP(p1: P, p2: P) {
let b1 = p1.b
let b2 = p2.b
p1.takesB(b1) // ok
p2.takesB(b1) // error: b1 may be of the wrong type
p2.takesB(b2) // ok
p1.takesB(b2) // error: b2 may be of the wrong type
}