Properly localize require ancestors in Typing_subtype
Summary:
We did not properly substitute type parameters when upcasing to a required ancestor. This diff fixes this by making sure we create the `ety_env` the same for both branches of our upcasting algorithm. In order to avoid unnecessary error reporting I hade to make the creation of `ety_env` lazy.
The added test case shows how it arises.
```
abstract class Expression<Tresult> {}
abstract class Evaluator<T, Texpression as Expression<T>> {}
class LiteralEvaluator<T, Texpression as ILiteralExpression<T>>
extends Evaluator<T, Texpression> {}
interface ILiteralExpression<TlitResult> {
require extends Expression<TlitResult>;
}
```
Here when we are checking if `ILiteralExpression<T> <: Expression<T>` we utilize the require extends to upcast `ILiteralExpression` to `Expression`. Before the diff we would not instantiate the type parameter correctly so we would end up checking `Expression<TlitResult> <: Expression<T>` which would fail because `TlitResult` and `T` are different generics. Note taht if `TlitResult` was named `T` then it would pass because now the type parameters have the same name, even though the type parameter was not properly instantiated.
{
D2613160} revealed this particular issue because now with scoping we can tell that `ILiteralExpression\T` is different than `LiteralEvaluator\T`.
Reviewed By: andrewjkennedy
Differential Revision:
D3561665
fbshipit-source-id:
907ecaaabb9eff63a4e8e4d38bc01137ac023f4c