예제 #1
0
  private static boolean isMoreSpecific(
      @NotNull CallableMemberDescriptor a, @NotNull CallableMemberDescriptor b) {
    if (a instanceof SimpleFunctionDescriptor) {
      assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass();

      KotlinType aReturnType = a.getReturnType();
      assert aReturnType != null;
      KotlinType bReturnType = b.getReturnType();
      assert bReturnType != null;

      return KotlinTypeChecker.DEFAULT.isSubtypeOf(aReturnType, bReturnType);
    }
    if (a instanceof PropertyDescriptor) {
      assert b instanceof PropertyDescriptor : "b is " + b.getClass();

      if (((PropertyDescriptor) a).isVar() || ((PropertyDescriptor) b).isVar()) {
        return ((PropertyDescriptor) a).isVar();
      }

      // both vals
      return KotlinTypeChecker.DEFAULT.isSubtypeOf(
          ((PropertyDescriptor) a).getType(), ((PropertyDescriptor) b).getType());
    }
    throw new IllegalArgumentException("Unexpected callable: " + a.getClass());
  }
예제 #2
0
  public static boolean shouldRecordInitializerForProperty(
      @NotNull VariableDescriptor variable, @NotNull KotlinType type) {
    if (variable.isVar() || type.isError()) return false;

    if (TypeUtils.acceptsNullable(type)) return true;

    KotlinBuiltIns builtIns = getBuiltIns(variable);
    return KotlinBuiltIns.isPrimitiveType(type)
        || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getStringType(), type)
        || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getNumber().getDefaultType(), type)
        || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getAnyType(), type);
  }
  private VariableDescriptor createLoopParameterDescriptor(
      KtParameter loopParameter,
      KotlinType expectedParameterType,
      ExpressionTypingContext context) {
    components
        .modifiersChecker
        .withTrace(context.trace)
        .checkParameterHasNoValOrVar(loopParameter, VAL_OR_VAR_ON_LOOP_PARAMETER);

    KtTypeReference typeReference = loopParameter.getTypeReference();
    VariableDescriptor variableDescriptor;
    if (typeReference != null) {
      variableDescriptor =
          components.descriptorResolver.resolveLocalVariableDescriptor(
              context.scope, loopParameter, context.trace);
      KotlinType actualParameterType = variableDescriptor.getType();
      if (expectedParameterType != null
          && !KotlinTypeChecker.DEFAULT.isSubtypeOf(expectedParameterType, actualParameterType)) {
        context.trace.report(
            TYPE_MISMATCH_IN_FOR_LOOP.on(
                typeReference, expectedParameterType, actualParameterType));
      }
    } else {
      if (expectedParameterType == null) {
        expectedParameterType = ErrorUtils.createErrorType("Error");
      }
      variableDescriptor =
          components.descriptorResolver.resolveLocalVariableDescriptor(
              loopParameter, expectedParameterType, context.trace, context.scope);
    }

    checkVariableShadowing(context.scope, context.trace, variableDescriptor);

    return variableDescriptor;
  }
예제 #4
0
  /**
   * Two types are related, roughly, when one is a subtype or supertype of the other.
   *
   * <p>Note that some types have platform-specific counterparts, i.e. kotlin.String is mapped to
   * java.lang.String, such types (and all their sub- and supertypes) are related too.
   *
   * <p>Due to limitations in PlatformToKotlinClassMap, we only consider mapping of platform classes
   * to Kotlin classed (i.e. java.lang.String -> kotlin.String) and ignore mappings that go the
   * other way.
   */
  private static boolean isRelated(
      @NotNull KotlinType a,
      @NotNull KotlinType b,
      @NotNull PlatformToKotlinClassMap platformToKotlinClassMap) {
    List<KotlinType> aTypes =
        mapToPlatformIndependentTypes(TypeUtils.makeNotNullable(a), platformToKotlinClassMap);
    List<KotlinType> bTypes =
        mapToPlatformIndependentTypes(TypeUtils.makeNotNullable(b), platformToKotlinClassMap);

    for (KotlinType aType : aTypes) {
      for (KotlinType bType : bTypes) {
        if (KotlinTypeChecker.DEFAULT.isSubtypeOf(aType, bType)) return true;
        if (KotlinTypeChecker.DEFAULT.isSubtypeOf(bType, aType)) return true;
      }
    }

    return false;
  }
예제 #5
0
  @NotNull
  public OverrideCompatibilityInfo isOverridableByWithoutExternalConditions(
      @NotNull CallableDescriptor superDescriptor,
      @NotNull CallableDescriptor subDescriptor,
      boolean checkReturnType) {
    OverrideCompatibilityInfo basicOverridability =
        getBasicOverridabilityProblem(superDescriptor, subDescriptor);
    if (basicOverridability != null) return basicOverridability;

    List<KotlinType> superValueParameters = compiledValueParameters(superDescriptor);
    List<KotlinType> subValueParameters = compiledValueParameters(subDescriptor);

    List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
    List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();

    if (superTypeParameters.size() != subTypeParameters.size()) {
      for (int i = 0; i < superValueParameters.size(); ++i) {
        // TODO: compare erasure
        if (!KotlinTypeChecker.DEFAULT.equalTypes(
            superValueParameters.get(i), subValueParameters.get(i))) {
          return OverrideCompatibilityInfo.incompatible("Type parameter number mismatch");
        }
      }
      return OverrideCompatibilityInfo.conflict("Type parameter number mismatch");
    }

    KotlinTypeChecker typeChecker = createTypeChecker(superTypeParameters, subTypeParameters);

    for (int i = 0; i < superTypeParameters.size(); i++) {
      if (!areTypeParametersEquivalent(
          superTypeParameters.get(i), subTypeParameters.get(i), typeChecker)) {
        return OverrideCompatibilityInfo.incompatible("Type parameter bounds mismatch");
      }
    }

    for (int i = 0; i < superValueParameters.size(); i++) {
      if (!areTypesEquivalent(
          superValueParameters.get(i), subValueParameters.get(i), typeChecker)) {
        return OverrideCompatibilityInfo.incompatible("Value parameter type mismatch");
      }
    }

    if (checkReturnType) {
      KotlinType superReturnType = superDescriptor.getReturnType();
      KotlinType subReturnType = subDescriptor.getReturnType();

      if (superReturnType != null && subReturnType != null) {
        boolean bothErrors = subReturnType.isError() && superReturnType.isError();
        if (!bothErrors && !typeChecker.isSubtypeOf(subReturnType, superReturnType)) {
          return OverrideCompatibilityInfo.conflict("Return type mismatch");
        }
      }
    }

    return OverrideCompatibilityInfo.success();
  }
예제 #6
0
 @NotNull
 public static KotlinType getPrimitiveNumberType(
     @NotNull IntegerValueTypeConstructor numberValueTypeConstructor,
     @NotNull KotlinType expectedType) {
   if (noExpectedType(expectedType) || expectedType.isError()) {
     return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
   }
   for (KotlinType primitiveNumberType : numberValueTypeConstructor.getSupertypes()) {
     if (KotlinTypeChecker.DEFAULT.isSubtypeOf(primitiveNumberType, expectedType)) {
       return primitiveNumberType;
     }
   }
   return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
 }
예제 #7
0
 public boolean isBooleanOrSubtype(@NotNull KotlinType type) {
   return KotlinTypeChecker.DEFAULT.isSubtypeOf(type, getBooleanType());
 }
예제 #8
0
  @NotNull
  public OverrideCompatibilityInfo isOverridableByWithoutExternalConditions(
      @NotNull CallableDescriptor superDescriptor,
      @NotNull CallableDescriptor subDescriptor,
      boolean checkReturnType) {
    if (superDescriptor instanceof FunctionDescriptor
            && !(subDescriptor instanceof FunctionDescriptor)
        || superDescriptor instanceof PropertyDescriptor
            && !(subDescriptor instanceof PropertyDescriptor)) {
      return OverrideCompatibilityInfo.incompatible("Member kind mismatch");
    }

    if (!(superDescriptor instanceof FunctionDescriptor)
        && !(superDescriptor instanceof PropertyDescriptor)) {
      throw new IllegalArgumentException(
          "This type of CallableDescriptor cannot be checked for overridability: "
              + superDescriptor);
    }

    // TODO: check outside of this method
    if (!superDescriptor.getName().equals(subDescriptor.getName())) {
      return OverrideCompatibilityInfo.incompatible("Name mismatch");
    }

    OverrideCompatibilityInfo receiverAndParameterResult =
        checkReceiverAndParameterCount(superDescriptor, subDescriptor);
    if (receiverAndParameterResult != null) {
      return receiverAndParameterResult;
    }

    List<KotlinType> superValueParameters = compiledValueParameters(superDescriptor);
    List<KotlinType> subValueParameters = compiledValueParameters(subDescriptor);

    List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
    List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();

    if (superTypeParameters.size() != subTypeParameters.size()) {
      for (int i = 0; i < superValueParameters.size(); ++i) {
        // TODO: compare erasure
        if (!KotlinTypeChecker.DEFAULT.equalTypes(
            superValueParameters.get(i), subValueParameters.get(i))) {
          return OverrideCompatibilityInfo.incompatible("Type parameter number mismatch");
        }
      }
      return OverrideCompatibilityInfo.conflict("Type parameter number mismatch");
    }

    KotlinTypeChecker typeChecker = createTypeChecker(superTypeParameters, subTypeParameters);

    for (int i = 0; i < superTypeParameters.size(); i++) {
      if (!areTypeParametersEquivalent(
          superTypeParameters.get(i), subTypeParameters.get(i), typeChecker)) {
        return OverrideCompatibilityInfo.incompatible("Type parameter bounds mismatch");
      }
    }

    for (int i = 0; i < superValueParameters.size(); i++) {
      if (!areTypesEquivalent(
          superValueParameters.get(i), subValueParameters.get(i), typeChecker)) {
        return OverrideCompatibilityInfo.incompatible("Value parameter type mismatch");
      }
    }

    if (checkReturnType) {
      KotlinType superReturnType = superDescriptor.getReturnType();
      KotlinType subReturnType = subDescriptor.getReturnType();

      if (superReturnType != null && subReturnType != null) {
        boolean bothErrors = subReturnType.isError() && superReturnType.isError();
        if (!bothErrors && !typeChecker.isSubtypeOf(subReturnType, superReturnType)) {
          return OverrideCompatibilityInfo.conflict("Return type mismatch");
        }
      }
    }

    return OverrideCompatibilityInfo.success();
  }
예제 #9
0
 public static boolean equalTypes(@NotNull KotlinType a, @NotNull KotlinType b) {
   return KotlinTypeChecker.DEFAULT.isSubtypeOf(a, b)
       && KotlinTypeChecker.DEFAULT.isSubtypeOf(b, a);
 }