예제 #1
0
 /**
  * Differs from `isNullableType` only by treating type parameters: acceptsNullable(T) <=> T has
  * nullable lower bound Semantics should be the same as `isSubtype(Nothing?, T)`
  *
  * @return true if `null` can be assigned to storage of this type
  */
 public static boolean acceptsNullable(@NotNull KotlinType type) {
   if (type.isMarkedNullable()) {
     return true;
   }
   if (FlexibleTypesKt.isFlexible(type)
       && acceptsNullable(FlexibleTypesKt.flexibility(type).getUpperBound())) {
     return true;
   }
   return false;
 }
예제 #2
0
 @Nullable
 public static KotlinType createSubstitutedSupertype(
     @NotNull KotlinType subType,
     @NotNull KotlinType superType,
     @NotNull TypeSubstitutor substitutor) {
   KotlinType substitutedType = substitutor.substitute(superType, Variance.INVARIANT);
   if (substitutedType != null) {
     return makeNullableIfNeeded(substitutedType, subType.isMarkedNullable());
   }
   return null;
 }
예제 #3
0
  public static boolean hasNullableSuperType(@NotNull KotlinType type) {
    if (type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
      // A class/trait cannot have a nullable supertype
      return false;
    }

    for (KotlinType supertype : getImmediateSupertypes(type)) {
      if (supertype.isMarkedNullable()) return true;
      if (hasNullableSuperType(supertype)) return true;
    }

    return false;
  }
예제 #4
0
 /**
  * A work-around of the generic nullability problem in the type checker Semantics should be the
  * same as `!isSubtype(T, Any)`
  *
  * @return true if a value of this type can be null
  */
 public static boolean isNullableType(@NotNull KotlinType type) {
   if (type.isMarkedNullable()) {
     return true;
   }
   if (FlexibleTypesKt.isFlexible(type)
       && isNullableType(FlexibleTypesKt.flexibility(type).getUpperBound())) {
     return true;
   }
   if (isTypeParameter(type)) {
     return hasNullableSuperType(type);
   }
   return false;
 }
예제 #5
0
  @NotNull
  public static KotlinType makeNullableAsSpecified(@NotNull KotlinType type, boolean nullable) {
    Flexibility flexibility = type.getCapability(Flexibility.class);
    if (flexibility != null) {
      return flexibility.makeNullableAsSpecified(nullable);
    }

    // Wrapping serves two purposes here
    // 1. It's requires less memory than copying with a changed nullability flag: a copy has many
    // fields, while a wrapper has only one
    // 2. It preserves laziness of types

    // Unwrap to avoid long delegation call chains
    if (type instanceof AbstractTypeWithKnownNullability) {
      return makeNullableAsSpecified(((AbstractTypeWithKnownNullability) type).delegate, nullable);
    }

    // checking to preserve laziness
    if (!(type instanceof LazyType) && type.isMarkedNullable() == nullable) {
      return type;
    }

    return nullable ? new NullableType(type) : new NotNullType(type);
  }
예제 #6
0
 private static boolean isNotNullConstructedFromGivenClass(
     @NotNull KotlinType type, @NotNull FqNameUnsafe fqName) {
   return !type.isMarkedNullable() && isConstructedFromGivenClass(type, fqName);
 }
예제 #7
0
 public static boolean isPrimitiveType(@NotNull KotlinType type) {
   ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
   return !type.isMarkedNullable()
       && descriptor instanceof ClassDescriptor
       && isPrimitiveClass((ClassDescriptor) descriptor);
 }
예제 #8
0
 public static boolean isNullableAny(@NotNull KotlinType type) {
   return isAnyOrNullableAny(type) && type.isMarkedNullable();
 }
예제 #9
0
 public static boolean isNullableNothing(@NotNull KotlinType type) {
   return isNothingOrNullableNothing(type) && type.isMarkedNullable();
 }
예제 #10
0
  public static boolean canHaveSubtypes(KotlinTypeChecker typeChecker, @NotNull KotlinType type) {
    if (type.isMarkedNullable()) {
      return true;
    }
    if (!type.getConstructor().isFinal()) {
      return true;
    }

    List<TypeParameterDescriptor> parameters = type.getConstructor().getParameters();
    List<TypeProjection> arguments = type.getArguments();
    for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
      TypeParameterDescriptor parameterDescriptor = parameters.get(i);
      TypeProjection typeProjection = arguments.get(i);
      if (typeProjection.isStarProjection()) return true;

      Variance projectionKind = typeProjection.getProjectionKind();
      KotlinType argument = typeProjection.getType();

      switch (parameterDescriptor.getVariance()) {
        case INVARIANT:
          switch (projectionKind) {
            case INVARIANT:
              if (lowerThanBound(typeChecker, argument, parameterDescriptor)
                  || canHaveSubtypes(typeChecker, argument)) {
                return true;
              }
              break;
            case IN_VARIANCE:
              if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
                return true;
              }
              break;
            case OUT_VARIANCE:
              if (canHaveSubtypes(typeChecker, argument)) {
                return true;
              }
              break;
          }
          break;
        case IN_VARIANCE:
          if (projectionKind != Variance.OUT_VARIANCE) {
            if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
              return true;
            }
          } else {
            if (canHaveSubtypes(typeChecker, argument)) {
              return true;
            }
          }
          break;
        case OUT_VARIANCE:
          if (projectionKind != Variance.IN_VARIANCE) {
            if (canHaveSubtypes(typeChecker, argument)) {
              return true;
            }
          } else {
            if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
              return true;
            }
          }
          break;
      }
    }
    return false;
  }