/** * Determines what constraint (supertype, subtype or equal) should be generated for type parameter * {@code T} in a constraint like (in this example subtype one): <br> * {@code MyClass<in/out/- A> <: MyClass<in/out/- B>}, where {@code MyClass<in/out/- T>} is * declared. <br> * The parameters description is given according to the example above. * * @param typeParameterVariance declared variance of T * @param subjectTypeProjection {@code in/out/- A} * @param constrainingTypeProjection {@code in/out/- B} * @param upperConstraintKind kind of the constraint {@code MyClass<...A> <: MyClass<...B>} * (subtype in this example). * @return kind of constraint to be generated: {@code A <: B} (subtype), {@code A >: B} * (supertype) or {@code A = B} (equal). */ @NotNull private static ConstraintKind getTypeParameterConstraintKind( @NotNull Variance typeParameterVariance, @NotNull TypeProjection subjectTypeProjection, @NotNull TypeProjection constrainingTypeProjection, @NotNull ConstraintKind upperConstraintKind) { // If variance of type parameter is non-trivial, it should be taken into consideration to infer // result constraint type. // Otherwise when type parameter declared as INVARIANT, there might be non-trivial use-site // variance of a supertype. // // Example: Let class MyClass<T> is declared. // // If super type has 'out' projection: // MyClass<A> <: MyClass<out B>, // then constraint A <: B can be generated. // // If super type has 'in' projection: // MyClass<A> <: MyClass<in B>, // then constraint A >: B can be generated. // // Otherwise constraint A = B should be generated. Variance varianceForTypeParameter; if (typeParameterVariance != INVARIANT) { varianceForTypeParameter = typeParameterVariance; } else if (upperConstraintKind == SUPER_TYPE) { varianceForTypeParameter = constrainingTypeProjection.getProjectionKind(); } else if (upperConstraintKind == SUB_TYPE) { varianceForTypeParameter = subjectTypeProjection.getProjectionKind(); } else { varianceForTypeParameter = INVARIANT; } return getTypeParameterConstraintKind(varianceForTypeParameter, upperConstraintKind); }