covariance - Why can't class-wide upper-bound constraints be covariant and lower-bound constraints be contravariant in Hack? -


regardless of variance of parameter on left side, constraints placed on ta , tb in following declaration fail typecheck:

class a<+tcov, -tcon, [±]ta tcov, [±]tb super tcon> {   public function __construct(private ta $ta, private tb $tb) {}   // [various methods making use of ta , tb] } 

it's worth noting empty class declaration doesn't raise errors, once constrained parameters used (in otherwise valid positions given own variances), typechecker raises 1 of following:

illegal use of covariant type parameter (typing[4120])... as constraints contravariant

illegal use of contravariant type parameter (typing[4121])... super constraints covariant

with reference parameter on right side of constraint.

i can more understand why generic methods pose problems. violating positions obvious, , using arguments in positions matching variance of constraints impossible:

class a<+tcov, -tcon> {   public function cov_violate<t tcov>(t $v): void {     // t can cast tcov , violate type if original type subtype of t   }   public function con_violate<t super tcon>(): t {     // vice versa contravariant parameter   }    public function cov_impossible<t tcov>(): t {     // how produce t-typed value?   }   public function con_impossible<t super tcov>(t $v): void {     // t-typed value?   } } 

but problem class-wide parameters? 6 errant relationships ({+|-| }t +tcov , {+|-| }t super -tcon) can't think scenario these wouldn't type-safe. in mind, variances seem either restrict casting direction or positions sufficiently let declaring these relationships safe.

i running 3.13.1 @ time of question, luckily restriction has been relaxed allow subtyping of class type parameters of hhvm 3.14.4 this commit! commit points this microsoft paper proof of soundness.


Comments