JLS defined a concept called "constraint formula". There is a formal definition:
Constraint formulas are assertions of compatibility or subtyping that may involve inference variables. The formulas may take one of the following forms:
‹Expression → T›: An expression is compatible in a loose invocation context with type T (§5.3).
‹S → T›: A type S is compatible in a loose invocation context with type T (§5.3).
‹S <: T›: A reference type S is a subtype of a reference type T (§4.10).
‹S <= T›: A type argument S is contained by a type argument T (§4.5.1).
‹S = T›: A reference type S is the same as a reference type T (§4.3.4), or a type argument S is the same as type argument T.
‹LambdaExpression →throws T›: The checked exceptions thrown by the body of the LambdaExpression are declared by the throws clause of the function type derived from T.
‹MethodReference →throws T›: The checked exceptions thrown by the referenced method are declared by the throws clause of the function type derived from T.
I have some misunderstanding about it. As far as I've understood we have a set of all Java types, denote it by M
. Could we say, that any constraint formula defines a subset of M
, for instance
‹S <: T› = {S | (S belongs to M) and (S is a subtype of T) }