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 contravariantillegal 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
Post a Comment