为什么类范围的上限约束不能协变,而下限约束在Hack中是逆变的?

时间:2016-08-01 17:50:39

标签: covariance contravariance type-constraints hacklang

无论左侧参数的方差如何,以下声明中TaTb上的约束都无法进行类型检查:

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]
}

值得注意的是,空类声明不会引发错误,但是一旦约束参数使用(在其他有效位置给出它们自己的方差),typechecker会引发以下其中一项:

  

非法使用协变类型参数(打字[4120])...... as约束是逆变的

     

非法使用逆变型参数(打字[4121])...... super约束是协变的

参考约束右侧的参数。

我可以更好地理解为什么泛型方法会带来问题。违规位置是相当明显的,并且在匹配其约束方差的位置使用参数是不可能的:

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?
  }
}

但是类范围的参数有什么问题?对于所有六种错误关系({+|-| }T as +TCov{+|-| }T super -TCon),我无法想到这些关系不是类型安全的情况。在我看来,他们的差异似乎要么限制他们的演员方向或他们的位置,以便宣布这些关系是安全的。

1 个答案:

答案 0 :(得分:0)

在这个问题的时候,我正在运行3.13.1,但幸运的是,限制已经放宽,允许{HHVM 3.14.4的类型参数的子类型由this commit完成!提交还指向this Microsoft paper以获得稳健性证明。