Ejemplo n.º 1
0
 @NotNull
 public static KotlinType makeUnsubstitutedType(
     ClassDescriptor classDescriptor, MemberScope unsubstitutedMemberScope) {
   if (ErrorUtils.isError(classDescriptor)) {
     return ErrorUtils.createErrorType("Unsubstituted type for " + classDescriptor);
   }
   TypeConstructor typeConstructor = classDescriptor.getTypeConstructor();
   List<TypeProjection> arguments = getDefaultTypeProjections(typeConstructor.getParameters());
   return KotlinTypeImpl.create(
       Annotations.Companion.getEMPTY(),
       typeConstructor,
       false,
       arguments,
       unsubstitutedMemberScope);
 }
Ejemplo n.º 2
0
  @NotNull
  private JetType modifyTypeAccordingToSuperMethods(
      @NotNull JetType autoType,
      @NotNull List<TypeAndVariance> typesFromSuper,
      @NotNull TypeUsage howThisTypeIsUsed) {
    if (ErrorUtils.isErrorType(autoType)) {
      return autoType;
    }

    boolean resultNullable = typeMustBeNullable(autoType, typesFromSuper, howThisTypeIsUsed);
    ClassifierDescriptor resultClassifier = modifyTypeClassifier(autoType, typesFromSuper);
    List<TypeProjection> resultArguments =
        getTypeArgsOfType(autoType, resultClassifier, typesFromSuper);
    JetScope resultScope;
    if (resultClassifier instanceof ClassDescriptor) {
      resultScope = ((ClassDescriptor) resultClassifier).getMemberScope(resultArguments);
    } else {
      resultScope = autoType.getMemberScope();
    }

    JetTypeImpl type =
        new JetTypeImpl(
            autoType.getAnnotations(),
            resultClassifier.getTypeConstructor(),
            resultNullable,
            resultArguments,
            resultScope);

    PropagationHeuristics.checkArrayInReturnType(this, type, typesFromSuper);
    return type;
  }
Ejemplo n.º 3
0
  @NotNull
  public JetType safeSubstitute(@NotNull JetType type, @NotNull Variance howThisTypeIsUsed) {
    if (isEmpty()) {
      return type;
    }

    try {
      return unsafeSubstitute(new TypeProjectionImpl(howThisTypeIsUsed, type), 0).getType();
    } catch (SubstitutionException e) {
      return ErrorUtils.createErrorType(e.getMessage());
    }
  }
Ejemplo n.º 4
0
  @Nullable
  private static FqName getFqNameSafeIfPossible(@NotNull DeclarationDescriptor descriptor) {
    if (descriptor instanceof ModuleDescriptor || ErrorUtils.isError(descriptor)) {
      return FqName.ROOT;
    }

    if (descriptor instanceof PackageViewDescriptor) {
      return ((PackageViewDescriptor) descriptor).getFqName();
    } else if (descriptor instanceof PackageFragmentDescriptor) {
      return ((PackageFragmentDescriptor) descriptor).getFqName();
    }

    return null;
  }
Ejemplo n.º 5
0
  @NotNull
  private String renderClassName(@NotNull ClassDescriptor klass) {
    if (ErrorUtils.isError(klass)) {
      return klass.getTypeConstructor().toString();
    }
    if (shortNames) {
      List<Name> qualifiedNameElements = Lists.newArrayList();

      // for nested classes qualified name should be used
      DeclarationDescriptor current = klass;
      do {
        if (((ClassDescriptor) current).getKind() != ClassKind.CLASS_OBJECT) {
          qualifiedNameElements.add(current.getName());
        }
        current = current.getContainingDeclaration();
      } while (current instanceof ClassDescriptor);

      Collections.reverse(qualifiedNameElements);
      return renderFqName(qualifiedNameElements);
    }
    return renderFqName(DescriptorUtils.getFQName(klass));
  }
Ejemplo n.º 6
0
  private void checkSupertypeList(
      @NotNull ClassDescriptor supertypeOwner,
      @NotNull Map<JetTypeReference, JetType> supertypes,
      @NotNull JetClassOrObject jetClass) {
    Set<TypeConstructor> allowedFinalSupertypes =
        getAllowedFinalSupertypes(supertypeOwner, jetClass);
    Set<TypeConstructor> typeConstructors = Sets.newHashSet();
    boolean classAppeared = false;
    for (Map.Entry<JetTypeReference, JetType> entry : supertypes.entrySet()) {
      JetTypeReference typeReference = entry.getKey();
      JetType supertype = entry.getValue();

      boolean addSupertype = true;

      ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
      if (classDescriptor != null) {
        if (ErrorUtils.isError(classDescriptor)) continue;

        if (classDescriptor.getKind() != ClassKind.INTERFACE) {
          if (supertypeOwner.getKind() == ClassKind.ENUM_CLASS) {
            trace.report(CLASS_IN_SUPERTYPE_FOR_ENUM.on(typeReference));
            addSupertype = false;
          } else if (supertypeOwner.getKind() == ClassKind.INTERFACE
              && !classAppeared
              && !TypesPackage.isDynamic(supertype) /* avoid duplicate diagnostics */) {
            trace.report(TRAIT_WITH_SUPERCLASS.on(typeReference));
            addSupertype = false;
          }

          if (classAppeared) {
            trace.report(MANY_CLASSES_IN_SUPERTYPE_LIST.on(typeReference));
          } else {
            classAppeared = true;
          }
        }
      } else {
        trace.report(SUPERTYPE_NOT_A_CLASS_OR_TRAIT.on(typeReference));
      }

      TypeConstructor constructor = supertype.getConstructor();
      if (addSupertype && !typeConstructors.add(constructor)) {
        trace.report(SUPERTYPE_APPEARS_TWICE.on(typeReference));
      }

      if (DescriptorUtils.isSingleton(classDescriptor)) {
        trace.report(SINGLETON_IN_SUPERTYPE.on(typeReference));
      } else if (constructor.isFinal() && !allowedFinalSupertypes.contains(constructor)) {
        if (classDescriptor.getModality() == Modality.SEALED) {
          DeclarationDescriptor containingDescriptor = supertypeOwner.getContainingDeclaration();
          while (containingDescriptor != null && containingDescriptor != classDescriptor) {
            containingDescriptor = containingDescriptor.getContainingDeclaration();
          }
          if (containingDescriptor == null) {
            trace.report(SEALED_SUPERTYPE.on(typeReference));
          } else {
            trace.report(SEALED_SUPERTYPE_IN_LOCAL_CLASS.on(typeReference));
          }
        } else {
          trace.report(FINAL_SUPERTYPE.on(typeReference));
        }
      }
    }
  }
Ejemplo n.º 7
0
public class TypeUtils {
  public static final KotlinType DONT_CARE =
      ErrorUtils.createErrorTypeWithCustomDebugName("DONT_CARE");
  public static final KotlinType CANT_INFER_FUNCTION_PARAM_TYPE =
      ErrorUtils.createErrorType("Cannot be inferred");

  public static class SpecialType implements KotlinType {
    private final String name;

    public SpecialType(String name) {
      this.name = name;
    }

    @NotNull
    @Override
    public TypeConstructor getConstructor() {
      throw new IllegalStateException(name);
    }

    @NotNull
    @Override
    public List<TypeProjection> getArguments() {
      throw new IllegalStateException(name);
    }

    @Override
    public boolean isMarkedNullable() {
      throw new IllegalStateException(name);
    }

    @NotNull
    @Override
    public MemberScope getMemberScope() {
      throw new IllegalStateException(name);
    }

    @Override
    public boolean isError() {
      return false;
    }

    @NotNull
    @Override
    public Annotations getAnnotations() {
      throw new IllegalStateException(name);
    }

    @Nullable
    @Override
    public <T extends TypeCapability> T getCapability(@NotNull Class<T> capabilityClass) {
      return null;
    }

    @NotNull
    @Override
    public TypeCapabilities getCapabilities() {
      return TypeCapabilities.NONE.INSTANCE;
    }

    @Override
    public String toString() {
      return name;
    }
  }

  @NotNull public static final KotlinType NO_EXPECTED_TYPE = new SpecialType("NO_EXPECTED_TYPE");

  public static final KotlinType UNIT_EXPECTED_TYPE = new SpecialType("UNIT_EXPECTED_TYPE");

  public static boolean noExpectedType(@NotNull KotlinType type) {
    return type == NO_EXPECTED_TYPE || type == UNIT_EXPECTED_TYPE;
  }

  public static boolean isDontCarePlaceholder(@Nullable KotlinType type) {
    return type != null && type.getConstructor() == DONT_CARE.getConstructor();
  }

  @NotNull
  public static KotlinType makeNullable(@NotNull KotlinType type) {
    return makeNullableAsSpecified(type, true);
  }

  @NotNull
  public static KotlinType makeNotNullable(@NotNull KotlinType type) {
    return makeNullableAsSpecified(type, false);
  }

  @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);
  }

  @NotNull
  public static KotlinType makeNullableIfNeeded(@NotNull KotlinType type, boolean nullable) {
    if (nullable) {
      return makeNullable(type);
    }
    return type;
  }

  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;
  }

  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;
  }

  @NotNull
  public static KotlinType makeUnsubstitutedType(
      ClassDescriptor classDescriptor, MemberScope unsubstitutedMemberScope) {
    if (ErrorUtils.isError(classDescriptor)) {
      return ErrorUtils.createErrorType("Unsubstituted type for " + classDescriptor);
    }
    TypeConstructor typeConstructor = classDescriptor.getTypeConstructor();
    List<TypeProjection> arguments = getDefaultTypeProjections(typeConstructor.getParameters());
    return KotlinTypeImpl.create(
        Annotations.Companion.getEMPTY(),
        typeConstructor,
        false,
        arguments,
        unsubstitutedMemberScope);
  }

  @NotNull
  public static List<TypeProjection> getDefaultTypeProjections(
      @NotNull List<TypeParameterDescriptor> parameters) {
    List<TypeProjection> result = new ArrayList<TypeProjection>(parameters.size());
    for (TypeParameterDescriptor parameterDescriptor : parameters) {
      result.add(new TypeProjectionImpl(parameterDescriptor.getDefaultType()));
    }
    return org.jetbrains.kotlin.utils.CollectionsKt.toReadOnlyList(result);
  }

  @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;
  }

  @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;
  }

  private static void collectAllSupertypes(
      @NotNull KotlinType type, @NotNull Set<KotlinType> result) {
    List<KotlinType> immediateSupertypes = getImmediateSupertypes(type);
    result.addAll(immediateSupertypes);
    for (KotlinType supertype : immediateSupertypes) {
      collectAllSupertypes(supertype, result);
    }
  }

  @NotNull
  public static Set<KotlinType> getAllSupertypes(@NotNull KotlinType type) {
    // 15 is obtained by experimentation: JDK classes like ArrayList tend to have so many
    // supertypes,
    // the average number is lower
    Set<KotlinType> result = new LinkedHashSet<KotlinType>(15);
    collectAllSupertypes(type, result);
    return result;
  }

  /**
   * 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;
  }

  /**
   * 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;
  }

  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;
  }

  @Nullable
  public static ClassDescriptor getClassDescriptor(@NotNull KotlinType type) {
    DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
    if (declarationDescriptor instanceof ClassDescriptor) {
      return (ClassDescriptor) declarationDescriptor;
    }
    return null;
  }

  @NotNull
  public static KotlinType substituteParameters(
      @NotNull ClassDescriptor clazz, @NotNull List<KotlinType> typeArguments) {
    List<TypeProjection> projections =
        CollectionsKt.map(
            typeArguments,
            new Function1<KotlinType, TypeProjection>() {
              @Override
              public TypeProjection invoke(KotlinType type) {
                return new TypeProjectionImpl(type);
              }
            });

    return substituteProjectionsForParameters(clazz, projections);
  }

  @NotNull
  public static KotlinType substituteProjectionsForParameters(
      @NotNull ClassDescriptor clazz, @NotNull List<TypeProjection> projections) {
    List<TypeParameterDescriptor> clazzTypeParameters = clazz.getTypeConstructor().getParameters();
    if (clazzTypeParameters.size() != projections.size()) {
      throw new IllegalArgumentException(
          "type parameter counts do not match: " + clazz + ", " + projections);
    }

    Map<TypeConstructor, TypeProjection> substitutions =
        org.jetbrains.kotlin.utils.CollectionsKt.newHashMapWithExpectedSize(
            clazzTypeParameters.size());

    for (int i = 0; i < clazzTypeParameters.size(); ++i) {
      TypeConstructor typeConstructor = clazzTypeParameters.get(i).getTypeConstructor();
      substitutions.put(typeConstructor, projections.get(i));
    }

    return TypeSubstitutor.create(substitutions)
        .substitute(clazz.getDefaultType(), Variance.INVARIANT);
  }

  public static boolean equalTypes(@NotNull KotlinType a, @NotNull KotlinType b) {
    return KotlinTypeChecker.DEFAULT.isSubtypeOf(a, b)
        && KotlinTypeChecker.DEFAULT.isSubtypeOf(b, a);
  }

  public static boolean dependsOnTypeParameters(
      @NotNull KotlinType type, @NotNull Collection<TypeParameterDescriptor> typeParameters) {
    return dependsOnTypeConstructors(
        type,
        CollectionsKt.map(
            typeParameters,
            new Function1<TypeParameterDescriptor, TypeConstructor>() {
              @Override
              public TypeConstructor invoke(
                  @NotNull TypeParameterDescriptor typeParameterDescriptor) {
                return typeParameterDescriptor.getTypeConstructor();
              }
            }));
  }

  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;
  }

  public static boolean contains(@Nullable KotlinType type, @NotNull final KotlinType specialType) {
    return contains(
        type,
        new Function1<KotlinType, Boolean>() {
          @Override
          public Boolean invoke(KotlinType type) {
            return specialType.equals(type);
          }
        });
  }

  public static boolean contains(
      @Nullable KotlinType type, @NotNull Function1<KotlinType, Boolean> isSpecialType) {
    if (type == null) return false;
    if (isSpecialType.invoke(type)) return true;
    Flexibility flexibility = type.getCapability(Flexibility.class);
    if (flexibility != null
        && (contains(flexibility.getLowerBound(), isSpecialType)
            || contains(flexibility.getUpperBound(), isSpecialType))) {
      return true;
    }
    for (TypeProjection projection : type.getArguments()) {
      if (!projection.isStarProjection() && contains(projection.getType(), isSpecialType))
        return true;
    }
    return false;
  }

  @NotNull
  public static TypeProjection makeStarProjection(
      @NotNull TypeParameterDescriptor parameterDescriptor) {
    return new StarProjectionImpl(parameterDescriptor);
  }

  @NotNull
  public static KotlinType getDefaultPrimitiveNumberType(
      @NotNull IntegerValueTypeConstructor numberValueTypeConstructor) {
    KotlinType type = getDefaultPrimitiveNumberType(numberValueTypeConstructor.getSupertypes());
    assert type != null
        : "Strange number value type constructor: "
            + numberValueTypeConstructor
            + ". "
            + "Super types doesn't contain double, int or long: "
            + numberValueTypeConstructor.getSupertypes();
    return type;
  }

  @Nullable
  public static KotlinType getDefaultPrimitiveNumberType(
      @NotNull Collection<KotlinType> supertypes) {
    if (supertypes.isEmpty()) {
      return null;
    }

    KotlinBuiltIns builtIns = supertypes.iterator().next().getConstructor().getBuiltIns();
    KotlinType doubleType = builtIns.getDoubleType();
    if (supertypes.contains(doubleType)) {
      return doubleType;
    }
    KotlinType intType = builtIns.getIntType();
    if (supertypes.contains(intType)) {
      return intType;
    }
    KotlinType longType = builtIns.getLongType();
    if (supertypes.contains(longType)) {
      return longType;
    }
    return null;
  }

  @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);
  }

  public static boolean isTypeParameter(@NotNull KotlinType type) {
    return getTypeParameterDescriptorOrNull(type) != null;
  }

  public static boolean isReifiedTypeParameter(@NotNull KotlinType type) {
    TypeParameterDescriptor typeParameterDescriptor = getTypeParameterDescriptorOrNull(type);
    return typeParameterDescriptor != null && typeParameterDescriptor.isReified();
  }

  public static boolean isNonReifiedTypeParameter(@NotNull KotlinType type) {
    TypeParameterDescriptor typeParameterDescriptor = getTypeParameterDescriptorOrNull(type);
    return typeParameterDescriptor != null && !typeParameterDescriptor.isReified();
  }

  @Nullable
  public static TypeParameterDescriptor getTypeParameterDescriptorOrNull(@NotNull KotlinType type) {
    if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
      return (TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor();
    }
    return null;
  }

  private abstract static class AbstractTypeWithKnownNullability extends AbstractKotlinType {
    private final KotlinType delegate;

    private AbstractTypeWithKnownNullability(@NotNull KotlinType delegate) {
      this.delegate = delegate;
    }

    @Override
    @NotNull
    public TypeConstructor getConstructor() {
      return delegate.getConstructor();
    }

    @Override
    @NotNull
    public List<TypeProjection> getArguments() {
      return delegate.getArguments();
    }

    @Override
    public abstract boolean isMarkedNullable();

    @Override
    @NotNull
    public MemberScope getMemberScope() {
      return delegate.getMemberScope();
    }

    @Override
    public boolean isError() {
      return delegate.isError();
    }

    @Override
    @NotNull
    public Annotations getAnnotations() {
      return delegate.getAnnotations();
    }

    @Nullable
    @Override
    public <T extends TypeCapability> T getCapability(@NotNull Class<T> capabilityClass) {
      return delegate.getCapability(capabilityClass);
    }

    @NotNull
    @Override
    public TypeCapabilities getCapabilities() {
      return delegate.getCapabilities();
    }
  }

  private static class NullableType extends AbstractTypeWithKnownNullability {

    private NullableType(@NotNull KotlinType delegate) {
      super(delegate);
    }

    @Override
    public boolean isMarkedNullable() {
      return true;
    }
  }

  private static class NotNullType extends AbstractTypeWithKnownNullability {

    private NotNullType(@NotNull KotlinType delegate) {
      super(delegate);
    }

    @Override
    public boolean isMarkedNullable() {
      return false;
    }
  }
}
Ejemplo n.º 8
0
  private void addConstraint(
      @NotNull ConstraintKind constraintKind,
      @NotNull JetType subjectType,
      @Nullable JetType constrainingType,
      @NotNull ConstraintPosition constraintPosition) {

    if (constrainingType == TypeUtils.NO_EXPECTED_TYPE
        || constrainingType == DONT_CARE
        || constrainingType == CANT_INFER) {
      return;
    }

    if (constrainingType == null
        || (ErrorUtils.isErrorType(constrainingType)
            && constrainingType != PLACEHOLDER_FUNCTION_TYPE)) {
      hasErrorInConstrainingTypes = true;
      return;
    }

    assert subjectType != TypeUtils.NO_EXPECTED_TYPE
        : "Subject type shouldn't be NO_EXPECTED_TYPE (in position " + constraintPosition + " )";
    if (ErrorUtils.isErrorType(subjectType)) return;

    DeclarationDescriptor subjectTypeDescriptor =
        subjectType.getConstructor().getDeclarationDescriptor();

    KotlinBuiltIns kotlinBuiltIns = KotlinBuiltIns.getInstance();
    if (constrainingType == PLACEHOLDER_FUNCTION_TYPE) {
      if (!kotlinBuiltIns.isFunctionOrExtensionFunctionType(subjectType)) {
        if (subjectTypeDescriptor instanceof TypeParameterDescriptor
            && typeParameterConstraints.get(subjectTypeDescriptor) != null) {
          // a constraint binds type parameter and any function type, so there is no new info and no
          // error
          return;
        }
        errorConstraintPositions.add(constraintPosition);
      }
      return;
    }

    // todo temporary hack
    // function literal without declaring receiver type { x -> ... }
    // can be considered as extension function if one is expected
    // (special type constructor for function/ extension function should be introduced like
    // PLACEHOLDER_FUNCTION_TYPE)
    if (constraintKind == SUB_TYPE
        && kotlinBuiltIns.isFunctionType(constrainingType)
        && kotlinBuiltIns.isExtensionFunctionType(subjectType)) {
      constrainingType = createCorrespondingExtensionFunctionType(constrainingType, DONT_CARE);
    }

    DeclarationDescriptor constrainingTypeDescriptor =
        constrainingType.getConstructor().getDeclarationDescriptor();

    if (subjectTypeDescriptor instanceof TypeParameterDescriptor) {
      TypeParameterDescriptor typeParameter = (TypeParameterDescriptor) subjectTypeDescriptor;
      TypeConstraintsImpl typeConstraints = typeParameterConstraints.get(typeParameter);
      if (typeConstraints != null) {
        if (TypeUtils.dependsOnTypeParameterConstructors(
            constrainingType, Collections.singleton(DONT_CARE.getConstructor()))) {
          return;
        }
        if (subjectType.isNullable() && constrainingType.isNullable()) {
          constrainingType = TypeUtils.makeNotNullable(constrainingType);
        }
        typeConstraints.addBound(constraintKind, constrainingType);
        return;
      }
    }
    if (constrainingTypeDescriptor instanceof TypeParameterDescriptor) {
      assert typeParameterConstraints.get(constrainingTypeDescriptor) == null
          : "Constraining type contains type variable " + constrainingTypeDescriptor.getName();
    }
    if (constraintKind == SUB_TYPE && kotlinBuiltIns.isNothingOrNullableNothing(constrainingType)) {
      // following constraints are always true:
      // 'Nothing' is a subtype of any type
      if (!constrainingType.isNullable()) return;
      // 'Nothing?' is a subtype of nullable type
      if (subjectType.isNullable()) return;
    }
    if (!(constrainingTypeDescriptor instanceof ClassDescriptor)
        || !(subjectTypeDescriptor instanceof ClassDescriptor)) {
      errorConstraintPositions.add(constraintPosition);
      return;
    }
    switch (constraintKind) {
      case SUB_TYPE:
        {
          if (kotlinBuiltIns.isNothingOrNullableNothing(constrainingType)) break;
          JetType correspondingSupertype =
              TypeCheckingProcedure.findCorrespondingSupertype(constrainingType, subjectType);
          if (correspondingSupertype != null) {
            constrainingType = correspondingSupertype;
          }
          break;
        }
      case SUPER_TYPE:
        {
          if (kotlinBuiltIns.isNothingOrNullableNothing(subjectType)) break;
          JetType correspondingSupertype =
              TypeCheckingProcedure.findCorrespondingSupertype(subjectType, constrainingType);
          if (correspondingSupertype != null) {
            subjectType = correspondingSupertype;
          }
        }
      case EQUAL: // nothing
    }
    if (constrainingType.getConstructor() != subjectType.getConstructor()) {
      errorConstraintPositions.add(constraintPosition);
      return;
    }
    TypeConstructor typeConstructor = subjectType.getConstructor();
    List<TypeProjection> subjectArguments = subjectType.getArguments();
    List<TypeProjection> constrainingArguments = constrainingType.getArguments();
    List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
    for (int i = 0; i < subjectArguments.size(); i++) {
      Variance typeParameterVariance = parameters.get(i).getVariance();
      TypeProjection subjectArgument = subjectArguments.get(i);
      TypeProjection constrainingArgument = constrainingArguments.get(i);

      ConstraintKind typeParameterConstraintKind =
          getTypeParameterConstraintKind(
              typeParameterVariance, subjectArgument, constrainingArgument, constraintKind);

      addConstraint(
          typeParameterConstraintKind,
          subjectArgument.getType(),
          constrainingArgument.getType(),
          constraintPosition);
    }
  }