Ejemplo n.º 1
0
  /**
   * 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);
  }