Permit generic methods to override their own instantiations
Summary:
It's sound to allow generic methods to override methods whose signature is (a supertype of) an instantiation of the generic one. For example,
```
function foo(int):int;
```
can be overridden by
```
function foo<T>(T):T;
```
To implement this, Hack needs to find *some* instantiation of `T` such that subtyping holds. This is just the usual "inference" problem, and can be implemented by substituting type variables for generic type parameters. Here is a more complex example involving type constants:
```
interface I { abstract const type TC as num; }
class B {
function foo(num):void;
}
class C<T as I> extends B {
function foo<TF>(TF):void where TF super T::TC;
}
```
We need to find a solution for type variable `#1` with `T::TC <: #1` (from the where constraint) such that `num <: #1` (by contravariance of parameter types). Clearly `#1:=num` is a solution, as `T::TC <: num` from the type constant bound.
Dually, suppose we have
```
class C<T as I> extends B {
function foo<TF>(TF):void where TF as T::TC;
}
```
This time, we need to find type variable `#1` with `#1 <: T::TC` such that `num <: #1`. i.e. by transitivity we must have `num <: T::TC` which doesn't hold, so there is no solution, and the override should be rejected.
A nice side-effect of this diff is that we can now override generic methods with a version in which the generic parameter is renamed. (This was an error previously!)
Reviewed By: vassilmladenov
Differential Revision:
D34582988
fbshipit-source-id:
15d764b3157531e6fd4ddb0f7b2db996bb53544a