Fix unsoundness in overriding of generic method with bound
commit8d32e7882c4510761ff551d1364416fb1e2dfec5
authorAndrew Kennedy <akenn@fb.com>
Mon, 6 Jul 2020 14:11:13 +0000 (6 07:11 -0700)
committerFacebook GitHub Bot <facebook-github-bot@users.noreply.github.com>
Mon, 6 Jul 2020 14:12:59 +0000 (6 07:12 -0700)
tree7453fecad97ed1066e8c6407dbef6480c8f6ef8c
parent3b5927fc1dd623ee6e7cfc6719c81b7d4ed91e8b
Fix unsoundness in overriding of generic method with bound

Summary:
There is a bug associated with overriding of generic methods with non-generic methods in generic classes, where the respective type parameters just happen to match. Consider this program (now added as a test case):
```
interface I1 {
  public function get<T>(T $in): void;
}

final class C1<T as string> implements I1 {
  final public function get(string $in): void {}
}
```
Hack checks that the overriding method is a "subtype" of the overridden method, with respect to a type environment that includes that type parameters (and any bounds or constraints) in the overridden method (the supertype). Unfortunately, if there is already a type parameter in the environment with the same name, it doesn't get "replaced". This diff properly resets the type parameters (using `localize_and_add_generic_parameters`) before applying subtyping.

We also take the opportunity to factor out subtyping on method *decls* into a separate file, and include the `subtype_method` code there too, as it is not used elsewhere.

As readers might observe, this still doesn't fix all soundness issues. What if the type parameter of `C1` is used in the signature of `C1::get`? In any case, shouldn't we require generic methods to have the same type parameter arity as the overridden method? That's for another diff.

Reviewed By: vsiles

Differential Revision: D22136502

fbshipit-source-id: e6523c36d0c2eadbd916f9cc2d5d812198c7b41b
hphp/hack/src/typing/typing_subtype_method.ml
hphp/hack/test/typecheck/constraints/override_generic_parameter_bad.php [new file with mode: 0644]
hphp/hack/test/typecheck/constraints/override_generic_parameter_bad.php.exp [new file with mode: 0644]