2016-08-01 26 views
0

無論左側參數的方差,約束在下面的聲明放在TaTb失敗類型檢測:爲什麼不能將全局上界約束變爲協變,而下界約束在Hack中是否是逆變的?

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),我無法想象這些類型不安全的情況。在我看來,他們的差異似乎要麼足以限制他們的投射方向或他們的位置,以便讓這些關係安全。

回答

0

我在這個問題的時間運行3.13.1,但幸運的是,限制已經放寬,允許這種類型參數的子類型,如HHVM 3.14.4的this commit!該提交也指出this Microsoft paper爲證明健全性。