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