2016-08-01 1 views
0

Quelle que soit la variance du paramètre sur le côté gauche, les contraintes imposées sur Ta et Tb dans la déclaration suivante trahissons le typecheck:Pourquoi les contraintes de la limite supérieure de la classe ne peuvent-elles pas être covariantes et les contraintes de la limite inférieure sont-elles contravariantes dans 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] 
} 

Il convient de noter que la déclaration de classe vide ne soulève pas d'erreurs, mais une fois que les paramètres sont contraints utilisés (dans des positions par ailleurs valides compte tenu de leurs propres écarts), le typechecker soulève une des opérations suivantes:

l'utilisation illégale du paramètre de type covariant (Taper [4120]) ... as contraintes sont contravariant

utilisation illégale de paramètre de type contravariant (Typing [4121]) ... super contraintes sont covariant

en référence au paramètre sur le côté droit de la contrainte.

Je peux mieux comprendre pourquoi les méthodes génériques posent problème. Les positions sont assez évidentes qui violent, et en utilisant les arguments dans des positions correspondant à la variance de leurs contraintes sont impossibles:

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

Mais quel est le problème avec les paramètres de classe à l'échelle? Pour les six relations errantes ({+|-| }T as +TCov et {+|-| }T super -TCon) je ne peux pas imaginer un scénario où ceux-ci ne seraient pas sécurisés. Dans mon esprit, leurs variances semblent soit limiter leur direction de casting ou leurs positions suffisamment pour laisser déclarer ces relations être en sécurité.

Répondre

0

Je fonctionnais 3.13.1 au moment de cette question, mais heureusement la restriction a été assouplie pour permettre ce sous-typage des paramètres de type de classe à partir de HHVM 3.14.4 par this commit! Le commit pointe également à this Microsoft paper pour une preuve de solidité.