Subclasses of TUConstraint represent constraints between type parameter whose type arguments
are being inferred and the types used to do that inference. These constraints are used by
the TASolver to infer arguments.
TU constraints come in the classic form of subtype, supertype, and equality constraints.
T <: U - implies T is a subtype of U, it is represented by TSubU
T >: U - implies T is a supertype of U, it is represented by TSuperU
T = U - implies T is equal to U, it is represented by TIsU
Note, it is important that the type parameter is represented by an AnnotatedTypeVariable
because if a use of the type parameter has a primary annotation, then the two types
represented in by a TUConstraint are NOT constrained in the hierarchy of that annotation.
e.g.
<T> void method(List<@NonNull T> t1, T t2)
method(new ArrayList<@NonNull String>(), null);
The above method call would eventually be reduced to
constraints:
[@NonNull String == @NonNull T, @Nullable null <: T]
In this example, if we did not ignore the first constraint then the type argument
would be exactly @NonNull String and the second argument would be invalid. However,
the correct inference would be @Nullable String and both arguments would be valid.