Example #1
0
 @Nullable
 public static TypeParameterDescriptor getTypeParameterDescriptorOrNull(@NotNull KotlinType type) {
   if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
     return (TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor();
   }
   return null;
 }
Example #2
0
 private static boolean lowerThanBound(
     KotlinTypeChecker typeChecker,
     KotlinType argument,
     TypeParameterDescriptor parameterDescriptor) {
   for (KotlinType bound : parameterDescriptor.getUpperBounds()) {
     if (typeChecker.isSubtypeOf(argument, bound)) {
       if (!argument.getConstructor().equals(bound.getConstructor())) {
         return true;
       }
     }
   }
   return false;
 }
Example #3
0
  /**
   * Check if cast from supertype to subtype is erased. It is an error in "is" statement and warning
   * in "as".
   */
  public static boolean isCastErased(
      @NotNull KotlinType supertype,
      @NotNull KotlinType subtype,
      @NotNull KotlinTypeChecker typeChecker) {
    // cast between T and T? is always OK
    if (supertype.isMarkedNullable() || subtype.isMarkedNullable()) {
      return isCastErased(
          TypeUtils.makeNotNullable(supertype), TypeUtils.makeNotNullable(subtype), typeChecker);
    }

    // if it is a upcast, it's never erased
    if (typeChecker.isSubtypeOf(supertype, subtype)) return false;

    // downcasting to a non-reified type parameter is always erased
    if (TypeUtils.isNonReifiedTypeParemeter(subtype)) return true;

    // Check that we are actually casting to a generic type
    // NOTE: this does not account for 'as Array<List<T>>'
    if (allParametersReified(subtype)) return false;

    KotlinType staticallyKnownSubtype =
        findStaticallyKnownSubtype(supertype, subtype.getConstructor()).getResultingType();

    // If the substitution failed, it means that the result is an impossible type, e.g. something
    // like Out<in Foo>
    // In this case, we can't guarantee anything, so the cast is considered to be erased
    if (staticallyKnownSubtype == null) return true;

    // If the type we calculated is a subtype of the cast target, it's OK to use the cast target
    // instead.
    // If not, it's wrong to use it
    return !typeChecker.isSubtypeOf(staticallyKnownSubtype, subtype);
  }
Example #4
0
  /**
   * Remember that we are trying to cast something of type {@code supertype} to {@code subtype}.
   *
   * <p>Since at runtime we can only check the class (type constructor), the rest of the subtype
   * should be known statically, from supertype. This method reconstructs all static information
   * that can be obtained from supertype.
   *
   * <p>Example 1: supertype = Collection<String> subtype = List<...> result = List<String>, all
   * arguments are inferred
   *
   * <p>Example 2: supertype = Any subtype = List<...> result = List<*>, some arguments were not
   * inferred, replaced with '*'
   */
  public static TypeReconstructionResult findStaticallyKnownSubtype(
      @NotNull KotlinType supertype, @NotNull TypeConstructor subtypeConstructor) {
    assert !supertype.isMarkedNullable() : "This method only makes sense for non-nullable types";

    // Assume we are casting an expression of type Collection<Foo> to List<Bar>
    // First, let's make List<T>, where T is a type variable
    ClassifierDescriptor descriptor = subtypeConstructor.getDeclarationDescriptor();
    assert descriptor != null : "Can't create default type for " + subtypeConstructor;
    KotlinType subtypeWithVariables = descriptor.getDefaultType();

    // Now, let's find a supertype of List<T> that is a Collection of something,
    // in this case it will be Collection<T>
    KotlinType supertypeWithVariables =
        TypeCheckingProcedure.findCorrespondingSupertype(subtypeWithVariables, supertype);

    final List<TypeParameterDescriptor> variables =
        subtypeWithVariables.getConstructor().getParameters();

    Map<TypeConstructor, TypeProjection> substitution;
    if (supertypeWithVariables != null) {
      // Now, let's try to unify Collection<T> and Collection<Foo> solution is a map from T to Foo
      TypeUnifier.UnificationResult solution =
          TypeUnifier.unify(
              new TypeProjectionImpl(supertype),
              new TypeProjectionImpl(supertypeWithVariables),
              new Predicate<TypeConstructor>() {
                @Override
                public boolean apply(TypeConstructor typeConstructor) {
                  ClassifierDescriptor descriptor = typeConstructor.getDeclarationDescriptor();
                  return descriptor instanceof TypeParameterDescriptor
                      && variables.contains(descriptor);
                }
              });
      substitution = Maps.newHashMap(solution.getSubstitution());
    } else {
      // If there's no corresponding supertype, no variables are determined
      // This may be OK, e.g. in case 'Any as List<*>'
      substitution = Maps.newHashMapWithExpectedSize(variables.size());
    }

    // If some of the parameters are not determined by unification, it means that these parameters
    // are lost,
    // let's put stars instead, so that we can only cast to something like List<*>, e.g. (a: Any) as
    // List<*>
    boolean allArgumentsInferred = true;
    for (TypeParameterDescriptor variable : variables) {
      TypeProjection value = substitution.get(variable.getTypeConstructor());
      if (value == null) {
        substitution.put(variable.getTypeConstructor(), TypeUtils.makeStarProjection(variable));
        allArgumentsInferred = false;
      }
    }

    // At this point we have values for all type parameters of List
    // Let's make a type by substituting them: List<T> -> List<Foo>
    KotlinType substituted =
        TypeSubstitutor.create(substitution).substitute(subtypeWithVariables, Variance.INVARIANT);

    return new TypeReconstructionResult(substituted, allArgumentsInferred);
  }
Example #5
0
 @Nullable
 public static ClassDescriptor getClassDescriptor(@NotNull KotlinType type) {
   DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
   if (declarationDescriptor instanceof ClassDescriptor) {
     return (ClassDescriptor) declarationDescriptor;
   }
   return null;
 }
Example #6
0
  public static boolean isExtensionFunctionType(@NotNull KotlinType type) {
    if (isExactExtensionFunctionType(type)) return true;

    for (KotlinType superType : type.getConstructor().getSupertypes()) {
      if (isExtensionFunctionType(superType)) return true;
    }

    return false;
  }
Example #7
0
 private static boolean isConstructedFromGivenClass(
     @NotNull KotlinType type, @NotNull FqNameUnsafe fqName) {
   ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
   return descriptor != null
       &&
       /* quick check to avoid creation of full FqName instance */ descriptor
           .getName()
           .equals(fqName.shortName())
       && fqName.equals(getFqName(descriptor));
 }
Example #8
0
 public static boolean isSubtypeOfClass(
     @NotNull KotlinType type, @NotNull DeclarationDescriptor superClass) {
   if (isSameClass(type, superClass)) return true;
   for (KotlinType superType : type.getConstructor().getSupertypes()) {
     if (isSubtypeOfClass(superType, superClass)) {
       return true;
     }
   }
   return false;
 }
Example #9
0
 public static boolean dependsOnTypeConstructors(
     @NotNull KotlinType type, @NotNull Collection<TypeConstructor> typeParameterConstructors) {
   if (typeParameterConstructors.contains(type.getConstructor())) return true;
   for (TypeProjection typeProjection : type.getArguments()) {
     if (!typeProjection.isStarProjection()
         && dependsOnTypeConstructors(typeProjection.getType(), typeParameterConstructors)) {
       return true;
     }
   }
   return false;
 }
Example #10
0
 @NotNull
 public static List<KotlinType> getImmediateSupertypes(@NotNull KotlinType type) {
   TypeSubstitutor substitutor = TypeSubstitutor.create(type);
   Collection<KotlinType> originalSupertypes = type.getConstructor().getSupertypes();
   List<KotlinType> result = new ArrayList<KotlinType>(originalSupertypes.size());
   for (KotlinType supertype : originalSupertypes) {
     KotlinType substitutedType = createSubstitutedSupertype(type, supertype, substitutor);
     if (substitutedType != null) {
       result.add(substitutedType);
     }
   }
   return result;
 }
Example #11
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;
  }
Example #12
0
 private static boolean isSameClass(
     @NotNull KotlinType type, @NotNull DeclarationDescriptor other) {
   DeclarationDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
   if (descriptor != null) {
     DeclarationDescriptor originalDescriptor = descriptor.getOriginal();
     if (originalDescriptor instanceof ClassifierDescriptor
         && other instanceof ClassifierDescriptor
         && ((ClassifierDescriptor) other)
             .getTypeConstructor()
             .equals(((ClassifierDescriptor) originalDescriptor).getTypeConstructor())) {
       return true;
     }
   }
   return false;
 }
Example #13
0
  private static List<KotlinType> mapToPlatformIndependentTypes(
      @NotNull KotlinType type, @NotNull PlatformToKotlinClassMap platformToKotlinClassMap) {
    ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
    if (!(descriptor instanceof ClassDescriptor)) return Collections.singletonList(type);

    ClassDescriptor originalClass = (ClassDescriptor) descriptor;
    Collection<ClassDescriptor> kotlinClasses =
        platformToKotlinClassMap.mapPlatformClass(originalClass);
    if (kotlinClasses.isEmpty()) return Collections.singletonList(type);

    List<KotlinType> result = Lists.newArrayListWithCapacity(2);
    result.add(type);
    for (ClassDescriptor classDescriptor : kotlinClasses) {
      KotlinType kotlinType =
          TypeUtils.substituteProjectionsForParameters(classDescriptor, type.getArguments());
      result.add(kotlinType);
    }

    return result;
  }
Example #14
0
 public static boolean isDontCarePlaceholder(@Nullable KotlinType type) {
   return type != null && type.getConstructor() == DONT_CARE.getConstructor();
 }
Example #15
0
 public static boolean isExactFunctionOrExtensionFunctionType(@NotNull KotlinType type) {
   ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
   return descriptor != null && isNumberedFunctionClassFqName(getFqName(descriptor));
 }
Example #16
0
 public static boolean isPrimitiveType(@NotNull KotlinType type) {
   ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
   return !type.isMarkedNullable()
       && descriptor instanceof ClassDescriptor
       && isPrimitiveClass((ClassDescriptor) descriptor);
 }
Example #17
0
 public static boolean isPrimitiveArray(@NotNull KotlinType type) {
   ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
   return descriptor != null && getPrimitiveTypeByArrayClassFqName(getFqName(descriptor)) != null;
 }
Example #18
0
 @NotNull
 public static ClassDescriptor getClassDescriptorForType(@NotNull KotlinType type) {
   return getClassDescriptorForTypeConstructor(type.getConstructor());
 }
Example #19
0
 private static boolean allParametersReified(KotlinType subtype) {
   for (TypeParameterDescriptor parameterDescriptor : subtype.getConstructor().getParameters()) {
     if (!parameterDescriptor.isReified()) return false;
   }
   return true;
 }
Example #20
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;
  }
Example #21
0
 private static boolean isTrait(@NotNull KotlinType type) {
   ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
   return descriptor instanceof ClassDescriptor
       && ((ClassDescriptor) descriptor).getKind() == ClassKind.INTERFACE;
 }
Example #22
0
 @Override
 @NotNull
 public TypeConstructor getConstructor() {
   return delegate.getConstructor();
 }