Converted ConstraintSystem to Kotlin
This commit is contained in:
@@ -428,8 +428,8 @@ public class Renderers {
|
||||
Function<TypeBoundsImpl.Bound, String> renderBound = new Function<TypeBoundsImpl.Bound, String>() {
|
||||
@Override
|
||||
public String fun(TypeBoundsImpl.Bound bound) {
|
||||
String arrow = bound.kind == LOWER_BOUND ? ">: " : bound.kind == UPPER_BOUND ? "<: " : ":= ";
|
||||
return arrow + RENDER_TYPE.render(bound.type) + '(' + bound.position + ')';
|
||||
String arrow = bound.getKind() == LOWER_BOUND ? ">: " : bound.getKind() == UPPER_BOUND ? "<: " : ":= ";
|
||||
return arrow + RENDER_TYPE.render(bound.getConstrainingType()) + '(' + bound.getPosition() + ')';
|
||||
}
|
||||
};
|
||||
Name typeVariableName = typeBounds.getTypeVariable().getName();
|
||||
|
||||
@@ -134,7 +134,7 @@ public class CallCompleter(
|
||||
trace: BindingTrace
|
||||
) {
|
||||
fun updateSystemIfSuccessful(update: (ConstraintSystem) -> Boolean) {
|
||||
val copy = getConstraintSystem()!!.copy()
|
||||
val copy = (getConstraintSystem() as ConstraintSystemImpl).copy()
|
||||
if (update(copy)) {
|
||||
setConstraintSystem(copy)
|
||||
}
|
||||
|
||||
+3
@@ -34,6 +34,7 @@ public class ConstraintPosition {
|
||||
private static final Map<Integer, ConstraintPosition> valueParameterPositions = new HashMap<Integer, ConstraintPosition>();
|
||||
private static final Map<Integer, ConstraintPosition> typeBoundPositions = new HashMap<Integer, ConstraintPosition>();
|
||||
|
||||
@NotNull
|
||||
public static ConstraintPosition getValueParameterPosition(int index) {
|
||||
ConstraintPosition position = valueParameterPositions.get(index);
|
||||
if (position == null) {
|
||||
@@ -43,6 +44,7 @@ public class ConstraintPosition {
|
||||
return position;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ConstraintPosition getTypeBoundPosition(int index) {
|
||||
ConstraintPosition position = typeBoundPositions.get(index);
|
||||
if (position == null) {
|
||||
@@ -74,6 +76,7 @@ public class ConstraintPosition {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ConstraintPosition getCompoundConstraintPosition(ConstraintPosition... positions) {
|
||||
return new CompoundConstraintPosition(Arrays.asList(positions));
|
||||
}
|
||||
|
||||
+16
-29
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,30 +14,24 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.calls.inference;
|
||||
package org.jetbrains.jet.lang.resolve.calls.inference
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||
import org.jetbrains.jet.lang.types.Variance;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.jet.lang.types.Variance
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface ConstraintSystem {
|
||||
public trait ConstraintSystem {
|
||||
|
||||
/**
|
||||
* Registers variables in a constraint system.
|
||||
*/
|
||||
void registerTypeVariables(@NotNull Map<TypeParameterDescriptor, Variance> typeVariables);
|
||||
public fun registerTypeVariables(typeVariables: Map<TypeParameterDescriptor, Variance>)
|
||||
|
||||
/**
|
||||
* Returns a set of all registered type variables.
|
||||
*/
|
||||
@NotNull
|
||||
Set<TypeParameterDescriptor> getTypeVariables();
|
||||
public fun getTypeVariables(): Set<TypeParameterDescriptor>
|
||||
|
||||
/**
|
||||
* Adds a constraint that the constraining type is a subtype of the subject type.<p/>
|
||||
@@ -46,7 +40,7 @@ public interface ConstraintSystem {
|
||||
* For example, for {@code "fun <T> id(t: T) {}"} to infer <tt>T</tt> in invocation <tt>"id(1)"</tt>
|
||||
* should be generated a constraint <tt>"Int is a subtype of T"</tt> where T is a subject type, and Int is a constraining type.
|
||||
*/
|
||||
void addSubtypeConstraint(@Nullable JetType constrainingType, @NotNull JetType subjectType, @NotNull ConstraintPosition constraintPosition);
|
||||
public fun addSubtypeConstraint(constrainingType: JetType?, subjectType: JetType, constraintPosition: ConstraintPosition)
|
||||
|
||||
/**
|
||||
* Adds a constraint that the constraining type is a supertype of the subject type. <p/>
|
||||
@@ -55,17 +49,15 @@ public interface ConstraintSystem {
|
||||
* For example, for {@code "fun <T> create() : T"} to infer <tt>T</tt> in invocation <tt>"val i: Int = create()"</tt>
|
||||
* should be generated a constraint <tt>"Int is a supertype of T"</tt> where T is a subject type, and Int is a constraining type.
|
||||
*/
|
||||
void addSupertypeConstraint(@Nullable JetType constrainingType, @NotNull JetType subjectType, @NotNull ConstraintPosition constraintPosition);
|
||||
public fun addSupertypeConstraint(constrainingType: JetType?, subjectType: JetType, constraintPosition: ConstraintPosition)
|
||||
|
||||
@NotNull
|
||||
ConstraintSystemStatus getStatus();
|
||||
public fun getStatus(): ConstraintSystemStatus
|
||||
|
||||
/**
|
||||
* Returns the resulting type constraints of solving the constraint system for specific type variable. <p/>
|
||||
* Returns null if the type variable was not registered.
|
||||
*/
|
||||
@NotNull
|
||||
TypeBounds getTypeBounds(@NotNull TypeParameterDescriptor typeVariable);
|
||||
public fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBounds
|
||||
|
||||
/**
|
||||
* Returns a result of solving the constraint system (mapping from the type variable to the resulting type projection). <p/>
|
||||
@@ -76,16 +68,11 @@ public interface ConstraintSystem {
|
||||
* If the addition of the 'expected type' constraint made the system fail,
|
||||
* this constraint is not included in the resulting substitution.
|
||||
*/
|
||||
@NotNull
|
||||
TypeSubstitutor getResultingSubstitutor();
|
||||
public fun getResultingSubstitutor(): TypeSubstitutor
|
||||
|
||||
/**
|
||||
* Returns a current result of solving the constraint system (mapping from the type variable to the resulting type projection).
|
||||
* If there is no information for type parameter, returns type projection for DONT_CARE type.
|
||||
*/
|
||||
@NotNull
|
||||
TypeSubstitutor getCurrentSubstitutor();
|
||||
|
||||
@NotNull
|
||||
ConstraintSystem copy();
|
||||
}
|
||||
public fun getCurrentSubstitutor(): TypeSubstitutor
|
||||
}
|
||||
+239
-383
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,464 +14,337 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.calls.inference;
|
||||
package org.jetbrains.jet.lang.resolve.calls.inference
|
||||
|
||||
import kotlin.Function1;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure;
|
||||
import org.jetbrains.jet.lang.types.checker.TypingConstraints;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.utils.UtilsPackage;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.jet.lang.types.TypeProjection
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.types.TypeUtils
|
||||
import org.jetbrains.jet.lang.types.TypeUtils.DONT_CARE
|
||||
import org.jetbrains.jet.lang.types.TypeProjectionImpl
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils
|
||||
import org.jetbrains.jet.lang.types.Variance
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind
|
||||
import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure
|
||||
import org.jetbrains.jet.lang.types.checker.TypingConstraints
|
||||
import org.jetbrains.jet.lang.types.TypeConstructor
|
||||
import java.util.LinkedHashMap
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind.*
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.*
|
||||
import java.util.HashMap
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.kotlin.util.sure
|
||||
|
||||
import java.util.*;
|
||||
public class ConstraintSystemImpl : ConstraintSystem {
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.EQUAL;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.SUB_TYPE;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.Bound;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind.*;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.DONT_CARE;
|
||||
|
||||
public class ConstraintSystemImpl implements ConstraintSystem {
|
||||
|
||||
public enum ConstraintKind {
|
||||
SUB_TYPE, EQUAL
|
||||
public enum class ConstraintKind {
|
||||
SUB_TYPE
|
||||
EQUAL
|
||||
}
|
||||
|
||||
private final Map<TypeParameterDescriptor, TypeBoundsImpl> typeParameterBounds =
|
||||
new LinkedHashMap<TypeParameterDescriptor, TypeBoundsImpl>();
|
||||
private final Set<ConstraintPosition> errorConstraintPositions = new HashSet<ConstraintPosition>();
|
||||
private boolean hasErrorInConstrainingTypes;
|
||||
private val typeParameterBounds = LinkedHashMap<TypeParameterDescriptor, TypeBoundsImpl>()
|
||||
private val errorConstraintPositions = HashSet<ConstraintPosition>()
|
||||
private var hasErrorInConstrainingTypes: Boolean = false
|
||||
|
||||
private final ConstraintSystemStatus constraintSystemStatus = new ConstraintSystemStatus() {
|
||||
private val constraintSystemStatus = object : ConstraintSystemStatus {
|
||||
// for debug ConstraintsUtil.getDebugMessageForStatus might be used
|
||||
|
||||
@Override
|
||||
public boolean isSuccessful() {
|
||||
return !hasContradiction() && !hasUnknownParameters();
|
||||
override fun isSuccessful() = !hasContradiction() && !hasUnknownParameters()
|
||||
|
||||
override fun hasContradiction() = hasTypeConstructorMismatch() || hasConflictingConstraints()
|
||||
|
||||
override fun hasViolatedUpperBound(): Boolean {
|
||||
if (isSuccessful()) return false
|
||||
return getSystemWithoutWeakConstraints().getStatus().isSuccessful()
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasContradiction() {
|
||||
return hasTypeConstructorMismatch() || hasConflictingConstraints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasViolatedUpperBound() {
|
||||
if (isSuccessful()) return false;
|
||||
return getSystemWithoutWeakConstraints().getStatus().isSuccessful();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasConflictingConstraints() {
|
||||
for (TypeBoundsImpl typeBounds : typeParameterBounds.values()) {
|
||||
if (typeBounds.getValues().size() > 1) return true;
|
||||
override fun hasConflictingConstraints(): Boolean {
|
||||
for (typeBounds in typeParameterBounds.values()) {
|
||||
if (typeBounds.getValues().size() > 1) return true
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasUnknownParameters() {
|
||||
for (TypeBoundsImpl typeBounds : typeParameterBounds.values()) {
|
||||
override fun hasUnknownParameters(): Boolean {
|
||||
for (typeBounds in typeParameterBounds.values()) {
|
||||
if (typeBounds.isEmpty()) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTypeConstructorMismatch() {
|
||||
return !errorConstraintPositions.isEmpty();
|
||||
}
|
||||
override fun hasTypeConstructorMismatch() = !errorConstraintPositions.isEmpty()
|
||||
|
||||
@Override
|
||||
public boolean hasTypeConstructorMismatchAt(@NotNull ConstraintPosition constraintPosition) {
|
||||
return errorConstraintPositions.contains(constraintPosition);
|
||||
}
|
||||
override fun hasTypeConstructorMismatchAt(constraintPosition: ConstraintPosition) =
|
||||
errorConstraintPositions.contains(constraintPosition)
|
||||
|
||||
@Override
|
||||
public boolean hasOnlyErrorsFromPosition(ConstraintPosition constraintPosition) {
|
||||
if (isSuccessful()) return false;
|
||||
ConstraintSystem systemWithoutConstraintsFromPosition = filterConstraintsOut(constraintPosition);
|
||||
override fun hasOnlyErrorsFromPosition(constraintPosition: ConstraintPosition): Boolean {
|
||||
if (isSuccessful()) return false
|
||||
val systemWithoutConstraintsFromPosition = filterConstraintsOut(constraintPosition)
|
||||
if (systemWithoutConstraintsFromPosition.getStatus().isSuccessful()) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
if (errorConstraintPositions.size() == 1 && errorConstraintPositions.contains(constraintPosition)) {
|
||||
// e.g. if systemWithoutConstraintsFromPosition has unknown type parameters, it's not successful
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasErrorInConstrainingTypes() {
|
||||
return hasErrorInConstrainingTypes;
|
||||
}
|
||||
};
|
||||
override fun hasErrorInConstrainingTypes() = hasErrorInConstrainingTypes
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Map<TypeParameterDescriptor, TypeProjection> getParameterToInferredValueMap(
|
||||
@NotNull Map<TypeParameterDescriptor, TypeBoundsImpl> typeParameterBounds,
|
||||
@NotNull Function1<TypeParameterDescriptor, TypeProjection> getDefaultTypeProjection
|
||||
) {
|
||||
Map<TypeParameterDescriptor, TypeProjection> substitutionContext =
|
||||
UtilsPackage.newHashMapWithExpectedSize(typeParameterBounds.size());
|
||||
for (Map.Entry<TypeParameterDescriptor, TypeBoundsImpl> entry : typeParameterBounds.entrySet()) {
|
||||
TypeParameterDescriptor typeParameter = entry.getKey();
|
||||
TypeBounds typeBounds = entry.getValue();
|
||||
|
||||
TypeProjection typeProjection;
|
||||
JetType value = typeBounds.getValue();
|
||||
if (value != null && !TypeUtils.containsSpecialType(value, TypeUtils.DONT_CARE)) {
|
||||
typeProjection = new TypeProjectionImpl(value);
|
||||
private fun getParameterToInferredValueMap(typeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>, getDefaultTypeProjection: Function1<TypeParameterDescriptor, TypeProjection>): Map<TypeParameterDescriptor, TypeProjection> {
|
||||
val substitutionContext = HashMap<TypeParameterDescriptor, TypeProjection>()
|
||||
for ((typeParameter, typeBounds) in typeParameterBounds) {
|
||||
val typeProjection: TypeProjection
|
||||
val value = typeBounds.getValue()
|
||||
if (value != null && !TypeUtils.containsSpecialType(value, DONT_CARE)) {
|
||||
typeProjection = TypeProjectionImpl(value)
|
||||
}
|
||||
else {
|
||||
typeProjection = getDefaultTypeProjection.invoke(typeParameter);
|
||||
typeProjection = getDefaultTypeProjection.invoke(typeParameter)
|
||||
}
|
||||
substitutionContext.put(typeParameter, typeProjection);
|
||||
substitutionContext.put(typeParameter, typeProjection)
|
||||
}
|
||||
return substitutionContext;
|
||||
return substitutionContext
|
||||
}
|
||||
|
||||
private TypeSubstitutor replaceUninferredBy(@NotNull Function1<TypeParameterDescriptor, TypeProjection> getDefaultValue) {
|
||||
return TypeUtils.makeSubstitutorForTypeParametersMap(getParameterToInferredValueMap(typeParameterBounds, getDefaultValue));
|
||||
private fun replaceUninferredBy(getDefaultValue: (TypeParameterDescriptor) -> TypeProjection): TypeSubstitutor {
|
||||
return TypeUtils.makeSubstitutorForTypeParametersMap(getParameterToInferredValueMap(typeParameterBounds, getDefaultValue))
|
||||
}
|
||||
|
||||
private TypeSubstitutor replaceUninferredBy(@NotNull final JetType defaultValue) {
|
||||
return replaceUninferredBy(
|
||||
new Function1<TypeParameterDescriptor, TypeProjection>() {
|
||||
@Override
|
||||
public TypeProjection invoke(TypeParameterDescriptor descriptor) {
|
||||
return new TypeProjectionImpl(defaultValue);
|
||||
}
|
||||
}
|
||||
);
|
||||
private fun replaceUninferredBy(defaultValue: JetType): TypeSubstitutor {
|
||||
return replaceUninferredBy { TypeProjectionImpl(defaultValue) }
|
||||
}
|
||||
|
||||
private TypeSubstitutor replaceUninferredBySpecialErrorType() {
|
||||
return replaceUninferredBy(
|
||||
new Function1<TypeParameterDescriptor, TypeProjection>() {
|
||||
@Override
|
||||
public TypeProjection invoke(TypeParameterDescriptor descriptor) {
|
||||
return new TypeProjectionImpl(ErrorUtils.createUninferredParameterType(descriptor));
|
||||
}
|
||||
}
|
||||
);
|
||||
private fun replaceUninferredBySpecialErrorType(): TypeSubstitutor {
|
||||
return replaceUninferredBy { TypeProjectionImpl(ErrorUtils.createUninferredParameterType(it)) }
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ConstraintSystemStatus getStatus() {
|
||||
return constraintSystemStatus;
|
||||
}
|
||||
override fun getStatus(): ConstraintSystemStatus = constraintSystemStatus
|
||||
|
||||
@Override
|
||||
public void registerTypeVariables(@NotNull Map<TypeParameterDescriptor, Variance> typeVariables) {
|
||||
for (Map.Entry<TypeParameterDescriptor, Variance> entry : typeVariables.entrySet()) {
|
||||
TypeParameterDescriptor typeVariable = entry.getKey();
|
||||
Variance positionVariance = entry.getValue();
|
||||
typeParameterBounds.put(typeVariable, new TypeBoundsImpl(typeVariable, positionVariance));
|
||||
override fun registerTypeVariables(typeVariables: Map<TypeParameterDescriptor, Variance>) {
|
||||
for ((typeVariable, positionVariance) in typeVariables) {
|
||||
typeParameterBounds.put(typeVariable, TypeBoundsImpl(typeVariable, positionVariance))
|
||||
}
|
||||
TypeSubstitutor constantSubstitutor = TypeUtils.makeConstantSubstitutor(typeParameterBounds.keySet(), DONT_CARE);
|
||||
for (Map.Entry<TypeParameterDescriptor, TypeBoundsImpl> entry : typeParameterBounds.entrySet()) {
|
||||
TypeParameterDescriptor typeVariable = entry.getKey();
|
||||
TypeBoundsImpl typeBounds = entry.getValue();
|
||||
|
||||
for (JetType declaredUpperBound : typeVariable.getUpperBounds()) {
|
||||
if (KotlinBuiltIns.getInstance().getNullableAnyType().equals(declaredUpperBound)) continue; //todo remove this line (?)
|
||||
JetType substitutedBound = constantSubstitutor.substitute(declaredUpperBound, Variance.INVARIANT);
|
||||
val constantSubstitutor = TypeUtils.makeConstantSubstitutor(typeParameterBounds.keySet(), DONT_CARE)
|
||||
for ((typeVariable, typeBounds) in typeParameterBounds) {
|
||||
for (declaredUpperBound in typeVariable.getUpperBounds()) {
|
||||
if (KotlinBuiltIns.getInstance().getNullableAnyType() == declaredUpperBound) continue //todo remove this line (?)
|
||||
val substitutedBound = constantSubstitutor?.substitute(declaredUpperBound, Variance.INVARIANT)
|
||||
if (substitutedBound != null) {
|
||||
typeBounds.addBound(UPPER_BOUND, substitutedBound, ConstraintPosition.getTypeBoundPosition(typeVariable.getIndex()));
|
||||
typeBounds.addBound(UPPER_BOUND, substitutedBound, ConstraintPosition.getTypeBoundPosition(typeVariable.getIndex()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ConstraintSystem copy() {
|
||||
return createNewConstraintSystemFromThis(
|
||||
UtilsPackage.<TypeParameterDescriptor>identity(),
|
||||
new Function1<TypeBoundsImpl, TypeBoundsImpl>() {
|
||||
@Override
|
||||
public TypeBoundsImpl invoke(TypeBoundsImpl typeBounds) {
|
||||
return typeBounds.copy();
|
||||
}
|
||||
},
|
||||
UtilsPackage.<ConstraintPosition>alwaysTrue()
|
||||
);
|
||||
public fun copy(): ConstraintSystem = createNewConstraintSystemFromThis({ it }, { it.copy() }, { true })
|
||||
|
||||
public fun substituteTypeVariables(typeVariablesMap: (TypeParameterDescriptor) -> TypeParameterDescriptor?): ConstraintSystem {
|
||||
// type bounds are proper types and don't contain other variables
|
||||
return createNewConstraintSystemFromThis(typeVariablesMap, { it }, { true })
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ConstraintSystem substituteTypeVariables(@NotNull Function1<TypeParameterDescriptor, TypeParameterDescriptor> typeVariablesMap) {
|
||||
return createNewConstraintSystemFromThis(
|
||||
typeVariablesMap,
|
||||
// type bounds are proper types and don't contain other variables
|
||||
UtilsPackage.<TypeBoundsImpl>identity(),
|
||||
UtilsPackage.<ConstraintPosition>alwaysTrue()
|
||||
);
|
||||
public fun filterConstraintsOut(vararg excludePositions: ConstraintPosition): ConstraintSystem {
|
||||
val positions = excludePositions.toSet()
|
||||
return filterConstraints { !positions.contains(it) }
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ConstraintSystem filterConstraintsOut(@NotNull final ConstraintPosition excludePosition) {
|
||||
return filterConstraints(new Function1<ConstraintPosition, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(ConstraintPosition constraintPosition) {
|
||||
return !excludePosition.equals(constraintPosition);
|
||||
public fun filterConstraints(condition: (ConstraintPosition) -> Boolean): ConstraintSystem {
|
||||
return createNewConstraintSystemFromThis({ it }, { it.filter(condition) }, condition)
|
||||
}
|
||||
|
||||
public fun getSystemWithoutWeakConstraints(): ConstraintSystem {
|
||||
return filterConstraints {
|
||||
constraintPosition ->
|
||||
// 'isStrong' for compound means 'has some strong constraints'
|
||||
// but for testing absence of weak constraints we need 'has only strong constraints' here
|
||||
if (constraintPosition is ConstraintPosition.CompoundConstraintPosition) {
|
||||
val position = constraintPosition as ConstraintPosition.CompoundConstraintPosition
|
||||
position.consistsOfOnlyStrongConstraints()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ConstraintSystem filterConstraints(@NotNull final Function1<ConstraintPosition, Boolean> condition) {
|
||||
return createNewConstraintSystemFromThis(
|
||||
UtilsPackage.<TypeParameterDescriptor>identity(),
|
||||
new Function1<TypeBoundsImpl, TypeBoundsImpl>() {
|
||||
@Override
|
||||
public TypeBoundsImpl invoke(TypeBoundsImpl typeBounds) {
|
||||
return typeBounds.filter(condition);
|
||||
}
|
||||
},
|
||||
condition
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ConstraintSystem getSystemWithoutWeakConstraints() {
|
||||
return filterConstraints(new Function1<ConstraintPosition, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(ConstraintPosition constraintPosition) {
|
||||
// 'isStrong' for compound means 'has some strong constraints'
|
||||
// but for testing absence of weak constraints we need 'has only strong constraints' here
|
||||
if (constraintPosition instanceof ConstraintPosition.CompoundConstraintPosition) {
|
||||
ConstraintPosition.CompoundConstraintPosition position =
|
||||
(ConstraintPosition.CompoundConstraintPosition) constraintPosition;
|
||||
return position.consistsOfOnlyStrongConstraints();
|
||||
}
|
||||
return constraintPosition.isStrong();
|
||||
else {
|
||||
constraintPosition.isStrong()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ConstraintSystem createNewConstraintSystemFromThis(
|
||||
@NotNull Function1<TypeParameterDescriptor, TypeParameterDescriptor> substituteTypeVariable,
|
||||
@NotNull Function1<TypeBoundsImpl, TypeBoundsImpl> replaceTypeBounds,
|
||||
@NotNull Function1<ConstraintPosition, Boolean> filterConstraintPosition
|
||||
) {
|
||||
ConstraintSystemImpl newSystem = new ConstraintSystemImpl();
|
||||
for (Map.Entry<TypeParameterDescriptor, TypeBoundsImpl> entry : typeParameterBounds.entrySet()) {
|
||||
TypeParameterDescriptor typeParameter = entry.getKey();
|
||||
TypeBoundsImpl typeBounds = entry.getValue();
|
||||
|
||||
TypeParameterDescriptor newTypeParameter = substituteTypeVariable.invoke(typeParameter);
|
||||
assert newTypeParameter != null;
|
||||
newSystem.typeParameterBounds.put(newTypeParameter, replaceTypeBounds.invoke(typeBounds));
|
||||
}
|
||||
newSystem.errorConstraintPositions.addAll(KotlinPackage.filter(errorConstraintPositions, filterConstraintPosition));
|
||||
}
|
||||
|
||||
private fun createNewConstraintSystemFromThis(
|
||||
substituteTypeVariable: (TypeParameterDescriptor) -> TypeParameterDescriptor?,
|
||||
replaceTypeBounds: (TypeBoundsImpl) -> TypeBoundsImpl,
|
||||
filterConstraintPosition: (ConstraintPosition) -> Boolean
|
||||
): ConstraintSystem {
|
||||
val newSystem = ConstraintSystemImpl()
|
||||
for ((typeParameter, typeBounds) in typeParameterBounds) {
|
||||
val newTypeParameter = substituteTypeVariable(typeParameter)
|
||||
newSystem.typeParameterBounds.put(newTypeParameter!!, replaceTypeBounds(typeBounds))
|
||||
}
|
||||
newSystem.errorConstraintPositions.addAll(errorConstraintPositions.filter(filterConstraintPosition))
|
||||
//todo if 'filterConstraintPosition' is not trivial, it's incorrect to just copy 'hasErrorInConstrainingTypes'
|
||||
newSystem.hasErrorInConstrainingTypes = hasErrorInConstrainingTypes;
|
||||
return newSystem;
|
||||
newSystem.hasErrorInConstrainingTypes = hasErrorInConstrainingTypes
|
||||
return newSystem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSupertypeConstraint(
|
||||
@Nullable JetType constrainingType,
|
||||
@NotNull JetType subjectType,
|
||||
@NotNull ConstraintPosition constraintPosition
|
||||
) {
|
||||
if (constrainingType != null && TypeUtils.noExpectedType(constrainingType)) return;
|
||||
override fun addSupertypeConstraint(constrainingType: JetType?, subjectType: JetType, constraintPosition: ConstraintPosition) {
|
||||
if (constrainingType != null && TypeUtils.noExpectedType(constrainingType)) return
|
||||
|
||||
addConstraint(SUB_TYPE, subjectType, constrainingType, constraintPosition);
|
||||
addConstraint(SUB_TYPE, subjectType, constrainingType, constraintPosition)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSubtypeConstraint(
|
||||
@Nullable JetType constrainingType,
|
||||
@NotNull JetType subjectType,
|
||||
@NotNull ConstraintPosition constraintPosition
|
||||
) {
|
||||
addConstraint(SUB_TYPE, constrainingType, subjectType, constraintPosition);
|
||||
override fun addSubtypeConstraint(constrainingType: JetType?, subjectType: JetType, constraintPosition: ConstraintPosition) {
|
||||
addConstraint(SUB_TYPE, constrainingType, subjectType, constraintPosition)
|
||||
}
|
||||
|
||||
private void addConstraint(
|
||||
@NotNull ConstraintKind constraintKind,
|
||||
@Nullable JetType subType,
|
||||
@Nullable JetType superType,
|
||||
@NotNull final ConstraintPosition constraintPosition
|
||||
) {
|
||||
TypeCheckingProcedure typeCheckingProcedure = new TypeCheckingProcedure(new TypingConstraints() {
|
||||
@Override
|
||||
public boolean assertEqualTypes(
|
||||
@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure
|
||||
) {
|
||||
doAddConstraint(EQUAL, a, b, constraintPosition, typeCheckingProcedure);
|
||||
return true;
|
||||
private fun addConstraint(constraintKind: ConstraintKind, subType: JetType?, superType: JetType?, constraintPosition: ConstraintPosition) {
|
||||
val typeCheckingProcedure = TypeCheckingProcedure(object : TypingConstraints {
|
||||
override fun assertEqualTypes(a: JetType, b: JetType, typeCheckingProcedure: TypeCheckingProcedure): Boolean {
|
||||
doAddConstraint(EQUAL, a, b, constraintPosition, typeCheckingProcedure)
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assertEqualTypeConstructors(
|
||||
@NotNull TypeConstructor a, @NotNull TypeConstructor b
|
||||
) {
|
||||
return a.equals(b);
|
||||
override fun assertEqualTypeConstructors(a: TypeConstructor, b: TypeConstructor): Boolean {
|
||||
return a == b
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assertSubtype(
|
||||
@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure
|
||||
) {
|
||||
doAddConstraint(SUB_TYPE, subtype, supertype, constraintPosition, typeCheckingProcedure);
|
||||
return true;
|
||||
override fun assertSubtype(subtype: JetType, supertype: JetType, typeCheckingProcedure: TypeCheckingProcedure): Boolean {
|
||||
doAddConstraint(SUB_TYPE, subtype, supertype, constraintPosition, typeCheckingProcedure)
|
||||
return true
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean noCorrespondingSupertype(
|
||||
@NotNull JetType subtype, @NotNull JetType supertype
|
||||
) {
|
||||
errorConstraintPositions.add(constraintPosition);
|
||||
return true;
|
||||
override fun noCorrespondingSupertype(subtype: JetType, supertype: JetType): Boolean {
|
||||
errorConstraintPositions.add(constraintPosition)
|
||||
return true
|
||||
}
|
||||
});
|
||||
doAddConstraint(constraintKind, subType, superType, constraintPosition, typeCheckingProcedure);
|
||||
})
|
||||
doAddConstraint(constraintKind, subType, superType, constraintPosition, typeCheckingProcedure)
|
||||
}
|
||||
|
||||
private boolean isErrorOrSpecialType(@Nullable JetType type) {
|
||||
private fun isErrorOrSpecialType(type: JetType?): Boolean {
|
||||
if (TypeUtils.isDontCarePlaceholder(type) || ErrorUtils.isUninferredParameter(type)) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
if (type == null || (type.isError() && type != TypeUtils.PLACEHOLDER_FUNCTION_TYPE)) {
|
||||
hasErrorInConstrainingTypes = true;
|
||||
return true;
|
||||
hasErrorInConstrainingTypes = true
|
||||
return true
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
private void doAddConstraint(
|
||||
@NotNull ConstraintKind constraintKind,
|
||||
@Nullable JetType subType,
|
||||
@Nullable JetType superType,
|
||||
@NotNull ConstraintPosition constraintPosition,
|
||||
@NotNull TypeCheckingProcedure typeCheckingProcedure
|
||||
private fun doAddConstraint(
|
||||
constraintKind: ConstraintKind,
|
||||
subType: JetType?,
|
||||
superType: JetType?,
|
||||
constraintPosition: ConstraintPosition,
|
||||
typeCheckingProcedure: TypeCheckingProcedure
|
||||
) {
|
||||
if (isErrorOrSpecialType(subType) || isErrorOrSpecialType(superType)) return
|
||||
if (subType == null || superType == null) return
|
||||
|
||||
if (isErrorOrSpecialType(subType) || isErrorOrSpecialType(superType)) return;
|
||||
assert subType != null && superType != null;
|
||||
|
||||
assert superType != TypeUtils.PLACEHOLDER_FUNCTION_TYPE : "The type for " + constraintPosition + " shouldn't be a placeholder for function type";
|
||||
assert(superType != TypeUtils.PLACEHOLDER_FUNCTION_TYPE) {
|
||||
"The type for " + constraintPosition + " shouldn't be a placeholder for function type"
|
||||
}
|
||||
|
||||
if (subType == TypeUtils.PLACEHOLDER_FUNCTION_TYPE) {
|
||||
if (!KotlinBuiltIns.isFunctionOrExtensionFunctionType(superType)) {
|
||||
if (isMyTypeVariable(superType)) {
|
||||
// a constraint binds type parameter and any function type, so there is no new info and no error
|
||||
return;
|
||||
return
|
||||
}
|
||||
errorConstraintPositions.add(constraintPosition);
|
||||
errorConstraintPositions.add(constraintPosition)
|
||||
}
|
||||
return;
|
||||
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(subType) && KotlinBuiltIns.isExtensionFunctionType(superType)) {
|
||||
subType = createCorrespondingExtensionFunctionType(subType, DONT_CARE);
|
||||
val newSubType = if (constraintKind == SUB_TYPE
|
||||
&& KotlinBuiltIns.isFunctionType(subType)
|
||||
&& KotlinBuiltIns.isExtensionFunctionType(superType)) {
|
||||
createCorrespondingExtensionFunctionType(subType, DONT_CARE)
|
||||
}
|
||||
else {
|
||||
subType : JetType
|
||||
}
|
||||
|
||||
// can be equal for the recursive invocations:
|
||||
// fun <T> foo(i: Int) : T { ... return foo(i); } => T <: T
|
||||
if (isMyTypeVariable(subType) && isMyTypeVariable(superType) && JetTypeChecker.DEFAULT.equalTypes(subType, superType)) return;
|
||||
fun simplifyConstraint(subType: JetType, superType: JetType) {
|
||||
// can be equal for the recursive invocations:
|
||||
// fun <T> foo(i: Int) : T { ... return foo(i); } => T <: T
|
||||
if (subType == superType) return
|
||||
|
||||
//todo temporary hack KT-6320
|
||||
if (isMyTypeVariable(subType) && isMyTypeVariable(superType)) return;
|
||||
assert !isMyTypeVariable(subType) || !isMyTypeVariable(superType) :
|
||||
"The constraint shouldn't contain different type variables on both sides: " + subType + " <: " + superType;
|
||||
assert(!isMyTypeVariable(subType) || !isMyTypeVariable(superType)) {
|
||||
"The constraint shouldn't contain different type variables on both sides: " + subType + " <: " + superType
|
||||
}
|
||||
|
||||
|
||||
if (isMyTypeVariable(subType)) {
|
||||
generateTypeParameterConstraint(subType, superType, constraintKind == SUB_TYPE ? UPPER_BOUND : EXACT_BOUND, constraintPosition);
|
||||
return;
|
||||
if (isMyTypeVariable(subType)) {
|
||||
val boundKind = if (constraintKind == SUB_TYPE) UPPER_BOUND else EXACT_BOUND
|
||||
generateTypeParameterConstraint(subType, superType, boundKind, constraintPosition)
|
||||
return
|
||||
}
|
||||
if (isMyTypeVariable(superType)) {
|
||||
val boundKind = if (constraintKind == SUB_TYPE) LOWER_BOUND else EXACT_BOUND
|
||||
generateTypeParameterConstraint(superType, subType, boundKind, constraintPosition)
|
||||
return
|
||||
}
|
||||
// if superType is nullable and subType is not nullable, unsafe call error will be generated later,
|
||||
// but constraint system should be solved anyway
|
||||
typeCheckingProcedure.isSubtypeOf(TypeUtils.makeNotNullable(subType), TypeUtils.makeNotNullable(superType))
|
||||
}
|
||||
if (isMyTypeVariable(superType)) {
|
||||
generateTypeParameterConstraint(superType, subType, constraintKind == SUB_TYPE ? LOWER_BOUND : EXACT_BOUND, constraintPosition);
|
||||
return;
|
||||
}
|
||||
// if superType is nullable and subType is not nullable, unsafe call error will be generated later,
|
||||
// but constraint system should be solved anyway
|
||||
typeCheckingProcedure.isSubtypeOf(TypeUtils.makeNotNullable(subType), TypeUtils.makeNotNullable(superType));
|
||||
simplifyConstraint(newSubType, superType)
|
||||
}
|
||||
|
||||
private void generateTypeParameterConstraint(
|
||||
@NotNull JetType parameterType,
|
||||
@NotNull JetType constrainingType,
|
||||
@NotNull TypeBoundsImpl.BoundKind boundKind,
|
||||
@NotNull ConstraintPosition constraintPosition
|
||||
private fun generateTypeParameterConstraint(
|
||||
parameterType: JetType,
|
||||
constrainingType: JetType,
|
||||
boundKind: TypeBounds.BoundKind,
|
||||
constraintPosition: ConstraintPosition
|
||||
) {
|
||||
// Here we are handling the case when T! gets a bound Foo (or Foo?)
|
||||
// In this case, type parameter T is supposed to get the bound Foo!
|
||||
// Example:
|
||||
// val c: Collection<Foo> = Collections.singleton(null : Foo?)
|
||||
// Constraints for T are:
|
||||
// Foo? <: T!
|
||||
// Foo >: T!
|
||||
// both Foo and Foo? transform to Foo! here
|
||||
if (TypesPackage.isFlexible(parameterType)) {
|
||||
CustomTypeVariable typeVariable = TypesPackage.getCustomTypeVariable(parameterType);
|
||||
if (typeVariable != null) {
|
||||
constrainingType = typeVariable.substitutionResult(constrainingType);
|
||||
}
|
||||
}
|
||||
|
||||
TypeBoundsImpl typeBounds = getTypeBounds(parameterType);
|
||||
assert typeBounds != null : "constraint should be generated only for type variables";
|
||||
val typeBounds = getTypeBounds(parameterType).sure("constraint should be generated only for type variables")
|
||||
|
||||
if (!parameterType.isMarkedNullable() || !constrainingType.isMarkedNullable()) {
|
||||
typeBounds.addBound(boundKind, constrainingType, constraintPosition);
|
||||
return;
|
||||
typeBounds.addBound(boundKind, constrainingType, constraintPosition)
|
||||
return
|
||||
}
|
||||
// For parameter type T:
|
||||
// constraint T? = Int? should transform to T >: Int and T <: Int?
|
||||
// constraint T? >: Int? should transform to T >: Int
|
||||
JetType notNullConstrainingType = TypeUtils.makeNotNullable(constrainingType);
|
||||
val notNullConstrainingType = TypeUtils.makeNotNullable(constrainingType)
|
||||
if (boundKind == EXACT_BOUND || boundKind == LOWER_BOUND) {
|
||||
typeBounds.addBound(LOWER_BOUND, notNullConstrainingType, constraintPosition);
|
||||
typeBounds.addBound(LOWER_BOUND, notNullConstrainingType, constraintPosition)
|
||||
}
|
||||
// constraint T? <: Int? should transform to T <: Int?
|
||||
if (boundKind == EXACT_BOUND || boundKind == UPPER_BOUND) {
|
||||
typeBounds.addBound(UPPER_BOUND, constrainingType, constraintPosition);
|
||||
typeBounds.addBound(UPPER_BOUND, constrainingType, constraintPosition)
|
||||
}
|
||||
}
|
||||
|
||||
public void processDeclaredBoundConstraints() {
|
||||
for (Map.Entry<TypeParameterDescriptor, TypeBoundsImpl> entry : typeParameterBounds.entrySet()) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = entry.getKey();
|
||||
TypeBoundsImpl typeBounds = entry.getValue();
|
||||
for (JetType declaredUpperBound : typeParameterDescriptor.getUpperBounds()) {
|
||||
public fun processDeclaredBoundConstraints() {
|
||||
for ((typeParameterDescriptor, typeBounds) in typeParameterBounds) {
|
||||
for (declaredUpperBound in typeParameterDescriptor.getUpperBounds()) {
|
||||
//todo order matters here
|
||||
Collection<Bound> bounds = new ArrayList<Bound>(typeBounds.getBounds());
|
||||
for (Bound bound : bounds) {
|
||||
val bounds = ArrayList(typeBounds.bounds)
|
||||
for (bound in bounds) {
|
||||
if (bound.kind == LOWER_BOUND || bound.kind == EXACT_BOUND) {
|
||||
ConstraintPosition position = ConstraintPosition.getCompoundConstraintPosition(
|
||||
ConstraintPosition.getTypeBoundPosition(typeParameterDescriptor.getIndex()), bound.position);
|
||||
addSubtypeConstraint(bound.type, declaredUpperBound, position);
|
||||
val position = ConstraintPosition.getCompoundConstraintPosition(ConstraintPosition.getTypeBoundPosition(typeParameterDescriptor.getIndex()), bound.position)
|
||||
addSubtypeConstraint(bound.constrainingType, declaredUpperBound, position)
|
||||
}
|
||||
}
|
||||
ClassifierDescriptor declarationDescriptor = declaredUpperBound.getConstructor().getDeclarationDescriptor();
|
||||
if (declarationDescriptor instanceof TypeParameterDescriptor && typeParameterBounds.containsKey(declarationDescriptor)) {
|
||||
TypeBoundsImpl typeBoundsForUpperBound = typeParameterBounds.get(declarationDescriptor);
|
||||
for (Bound bound : typeBoundsForUpperBound.getBounds()) {
|
||||
val declarationDescriptor = declaredUpperBound.getConstructor().getDeclarationDescriptor()
|
||||
if (declarationDescriptor is TypeParameterDescriptor && typeParameterBounds.containsKey(declarationDescriptor)) {
|
||||
val typeBoundsForUpperBound = typeParameterBounds.get(declarationDescriptor)
|
||||
for (bound in typeBoundsForUpperBound!!.bounds) {
|
||||
if (bound.kind == UPPER_BOUND || bound.kind == EXACT_BOUND) {
|
||||
ConstraintPosition position = ConstraintPosition.getCompoundConstraintPosition(
|
||||
ConstraintPosition.getTypeBoundPosition(typeParameterDescriptor.getIndex()), bound.position);
|
||||
typeBounds.addBound(UPPER_BOUND, bound.type, position);
|
||||
val position = ConstraintPosition.getCompoundConstraintPosition(ConstraintPosition.getTypeBoundPosition(typeParameterDescriptor.getIndex()), bound.position)
|
||||
typeBounds.addBound(UPPER_BOUND, bound.constrainingType, position)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -479,64 +352,47 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<TypeParameterDescriptor> getTypeVariables() {
|
||||
return typeParameterBounds.keySet();
|
||||
override fun getTypeVariables() = typeParameterBounds.keySet()
|
||||
|
||||
override fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBounds {
|
||||
return typeParameterBounds.get(typeVariable).sure(
|
||||
"TypeParameterDescriptor is not a type variable for constraint system: $typeVariable")
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TypeBounds getTypeBounds(@NotNull TypeParameterDescriptor typeVariable) {
|
||||
TypeBoundsImpl typeBounds = typeParameterBounds.get(typeVariable);
|
||||
assert typeBounds != null : "TypeParameterDescriptor is not a type variable for constraint system: " + typeVariable;
|
||||
return typeBounds;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private TypeBoundsImpl getTypeBounds(@NotNull JetType type) {
|
||||
ClassifierDescriptor parameterDescriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
if (parameterDescriptor instanceof TypeParameterDescriptor) {
|
||||
return typeParameterBounds.get(parameterDescriptor);
|
||||
private fun getTypeBounds(type: JetType): TypeBoundsImpl? {
|
||||
val parameterDescriptor = type.getConstructor().getDeclarationDescriptor()
|
||||
if (parameterDescriptor is TypeParameterDescriptor) {
|
||||
return typeParameterBounds.get(parameterDescriptor)
|
||||
}
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
private boolean isMyTypeVariable(@NotNull JetType type) {
|
||||
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
return descriptor instanceof TypeParameterDescriptor && typeParameterBounds.get(descriptor) != null;
|
||||
private fun isMyTypeVariable(type: JetType): Boolean {
|
||||
val descriptor = type.getConstructor().getDeclarationDescriptor()
|
||||
return descriptor is TypeParameterDescriptor && typeParameterBounds.get(descriptor) != null
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TypeSubstitutor getResultingSubstitutor() {
|
||||
return replaceUninferredBySpecialErrorType();
|
||||
}
|
||||
override fun getResultingSubstitutor() = replaceUninferredBySpecialErrorType()
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TypeSubstitutor getCurrentSubstitutor() {
|
||||
return replaceUninferredBy(TypeUtils.DONT_CARE);
|
||||
}
|
||||
override fun getCurrentSubstitutor() = replaceUninferredBy(TypeUtils.DONT_CARE)
|
||||
|
||||
@NotNull
|
||||
public static JetType createCorrespondingExtensionFunctionType(@NotNull JetType functionType, @NotNull JetType receiverType) {
|
||||
assert KotlinBuiltIns.isFunctionType(functionType);
|
||||
private fun createCorrespondingExtensionFunctionType(functionType: JetType, receiverType: JetType): JetType {
|
||||
assert(KotlinBuiltIns.isFunctionType(functionType))
|
||||
|
||||
List<TypeProjection> typeArguments = functionType.getArguments();
|
||||
assert !typeArguments.isEmpty();
|
||||
val typeArguments = functionType.getArguments()
|
||||
assert(!typeArguments.isEmpty())
|
||||
|
||||
val arguments = ArrayList<JetType>()
|
||||
// excluding the last type argument of the function type, which is the return type
|
||||
int index = 0;
|
||||
int lastIndex = typeArguments.size() - 1;
|
||||
List<JetType> arguments = new ArrayList<JetType>(lastIndex);
|
||||
for (TypeProjection typeArgument : typeArguments) {
|
||||
var index = 0
|
||||
val lastIndex = typeArguments.size() - 1
|
||||
for (typeArgument in typeArguments) {
|
||||
if (index < lastIndex) {
|
||||
arguments.add(typeArgument.getType());
|
||||
arguments.add(typeArgument.getType())
|
||||
}
|
||||
index++;
|
||||
index++
|
||||
}
|
||||
JetType returnType = typeArguments.get(lastIndex).getType();
|
||||
return KotlinBuiltIns.getInstance().getFunctionType(functionType.getAnnotations(), receiverType, arguments, returnType);
|
||||
val returnType = typeArguments.get(lastIndex).getType()
|
||||
return KotlinBuiltIns.getInstance().getFunctionType(functionType.getAnnotations(), receiverType, arguments, returnType)
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-19
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,24 +14,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.calls.inference;
|
||||
package org.jetbrains.jet.lang.resolve.calls.inference
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||
|
||||
public interface ConstraintSystemStatus {
|
||||
public trait ConstraintSystemStatus {
|
||||
/**
|
||||
* Returns <tt>true</tt> if constraint system has a solution (has no contradiction and has enough information to infer each registered type variable).
|
||||
*/
|
||||
boolean isSuccessful();
|
||||
public fun isSuccessful(): Boolean
|
||||
|
||||
/**
|
||||
* Return <tt>true</tt> if constraint system has no contradiction (it can be not successful because of the lack of information for a type variable).
|
||||
*/
|
||||
boolean hasContradiction();
|
||||
public fun hasContradiction(): Boolean
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if type constraints for some type variable are contradicting. <p/>
|
||||
@@ -41,7 +35,7 @@ public interface ConstraintSystemStatus {
|
||||
* - <tt>"R is a supertype of Int"</tt> <p/>
|
||||
* - <tt>"List<R> is a supertype of List<String>"</tt> which leads to <tt>"R is equal to String"</tt>
|
||||
*/
|
||||
boolean hasConflictingConstraints();
|
||||
public fun hasConflictingConstraints(): Boolean
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if contradiction of type constraints comes from declared bounds for type parameters.
|
||||
@@ -51,7 +45,7 @@ public interface ConstraintSystemStatus {
|
||||
*
|
||||
* It's the special case of 'hasConflictingConstraints' case.
|
||||
*/
|
||||
boolean hasViolatedUpperBound();
|
||||
public fun hasViolatedUpperBound(): Boolean
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if there is no information for some registered type variable.
|
||||
@@ -59,7 +53,7 @@ public interface ConstraintSystemStatus {
|
||||
* For example, for <pre>fun <E> newList()</pre> in invocation <tt>"val nl = newList()"</tt>
|
||||
* there is no information to infer type variable <tt>E</tt>.
|
||||
*/
|
||||
boolean hasUnknownParameters();
|
||||
public fun hasUnknownParameters(): Boolean
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if some constraint cannot be processed because of type constructor mismatch.
|
||||
@@ -67,7 +61,7 @@ public interface ConstraintSystemStatus {
|
||||
* For example, for <pre>fun <R> foo(t: List<R>) {}</pre> in invocation <tt>foo(hashSet("s"))</tt>
|
||||
* there is type constructor mismatch: <tt>"HashSet<String> cannot be a subtype of List<R>"</tt>.
|
||||
*/
|
||||
boolean hasTypeConstructorMismatch();
|
||||
public fun hasTypeConstructorMismatch(): Boolean
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if there is type constructor mismatch error at a specific {@code constraintPosition}.
|
||||
@@ -76,17 +70,17 @@ public interface ConstraintSystemStatus {
|
||||
* there is type constructor mismatch: <tt>"HashSet<String> cannot be a subtype of List<R>"</tt>
|
||||
* at a constraint position {@code ConstraintPosition.getValueParameterPosition(0)}.
|
||||
*/
|
||||
boolean hasTypeConstructorMismatchAt(@NotNull ConstraintPosition constraintPosition);
|
||||
public fun hasTypeConstructorMismatchAt(constraintPosition: ConstraintPosition): Boolean
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if there is type constructor mismatch only in constraintPosition or
|
||||
* constraint system is successful without constraints from this position.
|
||||
*/
|
||||
boolean hasOnlyErrorsFromPosition(ConstraintPosition constraintPosition);
|
||||
public fun hasOnlyErrorsFromPosition(constraintPosition: ConstraintPosition): Boolean
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if there is an error in constraining types. <p/>
|
||||
* Is used not to generate type inference error if there was one in argument types.
|
||||
*/
|
||||
boolean hasErrorInConstrainingTypes();
|
||||
}
|
||||
public fun hasErrorInConstrainingTypes(): Boolean
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,47 +14,30 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.calls.inference;
|
||||
package org.jetbrains.jet.lang.resolve.calls.inference
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.Variance;
|
||||
import org.jetbrains.jet.lang.types.Variance
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
|
||||
import java.util.Collection;
|
||||
public trait TypeBounds {
|
||||
public val varianceOfPosition: Variance
|
||||
|
||||
public interface TypeBounds {
|
||||
@NotNull
|
||||
Variance getVarianceOfPosition();
|
||||
public val typeVariable: TypeParameterDescriptor
|
||||
|
||||
@NotNull
|
||||
TypeParameterDescriptor getTypeVariable();
|
||||
public val bounds: Collection<Bound>
|
||||
|
||||
@NotNull
|
||||
Collection<Bound> getBounds();
|
||||
public fun isEmpty(): Boolean
|
||||
|
||||
boolean isEmpty();
|
||||
public fun getValue(): JetType?
|
||||
|
||||
@Nullable
|
||||
JetType getValue();
|
||||
public fun getValues(): Collection<JetType>
|
||||
|
||||
@NotNull
|
||||
Collection<JetType> getValues();
|
||||
|
||||
enum BoundKind {
|
||||
LOWER_BOUND, UPPER_BOUND, EXACT_BOUND
|
||||
public enum class BoundKind {
|
||||
LOWER_BOUND
|
||||
UPPER_BOUND
|
||||
EXACT_BOUND
|
||||
}
|
||||
|
||||
class Bound {
|
||||
public final JetType type;
|
||||
public final BoundKind kind;
|
||||
public final ConstraintPosition position;
|
||||
|
||||
public Bound(@NotNull JetType type, @NotNull BoundKind kind, @NotNull ConstraintPosition position) {
|
||||
this.type = type;
|
||||
this.kind = kind;
|
||||
this.position = position;
|
||||
}
|
||||
}
|
||||
}
|
||||
public class Bound(public val constrainingType: JetType, public val kind: BoundKind, public val position: ConstraintPosition)
|
||||
}
|
||||
+97
-172
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,238 +14,163 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.calls.inference;
|
||||
package org.jetbrains.jet.lang.resolve.calls.inference
|
||||
|
||||
import kotlin.Function1;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstructor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.utils.UtilsPackage;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.jet.lang.types.Variance
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.Bound
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils
|
||||
import org.jetbrains.jet.lang.types.CommonSupertypes
|
||||
import org.jetbrains.jet.lang.types.TypeUtils
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
|
||||
import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstructor
|
||||
import java.util.LinkedHashSet
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind.*
|
||||
import org.jetbrains.jet.utils.addIfNotNull
|
||||
|
||||
import java.util.*;
|
||||
public class TypeBoundsImpl(
|
||||
override val typeVariable: TypeParameterDescriptor,
|
||||
override val varianceOfPosition: Variance
|
||||
) : TypeBounds {
|
||||
override val bounds = LinkedHashSet<Bound>()
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind.LOWER_BOUND;
|
||||
private var resultValues: Collection<JetType>? = null
|
||||
|
||||
public class TypeBoundsImpl implements TypeBounds {
|
||||
private final TypeParameterDescriptor typeVariable;
|
||||
private final Variance varianceOfPosition;
|
||||
private final Set<Bound> bounds = new LinkedHashSet<Bound>();
|
||||
|
||||
private Collection<JetType> resultValues;
|
||||
|
||||
public TypeBoundsImpl(
|
||||
@NotNull TypeParameterDescriptor typeVariable,
|
||||
@NotNull Variance varianceOfPosition
|
||||
) {
|
||||
this.typeVariable = typeVariable;
|
||||
this.varianceOfPosition = varianceOfPosition;
|
||||
public fun addBound(kind: BoundKind, constrainingType: JetType, position: ConstraintPosition) {
|
||||
resultValues = null
|
||||
bounds.add(Bound(constrainingType, kind, position))
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Variance getVarianceOfPosition() {
|
||||
return varianceOfPosition;
|
||||
override fun isEmpty(): Boolean {
|
||||
return getValues().isEmpty()
|
||||
}
|
||||
|
||||
public void addBound(@NotNull BoundKind kind, @NotNull JetType type, @NotNull ConstraintPosition position) {
|
||||
resultValues = null;
|
||||
bounds.add(new Bound(type, kind, position));
|
||||
private fun filterBounds(bounds: Collection<Bound>, kind: BoundKind): Set<JetType> {
|
||||
return filterBounds(bounds, kind, null)
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return getValues().isEmpty();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TypeParameterDescriptor getTypeVariable() {
|
||||
return typeVariable;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Collection<Bound> getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<JetType> filterBounds(
|
||||
@NotNull Collection<Bound> bounds,
|
||||
@NotNull BoundKind kind
|
||||
) {
|
||||
return filterBounds(bounds, kind, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<JetType> filterBounds(
|
||||
@NotNull Collection<Bound> bounds,
|
||||
@NotNull BoundKind kind,
|
||||
@Nullable Collection<JetType> errorValues
|
||||
) {
|
||||
Set<JetType> result = new LinkedHashSet<JetType>();
|
||||
for (Bound bound : bounds) {
|
||||
private fun filterBounds(bounds: Collection<Bound>, kind: BoundKind, errorValues: MutableCollection<JetType>?): Set<JetType> {
|
||||
val result = LinkedHashSet<JetType>()
|
||||
for (bound in bounds) {
|
||||
if (bound.kind == kind) {
|
||||
if (!ErrorUtils.containsErrorType(bound.type)) {
|
||||
result.add(bound.type);
|
||||
if (!ErrorUtils.containsErrorType(bound.constrainingType)) {
|
||||
result.add(bound.constrainingType)
|
||||
}
|
||||
else if (errorValues != null) {
|
||||
errorValues.add(bound.type);
|
||||
else {
|
||||
errorValues?.add(bound.constrainingType)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return result
|
||||
}
|
||||
|
||||
/*package*/ TypeBoundsImpl copy() {
|
||||
TypeBoundsImpl typeBounds = new TypeBoundsImpl(typeVariable, varianceOfPosition);
|
||||
typeBounds.bounds.addAll(bounds);
|
||||
typeBounds.resultValues = resultValues;
|
||||
return typeBounds;
|
||||
fun copy(): TypeBoundsImpl {
|
||||
val typeBounds = TypeBoundsImpl(typeVariable, varianceOfPosition)
|
||||
typeBounds.bounds.addAll(bounds)
|
||||
typeBounds.resultValues = resultValues
|
||||
return typeBounds
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TypeBoundsImpl filter(@NotNull final Function1<ConstraintPosition, Boolean> condition) {
|
||||
TypeBoundsImpl result = new TypeBoundsImpl(typeVariable, varianceOfPosition);
|
||||
result.bounds.addAll(KotlinPackage.filter(bounds, new Function1<Bound, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(Bound bound) {
|
||||
return condition.invoke(bound.position);
|
||||
}
|
||||
}));
|
||||
return result;
|
||||
public fun filter(condition: (ConstraintPosition) -> Boolean): TypeBoundsImpl {
|
||||
val result = TypeBoundsImpl(typeVariable, varianceOfPosition)
|
||||
result.bounds.addAll(bounds.filter { condition(it.position) })
|
||||
return result
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JetType getValue() {
|
||||
Collection<JetType> values = getValues();
|
||||
override fun getValue(): JetType? {
|
||||
val values = getValues()
|
||||
if (values.size() == 1) {
|
||||
return values.iterator().next();
|
||||
return values.iterator().next()
|
||||
}
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<JetType> getValues() {
|
||||
override fun getValues(): Collection<JetType> {
|
||||
if (resultValues == null) {
|
||||
resultValues = computeValues();
|
||||
resultValues = computeValues()
|
||||
}
|
||||
return resultValues;
|
||||
return resultValues!!
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Collection<JetType> computeValues() {
|
||||
Set<JetType> values = new LinkedHashSet<JetType>();
|
||||
private fun computeValues(): Collection<JetType> {
|
||||
val values = LinkedHashSet<JetType>()
|
||||
if (bounds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
return listOf()
|
||||
}
|
||||
boolean hasStrongBound = KotlinPackage.any(bounds, new Function1<Bound, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(Bound bound) {
|
||||
return bound.position.isStrong();
|
||||
}
|
||||
});
|
||||
val hasStrongBound = bounds.any { it.position.isStrong() }
|
||||
if (!hasStrongBound) {
|
||||
return Collections.emptyList();
|
||||
return listOf()
|
||||
}
|
||||
|
||||
Set<JetType> exactBounds = filterBounds(bounds, BoundKind.EXACT_BOUND, values);
|
||||
JetType bestFit = TypesPackage.singleBestRepresentative(exactBounds);
|
||||
if (bestFit != null) {
|
||||
if (tryPossibleAnswer(bestFit)) {
|
||||
return Collections.singleton(bestFit);
|
||||
val exactBounds = filterBounds(bounds, EXACT_BOUND, values)
|
||||
if (exactBounds.size() == 1) {
|
||||
val exactBound = exactBounds.iterator().next()
|
||||
if (tryPossibleAnswer(exactBound)) {
|
||||
return setOf(exactBound)
|
||||
}
|
||||
}
|
||||
values.addAll(exactBounds);
|
||||
values.addAll(exactBounds)
|
||||
|
||||
Collection<JetType> numberLowerBounds = new LinkedHashSet<JetType>();
|
||||
Collection<JetType> generalLowerBounds = new LinkedHashSet<JetType>();
|
||||
filterNumberTypes(filterBounds(bounds, LOWER_BOUND, values), numberLowerBounds, generalLowerBounds);
|
||||
val (numberLowerBounds, generalLowerBounds) =
|
||||
filterBounds(bounds, LOWER_BOUND, values).partition { it.getConstructor() is IntegerValueTypeConstructor }
|
||||
|
||||
JetType superTypeOfLowerBounds = CommonSupertypes.commonSupertypeForNonDenotableTypes(generalLowerBounds);
|
||||
val superTypeOfLowerBounds = CommonSupertypes.commonSupertypeForNonDenotableTypes(generalLowerBounds)
|
||||
if (tryPossibleAnswer(superTypeOfLowerBounds)) {
|
||||
return Collections.singleton(superTypeOfLowerBounds);
|
||||
return setOf(superTypeOfLowerBounds!!)
|
||||
}
|
||||
UtilsPackage.addIfNotNull(values, superTypeOfLowerBounds);
|
||||
values.addIfNotNull(superTypeOfLowerBounds)
|
||||
|
||||
//todo
|
||||
//fun <T> foo(t: T, consumer: Consumer<T>): T
|
||||
//foo(1, c: Consumer<Any>) - infer Int, not Any here
|
||||
|
||||
JetType superTypeOfNumberLowerBounds = TypeUtils.commonSupertypeForNumberTypes(numberLowerBounds);
|
||||
val superTypeOfNumberLowerBounds = TypeUtils.commonSupertypeForNumberTypes(numberLowerBounds)
|
||||
if (tryPossibleAnswer(superTypeOfNumberLowerBounds)) {
|
||||
return Collections.singleton(superTypeOfNumberLowerBounds);
|
||||
return setOf(superTypeOfNumberLowerBounds!!)
|
||||
}
|
||||
UtilsPackage.addIfNotNull(values, superTypeOfNumberLowerBounds);
|
||||
values.addIfNotNull(superTypeOfNumberLowerBounds)
|
||||
|
||||
if (superTypeOfLowerBounds != null && superTypeOfNumberLowerBounds != null) {
|
||||
JetType superTypeOfAllLowerBounds = CommonSupertypes.commonSupertypeForNonDenotableTypes(
|
||||
Arrays.asList(superTypeOfLowerBounds, superTypeOfNumberLowerBounds)
|
||||
);
|
||||
val superTypeOfAllLowerBounds = CommonSupertypes.commonSupertypeForNonDenotableTypes(listOf(superTypeOfLowerBounds, superTypeOfNumberLowerBounds))
|
||||
if (tryPossibleAnswer(superTypeOfAllLowerBounds)) {
|
||||
return Collections.singleton(superTypeOfAllLowerBounds);
|
||||
return setOf(superTypeOfAllLowerBounds!!)
|
||||
}
|
||||
}
|
||||
|
||||
Set<JetType> upperBounds = filterBounds(bounds, BoundKind.UPPER_BOUND, values);
|
||||
JetType intersectionOfUpperBounds = TypeUtils.intersect(JetTypeChecker.DEFAULT, upperBounds);
|
||||
val upperBounds = filterBounds(bounds, TypeBounds.BoundKind.UPPER_BOUND, values)
|
||||
val intersectionOfUpperBounds = TypeUtils.intersect(JetTypeChecker.DEFAULT, upperBounds)
|
||||
if (!upperBounds.isEmpty() && intersectionOfUpperBounds != null) {
|
||||
if (tryPossibleAnswer(intersectionOfUpperBounds)) {
|
||||
return Collections.singleton(intersectionOfUpperBounds);
|
||||
return setOf(intersectionOfUpperBounds)
|
||||
}
|
||||
}
|
||||
|
||||
values.addAll(filterBounds(bounds, BoundKind.UPPER_BOUND));
|
||||
values.addAll(filterBounds(bounds, TypeBounds.BoundKind.UPPER_BOUND))
|
||||
|
||||
return values;
|
||||
return values
|
||||
}
|
||||
|
||||
private static void filterNumberTypes(
|
||||
@NotNull Collection<JetType> types,
|
||||
@NotNull Collection<JetType> numberTypes,
|
||||
@NotNull Collection<JetType> otherTypes
|
||||
) {
|
||||
for (JetType type : types) {
|
||||
if (type.getConstructor() instanceof IntegerValueTypeConstructor) {
|
||||
numberTypes.add(type);
|
||||
}
|
||||
else {
|
||||
otherTypes.add(type);
|
||||
private fun tryPossibleAnswer(possibleAnswer: JetType?): Boolean {
|
||||
if (possibleAnswer == null) return false
|
||||
if (!possibleAnswer.getConstructor().isDenotable()) return false
|
||||
|
||||
for (bound in bounds) {
|
||||
when (bound.kind) {
|
||||
LOWER_BOUND -> if (!JetTypeChecker.DEFAULT.isSubtypeOf(bound.constrainingType, possibleAnswer)) {
|
||||
return false
|
||||
}
|
||||
|
||||
UPPER_BOUND -> if (!JetTypeChecker.DEFAULT.isSubtypeOf(possibleAnswer, bound.constrainingType)) {
|
||||
return false
|
||||
}
|
||||
|
||||
EXACT_BOUND -> if (!JetTypeChecker.DEFAULT.equalTypes(bound.constrainingType, possibleAnswer)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private boolean tryPossibleAnswer(@Nullable JetType possibleAnswer) {
|
||||
if (possibleAnswer == null) return false;
|
||||
if (!possibleAnswer.getConstructor().isDenotable()) return false;
|
||||
|
||||
for (Bound bound : bounds) {
|
||||
switch (bound.kind) {
|
||||
case LOWER_BOUND:
|
||||
if (!JetTypeChecker.DEFAULT.isSubtypeOf(bound.type, possibleAnswer)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case UPPER_BOUND:
|
||||
if (!JetTypeChecker.DEFAULT.isSubtypeOf(possibleAnswer, bound.type)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case EXACT_BOUND:
|
||||
if (!JetTypeChecker.DEFAULT.equalTypes(bound.type, possibleAnswer)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -711,6 +711,7 @@ public class TypeUtils {
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static TypeSubstitutor makeSubstitutorForTypeParametersMap(
|
||||
@NotNull final Map<TypeParameterDescriptor, TypeProjection> substitutionContext
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user