Пример #1
0
  // allowedFinalSupertypes typically contains a enum type of which supertypeOwner is an entry
  private void checkSupertypeList(
      @NotNull MutableClassDescriptor supertypeOwner,
      @NotNull Map<JetTypeReference, JetType> supertypes,
      Set<TypeConstructor> allowedFinalSupertypes) {
    Set<TypeConstructor> typeConstructors = Sets.newHashSet();
    boolean classAppeared = false;
    for (Map.Entry<JetTypeReference, JetType> entry : supertypes.entrySet()) {
      JetTypeReference typeReference = entry.getKey();
      JetType supertype = entry.getValue();

      ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
      if (classDescriptor != null) {
        if (classDescriptor.getKind() != ClassKind.TRAIT) {
          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 (!typeConstructors.add(constructor)) {
        trace.report(SUPERTYPE_APPEARS_TWICE.on(typeReference));
      }

      if (constructor.isSealed() && !allowedFinalSupertypes.contains(constructor)) {
        trace.report(FINAL_SUPERTYPE.on(typeReference));
      }
    }
  }
Пример #2
0
 @NotNull
 private String renderTypeName(@NotNull TypeConstructor typeConstructor) {
   ClassifierDescriptor cd = typeConstructor.getDeclarationDescriptor();
   if (cd instanceof TypeParameterDescriptor) {
     return renderName(cd.getName());
   } else if (cd instanceof ClassDescriptor) {
     return renderClassName((ClassDescriptor) cd);
   } else {
     assert cd == null : "Unexpected classifier: " + cd.getClass();
     return typeConstructor.toString();
   }
 }
Пример #3
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);
 }
Пример #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);
  }
Пример #5
0
 @NotNull
 public static ClassDescriptor getClassDescriptorForTypeConstructor(
     @NotNull TypeConstructor typeConstructor) {
   ClassifierDescriptor descriptor = typeConstructor.getDeclarationDescriptor();
   assert descriptor instanceof ClassDescriptor
       : "Classifier descriptor of a type should be of type ClassDescriptor: " + typeConstructor;
   return (ClassDescriptor) descriptor;
 }
Пример #6
0
 @Override
 public String toString() {
   return constructor.toString();
 }
Пример #7
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));
        }
      }
    }
  }
Пример #8
0
 @NotNull
 @Override
 public Annotations getAnnotations() {
   return errorTypeConstructor.getAnnotations();
 }
Пример #9
0
 @Nullable
 @Override
 public ClassifierDescriptor getDeclarationDescriptor() {
   return errorTypeConstructor.getDeclarationDescriptor();
 }
Пример #10
0
 @Override
 public boolean isDenotable() {
   return errorTypeConstructor.isDenotable();
 }
Пример #11
0
 @Override
 public boolean isFinal() {
   return errorTypeConstructor.isFinal();
 }
Пример #12
0
 @NotNull
 @Override
 public Collection<JetType> getSupertypes() {
   return errorTypeConstructor.getSupertypes();
 }
Пример #13
0
 @NotNull
 @Override
 public List<TypeParameterDescriptor> getParameters() {
   return errorTypeConstructor.getParameters();
 }
Пример #14
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);
    }
  }