0

Regardless of the variance of parameter on the left side, the constraints placed on Ta and Tb in the following declaration fail the typecheck:

class A<+TCov, -TCon, [±]Ta as TCov, [±]Tb super TCon> {
  public function __construct(private Ta $ta, private Tb $tb) {}
  // [various methods making use of Ta and Tb]
}

It's worth noting that the empty class declaration doesn't raise errors, but once the constrained parameters are used (in otherwise valid positions given their own variances), the typechecker raises one of the following:

Illegal use of covariant type parameter (Typing[4120])... as constraints are contravariant

Illegal use of contravariant type parameter (Typing[4121])... super constraints are covariant

with reference to the parameter on the right side of the constraint.

I can more understand why generic methods pose problems. The violating positions are fairly obvious, and using the arguments in positions matching the variance of their constraints are impossible:

class A<+TCov, -TCon> {
  public function cov_violate<T as TCov>(T $v): void {
    // T can be cast to TCov and violate type if the original type is a subtype of T
  }
  public function con_violate<T super TCon>(): T {
    // vice versa for the contravariant parameter
  }

  public function cov_impossible<T as TCov>(): T {
    // how will we produce a T-typed value?
  }
  public function con_impossible<T super TCov>(T $v): void {
    // what will we do with a T-typed value?
  }
}

But what is the problem with class-wide parameters? For all six errant relationships ({+|-| }T as +TCov and {+|-| }T super -TCon) I can't think up a scenario where these wouldn't be type-safe. In my mind, their variances seem to either restrict their casting direction or their positions sufficiently to let declaring these relationships be safe.

Community
  • 1
  • 1
concat
  • 3,107
  • 16
  • 30

1 Answers1

0

I was running 3.13.1 at the time of this question, but luckily the restriction has been relaxed to allow this subtyping of class type parameters as of HHVM 3.14.4 by this commit! The commit also points to this Microsoft paper for a proof of soundness.

concat
  • 3,107
  • 16
  • 30