Make ConstraintSystem work with variables, provide API to map to descriptors
This commit is contained in:
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.types.TypeIntersector
|
|||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
|
|
||||||
@@ -162,15 +163,15 @@ public object Renderers {
|
|||||||
substitutedDescriptors.add(substitutedDescriptor)
|
substitutedDescriptors.add(substitutedDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
val firstConflictingParameter = ConstraintsUtil.getFirstConflictingParameter(inferenceErrorData.constraintSystem)
|
val firstConflictingVariable = ConstraintsUtil.getFirstConflictingVariable(inferenceErrorData.constraintSystem)
|
||||||
if (firstConflictingParameter == null) {
|
if (firstConflictingVariable == null) {
|
||||||
LOG.error(renderDebugMessage("There is no conflicting parameter for 'conflicting constraints' error.", inferenceErrorData))
|
LOG.error(renderDebugMessage("There is no conflicting parameter for 'conflicting constraints' error.", inferenceErrorData))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
result.text(newText()
|
result.text(newText()
|
||||||
.normal("Cannot infer type parameter ")
|
.normal("Cannot infer type parameter ")
|
||||||
.strong(firstConflictingParameter.getName())
|
.strong(firstConflictingVariable.name)
|
||||||
.normal(" in "))
|
.normal(" in "))
|
||||||
val table = newTable()
|
val table = newTable()
|
||||||
result.table(table)
|
result.table(table)
|
||||||
@@ -224,21 +225,15 @@ public object Renderers {
|
|||||||
public fun renderNoInformationForParameterError(
|
public fun renderNoInformationForParameterError(
|
||||||
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
||||||
): TabledDescriptorRenderer {
|
): TabledDescriptorRenderer {
|
||||||
var firstUnknownParameter: TypeParameterDescriptor? = null
|
val firstUnknownVariable = inferenceErrorData.constraintSystem.typeVariables.firstOrNull { variable ->
|
||||||
for (typeParameter in inferenceErrorData.constraintSystem.typeParameterDescriptors) {
|
inferenceErrorData.constraintSystem.getTypeBounds(variable).values.isEmpty()
|
||||||
if (inferenceErrorData.constraintSystem.getTypeBounds(typeParameter).values.isEmpty()) {
|
} ?: return result.apply {
|
||||||
firstUnknownParameter = typeParameter
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (firstUnknownParameter == null) {
|
|
||||||
LOG.error(renderDebugMessage("There is no unknown parameter for 'no information for parameter error'.", inferenceErrorData))
|
LOG.error(renderDebugMessage("There is no unknown parameter for 'no information for parameter error'.", inferenceErrorData))
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
.text(newText().normal("Not enough information to infer parameter ")
|
.text(newText().normal("Not enough information to infer parameter ")
|
||||||
.strong(firstUnknownParameter.getName())
|
.strong(firstUnknownVariable.name)
|
||||||
.normal(" in "))
|
.normal(" in "))
|
||||||
.table(newTable()
|
.table(newTable()
|
||||||
.descriptor(inferenceErrorData.descriptor)
|
.descriptor(inferenceErrorData.descriptor)
|
||||||
@@ -266,7 +261,8 @@ public object Renderers {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
val inferredValueForTypeParameter = systemWithoutWeakConstraints.getTypeBounds(typeParameterDescriptor).value
|
val inferredValueForTypeParameter =
|
||||||
|
systemWithoutWeakConstraints.getTypeBounds(systemWithoutWeakConstraints.descriptorToVariable(typeParameterDescriptor)).value
|
||||||
if (inferredValueForTypeParameter == null) {
|
if (inferredValueForTypeParameter == null) {
|
||||||
LOG.error(renderDebugMessage("System without weak constraints is not successful, there is no value for type parameter " +
|
LOG.error(renderDebugMessage("System without weak constraints is not successful, there is no value for type parameter " +
|
||||||
typeParameterDescriptor.getName() + "\n: " + systemWithoutWeakConstraints, inferenceErrorData))
|
typeParameterDescriptor.getName() + "\n: " + systemWithoutWeakConstraints, inferenceErrorData))
|
||||||
@@ -308,15 +304,15 @@ public object Renderers {
|
|||||||
public fun renderCannotCaptureTypeParameterError(
|
public fun renderCannotCaptureTypeParameterError(
|
||||||
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
||||||
): TabledDescriptorRenderer {
|
): TabledDescriptorRenderer {
|
||||||
val constraintSystem = inferenceErrorData.constraintSystem
|
val system = inferenceErrorData.constraintSystem
|
||||||
val errors = constraintSystem.status.constraintErrors
|
val errors = system.status.constraintErrors
|
||||||
val typeParameterWithCapturedConstraint = (errors.firstOrNull { it is CannotCapture } as? CannotCapture)?.typeVariable
|
val typeVariableWithCapturedConstraint = errors.firstIsInstanceOrNull<CannotCapture>()?.typeVariable
|
||||||
if (typeParameterWithCapturedConstraint == null) {
|
if (typeVariableWithCapturedConstraint == null) {
|
||||||
LOG.error(renderDebugMessage("An error 'cannot capture type parameter' is not found in errors", inferenceErrorData))
|
LOG.error(renderDebugMessage("An error 'cannot capture type parameter' is not found in errors", inferenceErrorData))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
val typeBounds = constraintSystem.getTypeBounds(typeParameterWithCapturedConstraint)
|
val typeBounds = system.getTypeBounds(typeVariableWithCapturedConstraint)
|
||||||
val boundWithCapturedType = typeBounds.bounds.firstOrNull { it.constrainingType.isCaptured() }
|
val boundWithCapturedType = typeBounds.bounds.firstOrNull { it.constrainingType.isCaptured() }
|
||||||
val capturedTypeConstructor = boundWithCapturedType?.constrainingType?.getConstructor() as? CapturedTypeConstructor
|
val capturedTypeConstructor = boundWithCapturedType?.constrainingType?.getConstructor() as? CapturedTypeConstructor
|
||||||
if (capturedTypeConstructor == null) {
|
if (capturedTypeConstructor == null) {
|
||||||
@@ -324,8 +320,10 @@ public object Renderers {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val typeParameter = system.variableToDescriptor(typeVariableWithCapturedConstraint)
|
||||||
|
|
||||||
val explanation: String
|
val explanation: String
|
||||||
val upperBound = TypeIntersector.getUpperBoundsAsType(typeParameterWithCapturedConstraint)
|
val upperBound = TypeIntersector.getUpperBoundsAsType(typeParameter)
|
||||||
if (!KotlinBuiltIns.isNullableAny(upperBound) && capturedTypeConstructor.typeProjection.getProjectionKind() == Variance.IN_VARIANCE) {
|
if (!KotlinBuiltIns.isNullableAny(upperBound) && capturedTypeConstructor.typeProjection.getProjectionKind() == Variance.IN_VARIANCE) {
|
||||||
explanation = "Type parameter has an upper bound '" + result.getTypeRenderer().render(upperBound) + "'" +
|
explanation = "Type parameter has an upper bound '" + result.getTypeRenderer().render(upperBound) + "'" +
|
||||||
" that cannot be satisfied capturing 'in' projection"
|
" that cannot be satisfied capturing 'in' projection"
|
||||||
@@ -333,10 +331,12 @@ public object Renderers {
|
|||||||
else {
|
else {
|
||||||
explanation = "Only top-level type projections can be captured"
|
explanation = "Only top-level type projections can be captured"
|
||||||
}
|
}
|
||||||
result.text(newText().normal("'" + typeParameterWithCapturedConstraint.getName() + "'" +
|
result.text(newText().normal(
|
||||||
" cannot capture " +
|
"'" + typeParameter.name + "'" +
|
||||||
"'" + capturedTypeConstructor.typeProjection + "'. " +
|
" cannot capture " +
|
||||||
explanation))
|
"'" + capturedTypeConstructor.typeProjection + "'. " +
|
||||||
|
explanation
|
||||||
|
))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,9 +362,8 @@ public object Renderers {
|
|||||||
public val RENDER_COLLECTION_OF_TYPES: Renderer<Collection<KotlinType>> = Renderer { renderTypes(it) }
|
public val RENDER_COLLECTION_OF_TYPES: Renderer<Collection<KotlinType>> = Renderer { renderTypes(it) }
|
||||||
|
|
||||||
private fun renderConstraintSystem(constraintSystem: ConstraintSystem, renderTypeBounds: Renderer<TypeBounds>): String {
|
private fun renderConstraintSystem(constraintSystem: ConstraintSystem, renderTypeBounds: Renderer<TypeBounds>): String {
|
||||||
val typeVariables = constraintSystem.typeParameterDescriptors
|
|
||||||
val typeBounds = linkedSetOf<TypeBounds>()
|
val typeBounds = linkedSetOf<TypeBounds>()
|
||||||
for (variable in typeVariables) {
|
for (variable in constraintSystem.typeVariables) {
|
||||||
typeBounds.add(constraintSystem.getTypeBounds(variable))
|
typeBounds.add(constraintSystem.getTypeBounds(variable))
|
||||||
}
|
}
|
||||||
return "type parameter bounds:\n" +
|
return "type parameter bounds:\n" +
|
||||||
|
|||||||
+1
-1
@@ -165,7 +165,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
|||||||
val candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidateDescriptor)
|
val candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidateDescriptor)
|
||||||
val conversion = candidateDescriptor.typeParameters.zip(candidateWithFreshVariables.typeParameters).toMap()
|
val conversion = candidateDescriptor.typeParameters.zip(candidateWithFreshVariables.typeParameters).toMap()
|
||||||
|
|
||||||
val freshVariables = nestedTypeVariables.map { conversion[it] }.filterNotNull()
|
val freshVariables = nestedTypeVariables.map { conversion[argumentConstraintSystem.variableToDescriptor(it)] }.filterNotNull()
|
||||||
builder.registerTypeVariables(freshVariables, external = true)
|
builder.registerTypeVariables(freshVariables, external = true)
|
||||||
|
|
||||||
builder.addSubtypeConstraint(candidateWithFreshVariables.returnType, effectiveExpectedType, constraintPosition)
|
builder.addSubtypeConstraint(candidateWithFreshVariables.returnType, effectiveExpectedType, constraintPosition)
|
||||||
|
|||||||
+5
-1
@@ -36,11 +36,15 @@ interface ConstraintSystem {
|
|||||||
*/
|
*/
|
||||||
val typeVariables: Set<TypeParameterDescriptor>
|
val typeVariables: Set<TypeParameterDescriptor>
|
||||||
|
|
||||||
|
fun descriptorToVariable(descriptor: TypeParameterDescriptor): TypeParameterDescriptor
|
||||||
|
|
||||||
|
fun variableToDescriptor(typeVariable: TypeParameterDescriptor): TypeParameterDescriptor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the resulting type constraints of solving the constraint system for specific type parameter descriptor.
|
* Returns the resulting type constraints of solving the constraint system for specific type parameter descriptor.
|
||||||
* Throws IllegalArgumentException if the type parameter descriptor is not known to the system.
|
* Throws IllegalArgumentException if the type parameter descriptor is not known to the system.
|
||||||
*/
|
*/
|
||||||
fun getTypeBounds(descriptor: TypeParameterDescriptor): TypeBounds
|
fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBounds
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the result of solving the constraint system (mapping from the type variable to the resulting type projection).
|
* Returns the result of solving the constraint system (mapping from the type variable to the resulting type projection).
|
||||||
|
|||||||
+7
-7
@@ -149,15 +149,15 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun capture(typeVariable: KotlinType, typeProjection: TypeProjection): Boolean {
|
override fun capture(type: KotlinType, typeProjection: TypeProjection): Boolean {
|
||||||
if (isMyTypeVariable(typeProjection.type)) return false
|
if (isMyTypeVariable(typeProjection.type)) return false
|
||||||
val myTypeVariable = getMyTypeVariable(typeVariable)
|
val myTypeVariable = getMyTypeVariable(type)
|
||||||
|
|
||||||
if (myTypeVariable != null && constraintPosition.isParameter()) {
|
if (myTypeVariable != null && constraintPosition.isParameter()) {
|
||||||
if (depth > 0) {
|
if (depth > 0) {
|
||||||
errors.add(CannotCapture(constraintPosition, myTypeVariable))
|
errors.add(CannotCapture(constraintPosition, myTypeVariable))
|
||||||
}
|
}
|
||||||
generateTypeParameterCaptureConstraint(typeVariable, typeProjection, newConstraintContext)
|
generateTypeParameterCaptureConstraint(myTypeVariable, typeProjection, newConstraintContext, type.isMarkedNullable)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -311,16 +311,16 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateTypeParameterCaptureConstraint(
|
private fun generateTypeParameterCaptureConstraint(
|
||||||
parameterType: KotlinType,
|
typeVariable: TypeParameterDescriptor,
|
||||||
constrainingTypeProjection: TypeProjection,
|
constrainingTypeProjection: TypeProjection,
|
||||||
constraintContext: ConstraintContext
|
constraintContext: ConstraintContext,
|
||||||
|
isTypeMarkedNullable: Boolean
|
||||||
) {
|
) {
|
||||||
val typeVariable = getMyTypeVariable(parameterType)!!
|
|
||||||
if (!typeVariable.upperBounds.let { it.size == 1 && it.single().isDefaultBound() } &&
|
if (!typeVariable.upperBounds.let { it.size == 1 && it.single().isDefaultBound() } &&
|
||||||
constrainingTypeProjection.projectionKind == Variance.IN_VARIANCE) {
|
constrainingTypeProjection.projectionKind == Variance.IN_VARIANCE) {
|
||||||
errors.add(CannotCapture(constraintContext.position, typeVariable))
|
errors.add(CannotCapture(constraintContext.position, typeVariable))
|
||||||
}
|
}
|
||||||
val typeProjection = if (parameterType.isMarkedNullable) {
|
val typeProjection = if (isTypeMarkedNullable) {
|
||||||
TypeProjectionImpl(constrainingTypeProjection.projectionKind, TypeUtils.makeNotNullable(constrainingTypeProjection.type))
|
TypeProjectionImpl(constrainingTypeProjection.projectionKind, TypeUtils.makeNotNullable(constrainingTypeProjection.type))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+12
-9
@@ -112,8 +112,9 @@ internal class ConstraintSystemImpl(
|
|||||||
|
|
||||||
override fun getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor> {
|
override fun getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor> {
|
||||||
return type.getNestedArguments().map { typeProjection ->
|
return type.getNestedArguments().map { typeProjection ->
|
||||||
typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
val descriptor = typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
||||||
}.filterNotNull().filter { it in typeParameterDescriptors }
|
descriptor?.let { descriptorToVariable[it] }
|
||||||
|
}.filterNotNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val typeParameterDescriptors: Set<TypeParameterDescriptor>
|
override val typeParameterDescriptors: Set<TypeParameterDescriptor>
|
||||||
@@ -122,13 +123,15 @@ internal class ConstraintSystemImpl(
|
|||||||
override val typeVariables: Set<TypeParameterDescriptor>
|
override val typeVariables: Set<TypeParameterDescriptor>
|
||||||
get() = variableToDescriptor.keys
|
get() = variableToDescriptor.keys
|
||||||
|
|
||||||
override fun getTypeBounds(descriptor: TypeParameterDescriptor): TypeBoundsImpl {
|
override fun descriptorToVariable(descriptor: TypeParameterDescriptor): TypeParameterDescriptor =
|
||||||
val variable = descriptorToVariable[descriptor]
|
descriptorToVariable[descriptor] ?: throw IllegalArgumentException("Unknown descriptor: $descriptor")
|
||||||
if (variable != null && variable != descriptor) {
|
|
||||||
return getTypeBounds(variable)
|
override fun variableToDescriptor(typeVariable: TypeParameterDescriptor): TypeParameterDescriptor =
|
||||||
}
|
variableToDescriptor[typeVariable] ?: throw IllegalArgumentException("Unknown type variable: $typeVariable")
|
||||||
return allTypeParameterBounds[descriptor] ?:
|
|
||||||
throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $descriptor")
|
override fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBoundsImpl {
|
||||||
|
return allTypeParameterBounds[typeVariable] ?:
|
||||||
|
throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $typeVariable")
|
||||||
}
|
}
|
||||||
|
|
||||||
override val resultingSubstitutor: TypeSubstitutor
|
override val resultingSubstitutor: TypeSubstitutor
|
||||||
|
|||||||
+17
-16
@@ -30,11 +30,11 @@ import java.util.*;
|
|||||||
|
|
||||||
public class ConstraintsUtil {
|
public class ConstraintsUtil {
|
||||||
@Nullable
|
@Nullable
|
||||||
public static TypeParameterDescriptor getFirstConflictingParameter(@NotNull ConstraintSystem constraintSystem) {
|
public static TypeParameterDescriptor getFirstConflictingVariable(@NotNull ConstraintSystem constraintSystem) {
|
||||||
for (TypeParameterDescriptor typeParameter : constraintSystem.getTypeParameterDescriptors()) {
|
for (TypeParameterDescriptor typeVariable : constraintSystem.getTypeVariables()) {
|
||||||
TypeBounds constraints = constraintSystem.getTypeBounds(typeParameter);
|
TypeBounds constraints = constraintSystem.getTypeBounds(typeVariable);
|
||||||
if (constraints.getValues().size() > 1) {
|
if (constraints.getValues().size() > 1) {
|
||||||
return typeParameter;
|
return typeVariable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -42,10 +42,11 @@ public class ConstraintsUtil {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Collection<TypeSubstitutor> getSubstitutorsForConflictingParameters(@NotNull ConstraintSystem constraintSystem) {
|
public static Collection<TypeSubstitutor> getSubstitutorsForConflictingParameters(@NotNull ConstraintSystem constraintSystem) {
|
||||||
TypeParameterDescriptor firstConflictingParameter = getFirstConflictingParameter(constraintSystem);
|
TypeParameterDescriptor firstConflictingVariable = getFirstConflictingVariable(constraintSystem);
|
||||||
if (firstConflictingParameter == null) return Collections.emptyList();
|
if (firstConflictingVariable == null) return Collections.emptyList();
|
||||||
|
TypeParameterDescriptor firstConflictingParameter = constraintSystem.variableToDescriptor(firstConflictingVariable);
|
||||||
|
|
||||||
Collection<KotlinType> conflictingTypes = constraintSystem.getTypeBounds(firstConflictingParameter).getValues();
|
Collection<KotlinType> conflictingTypes = constraintSystem.getTypeBounds(firstConflictingVariable).getValues();
|
||||||
|
|
||||||
List<Map<TypeConstructor, TypeProjection>> substitutionContexts = Lists.newArrayList();
|
List<Map<TypeConstructor, TypeProjection>> substitutionContexts = Lists.newArrayList();
|
||||||
for (KotlinType type : conflictingTypes) {
|
for (KotlinType type : conflictingTypes) {
|
||||||
@@ -54,16 +55,16 @@ public class ConstraintsUtil {
|
|||||||
substitutionContexts.add(context);
|
substitutionContexts.add(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TypeParameterDescriptor typeParameter : constraintSystem.getTypeParameterDescriptors()) {
|
for (TypeParameterDescriptor typeVariable : constraintSystem.getTypeVariables()) {
|
||||||
if (typeParameter == firstConflictingParameter) continue;
|
if (typeVariable == firstConflictingVariable) continue;
|
||||||
|
|
||||||
KotlinType safeType = getSafeValue(constraintSystem, typeParameter);
|
KotlinType safeType = getSafeValue(constraintSystem, typeVariable);
|
||||||
for (Map<TypeConstructor, TypeProjection> context : substitutionContexts) {
|
for (Map<TypeConstructor, TypeProjection> context : substitutionContexts) {
|
||||||
TypeProjection typeProjection = new TypeProjectionImpl(safeType);
|
TypeProjection typeProjection = new TypeProjectionImpl(safeType);
|
||||||
context.put(typeParameter.getTypeConstructor(), typeProjection);
|
context.put(constraintSystem.variableToDescriptor(typeVariable).getTypeConstructor(), typeProjection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Collection<TypeSubstitutor> typeSubstitutors = Lists.newArrayList();
|
Collection<TypeSubstitutor> typeSubstitutors = new ArrayList<TypeSubstitutor>(substitutionContexts.size());
|
||||||
for (Map<TypeConstructor, TypeProjection> context : substitutionContexts) {
|
for (Map<TypeConstructor, TypeProjection> context : substitutionContexts) {
|
||||||
typeSubstitutors.add(TypeSubstitutor.create(context));
|
typeSubstitutors.add(TypeSubstitutor.create(context));
|
||||||
}
|
}
|
||||||
@@ -71,13 +72,13 @@ public class ConstraintsUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static KotlinType getSafeValue(@NotNull ConstraintSystem constraintSystem, @NotNull TypeParameterDescriptor typeParameter) {
|
private static KotlinType getSafeValue(@NotNull ConstraintSystem constraintSystem, @NotNull TypeParameterDescriptor typeVariable) {
|
||||||
KotlinType type = constraintSystem.getTypeBounds(typeParameter).getValue();
|
KotlinType type = constraintSystem.getTypeBounds(typeVariable).getValue();
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
//todo may be error type
|
//todo may be error type
|
||||||
return TypeIntersector.getUpperBoundsAsType(typeParameter);
|
return TypeIntersector.getUpperBoundsAsType(constraintSystem.variableToDescriptor(typeVariable));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean checkUpperBoundIsSatisfied(
|
public static boolean checkUpperBoundIsSatisfied(
|
||||||
@@ -85,7 +86,7 @@ public class ConstraintsUtil {
|
|||||||
@NotNull TypeParameterDescriptor typeParameter,
|
@NotNull TypeParameterDescriptor typeParameter,
|
||||||
boolean substituteOtherTypeParametersInBound
|
boolean substituteOtherTypeParametersInBound
|
||||||
) {
|
) {
|
||||||
KotlinType type = constraintSystem.getTypeBounds(typeParameter).getValue();
|
KotlinType type = constraintSystem.getTypeBounds(constraintSystem.descriptorToVariable(typeParameter)).getValue();
|
||||||
if (type == null) return true;
|
if (type == null) return true;
|
||||||
for (KotlinType upperBound : typeParameter.getUpperBounds()) {
|
for (KotlinType upperBound : typeParameter.getUpperBounds()) {
|
||||||
if (!substituteOtherTypeParametersInBound &&
|
if (!substituteOtherTypeParametersInBound &&
|
||||||
|
|||||||
Reference in New Issue
Block a user