On Thursday, September 10, 2015 at 11:38:48 PM UTC-7, Jukka Lehtosalo wrote:
The proposal doesn't spell out the rules for subtyping, but we should follow the ordinary rules for subtyping for functions, and return types would behave covariantly. So the answer is yes.
Ok. Note that this introduces some weird corner cases when trying to decide whether a class implements a protocol. Consider class P(Protocol): def f() -> P class A: def f() -> A It would be both valid to say that A *does not* implement P (because the return value of f is incompatible with P) as it would be to say that A *does* implement it (because once it does, the return value of f becomes compatible with P). For a more quirky example, consider class A(Protocol): def f(self) -> B def g(self) -> str class B(Protocol): def f(self) -> A def g(self) -> float class C: def f(self) -> D: return self.x def g(self): return self.y class D: def f(self) -> C: return self.x def g(self): return self.y Short of introducing intersection types, the protocols A and B are incompatible (because the return types of g() are mutually exclusive). Hence, C and D can, respectively, conform to either A or B, but not both. So the possible assignments are: C -> A D -> B *or* C -> B D -> A . It seems undecidable which of the two is the right one. (The structural type converter in pytype solves this by dropping the "mutually exclusive" constraint to the floor and making A and B both a C *and* a D, which you can do if all you want is a name for an anonymous structural type, But here you're using your structural types in type declarations, so that solution doesn't apply) Matthias