Fix computation of variance of generic type parameters occurring as roots of type accesses
Summary:
Previously we assumed that generic type parameters cannot occur in type accesses of the form `A::TB::TC`. Here `A` is a type (e.g., a class) and `TB` and `TC` are type constant names. We assumed that `A` couldn't be a generic type parameter. And indeed, one cannot project type constants off of a generic as in
```
<?hh
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
interface HasFoo {
abstract const type TFoo;
public function getFoo(): this::TFoo;
}
function test<T as HasFoo>(T $x): T::TFoo {
return $x->getFoo();
}
```
This produces
```
T must be an identifier for a class, "self", or "this" (Naming[2061])
```
However, it **is** possible to use projections off of generics in `where` constraints, so the above can be written (a bit awkwardly) as follows:
```
<?hh
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
interface HasFoo {
abstract const type TFoo;
public function getFoo(): this::TFoo;
}
function test<T as HasFoo, TFoo>(T $x): TFoo where TFoo = T::TFoo {
return $x->getFoo();
}
```
This example type checks but produces a lint warning about a redundant generic `T`. This is because we fail to account for the occurrence of `T` in the type `T::TFoo` inside the `where` constraint.
Reviewed By: kmeht
Differential Revision:
D16916838
fbshipit-source-id:
fabec480222e37453b7d02f027103746c9efcb10