Add call to type variable and mapping descriptor -> variable

Since type parameter descriptor represents a single declaration of a type
parameter, multiple variables in one system may correspond to one type
parameter (e.g. in case of nested calls). Hence it's not possible to map type
parameters uniquely onto type variables and additional information is required
This commit is contained in:
Alexander Udalov
2015-11-11 20:24:13 +03:00
parent fc73e8c620
commit 178ca3daae
14 changed files with 83 additions and 36 deletions
@@ -251,7 +251,7 @@ public object Renderers {
val systemWithoutWeakConstraints = constraintSystem.filterConstraintsOut(ConstraintPositionKind.TYPE_BOUND_POSITION) val systemWithoutWeakConstraints = constraintSystem.filterConstraintsOut(ConstraintPositionKind.TYPE_BOUND_POSITION)
val typeParameterDescriptor = inferenceErrorData.descriptor.typeParameters.firstOrNull { val typeParameterDescriptor = inferenceErrorData.descriptor.typeParameters.firstOrNull {
!ConstraintsUtil.checkUpperBoundIsSatisfied(systemWithoutWeakConstraints, it, true) !ConstraintsUtil.checkUpperBoundIsSatisfied(systemWithoutWeakConstraints, it, inferenceErrorData.call, true)
} }
if (typeParameterDescriptor == null && status.hasConflictingConstraints()) { if (typeParameterDescriptor == null && status.hasConflictingConstraints()) {
return renderConflictingSubstitutionsInferenceError(inferenceErrorData, result) return renderConflictingSubstitutionsInferenceError(inferenceErrorData, result)
@@ -261,8 +261,8 @@ public object Renderers {
return result return result
} }
val inferredValueForTypeParameter = val typeVariable = systemWithoutWeakConstraints.descriptorToVariable(inferenceErrorData.call.toHandle(), typeParameterDescriptor)
systemWithoutWeakConstraints.getTypeBounds(systemWithoutWeakConstraints.descriptorToVariable(typeParameterDescriptor)).value val inferredValueForTypeParameter = systemWithoutWeakConstraints.getTypeBounds(typeVariable).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))
@@ -204,7 +204,8 @@ public class CallCompleter(
val errorData = InferenceErrorData.create( val errorData = InferenceErrorData.create(
getCandidateDescriptor(), getConstraintSystem()!!, valueArgumentsCheckingResult.argumentTypes, getCandidateDescriptor(), getConstraintSystem()!!, valueArgumentsCheckingResult.argumentTypes,
receiverType, context.expectedType) receiverType, context.expectedType, context.call
)
tracing.typeInferenceFailed(context.trace, errorData) tracing.typeInferenceFailed(context.trace, errorData)
addStatus(ResolutionStatus.OTHER_ERROR) addStatus(ResolutionStatus.OTHER_ERROR)
@@ -32,13 +32,10 @@ import org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.ResolutionResultsCache import org.jetbrains.kotlin.resolve.calls.context.ResolutionResultsCache
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.*
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
import org.jetbrains.kotlin.resolve.calls.inference.getNestedTypeParameters
import org.jetbrains.kotlin.resolve.calls.inference.getNestedTypeVariables
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.OTHER_ERROR import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.OTHER_ERROR
@@ -56,7 +53,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
val candidate = candidateCall.candidateDescriptor val candidate = candidateCall.candidateDescriptor
val builder = ConstraintSystemBuilderImpl() val builder = ConstraintSystemBuilderImpl()
builder.registerTypeVariables(candidate.typeParameters) builder.registerTypeVariables(candidateCall.call.toHandle(), candidate.typeParameters)
val substituteDontCare = makeConstantSubstitutor(candidate.typeParameters, DONT_CARE) val substituteDontCare = makeConstantSubstitutor(candidate.typeParameters, DONT_CARE)
@@ -158,7 +155,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
val conversion = candidateDescriptor.typeParameters.zip(candidateWithFreshVariables.typeParameters).toMap() val conversion = candidateDescriptor.typeParameters.zip(candidateWithFreshVariables.typeParameters).toMap()
val freshVariables = returnType.getNestedTypeParameters().map { conversion[it] }.filterNotNull() val freshVariables = returnType.getNestedTypeParameters().map { conversion[it] }.filterNotNull()
builder.registerTypeVariables(freshVariables, external = true) builder.registerTypeVariables(resultingCall.call.toHandle(), freshVariables, external = true)
builder.addSubtypeConstraint(candidateWithFreshVariables.returnType, effectiveExpectedType, constraintPosition) builder.addSubtypeConstraint(candidateWithFreshVariables.returnType, effectiveExpectedType, constraintPosition)
return true return true
@@ -34,7 +34,7 @@ interface ConstraintSystem {
*/ */
val typeVariables: Set<TypeVariable> val typeVariables: Set<TypeVariable>
fun descriptorToVariable(descriptor: TypeParameterDescriptor): TypeVariable fun descriptorToVariable(call: CallHandle, descriptor: TypeParameterDescriptor): TypeVariable
/** /**
* 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.
@@ -66,7 +66,9 @@ interface ConstraintSystem {
* Registers variables in a constraint system. Returns a substitutor which maps type parameter descriptors given as parameters * Registers variables in a constraint system. Returns a substitutor which maps type parameter descriptors given as parameters
* to the corresponding type variables of the system. Use that substitutor to provide constraints to the system * to the corresponding type variables of the system. Use that substitutor to provide constraints to the system
*/ */
fun registerTypeVariables(typeParameters: Collection<TypeParameterDescriptor>, external: Boolean = false): TypeSubstitutor fun registerTypeVariables(
call: CallHandle, typeParameters: Collection<TypeParameterDescriptor>, external: Boolean = false
): TypeSubstitutor
/** /**
* Adds a constraint that the constraining type is a subtype of the subject type. * Adds a constraint that the constraining type is a subtype of the subject type.
@@ -64,19 +64,25 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
}) })
} }
override fun registerTypeVariables(typeParameters: Collection<TypeParameterDescriptor>, external: Boolean): TypeSubstitutor { override fun registerTypeVariables(
call: CallHandle, typeParameters: Collection<TypeParameterDescriptor>, external: Boolean
): TypeSubstitutor {
if (typeParameters.isEmpty()) return TypeSubstitutor.EMPTY if (typeParameters.isEmpty()) return TypeSubstitutor.EMPTY
val typeVariables = (if (external) { val typeVariables = if (external) {
typeParameters.toList() typeParameters.map {
TypeVariable(call, it, it, true)
}
} }
else ArrayList<TypeParameterDescriptor>(typeParameters.size).apply { else {
val freshTypeParameters = ArrayList<TypeParameterDescriptor>(typeParameters.size)
DescriptorSubstitutor.substituteTypeParameters( DescriptorSubstitutor.substituteTypeParameters(
typeParameters.toList(), TypeSubstitution.EMPTY, typeParameters.first().containingDeclaration, this typeParameters.toList(), TypeSubstitution.EMPTY, typeParameters.first().containingDeclaration, freshTypeParameters
) )
}).zip(typeParameters).map { freshTypeParameters.zip(typeParameters).map {
val (fresh, original) = it val (fresh, original) = it
TypeVariable(fresh, original, external) TypeVariable(call, fresh, original, external)
}
} }
for ((descriptor, typeVariable) in typeParameters.zip(typeVariables)) { for ((descriptor, typeVariable) in typeParameters.zip(typeVariables)) {
@@ -111,8 +111,8 @@ internal class ConstraintSystemImpl(
override val typeVariables: Set<TypeVariable> override val typeVariables: Set<TypeVariable>
get() = allTypeParameterBounds.keys get() = allTypeParameterBounds.keys
override fun descriptorToVariable(descriptor: TypeParameterDescriptor): TypeVariable = override fun descriptorToVariable(call: CallHandle, descriptor: TypeParameterDescriptor): TypeVariable =
descriptorToVariable[descriptor] ?: throw IllegalArgumentException("Unknown descriptor: $descriptor") descriptorToVariable[descriptor] ?: throw IllegalArgumentException("Unknown descriptor: $descriptor, call: $call")
override fun getTypeBounds(typeVariable: TypeVariable): TypeBoundsImpl { override fun getTypeBounds(typeVariable: TypeVariable): TypeBoundsImpl {
return allTypeParameterBounds[typeVariable] ?: return allTypeParameterBounds[typeVariable] ?:
@@ -21,6 +21,7 @@ import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.psi.Call;
import org.jetbrains.kotlin.types.*; import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
@@ -84,9 +85,11 @@ public class ConstraintsUtil {
public static boolean checkUpperBoundIsSatisfied( public static boolean checkUpperBoundIsSatisfied(
@NotNull ConstraintSystem constraintSystem, @NotNull ConstraintSystem constraintSystem,
@NotNull TypeParameterDescriptor typeParameter, @NotNull TypeParameterDescriptor typeParameter,
@NotNull Call call,
boolean substituteOtherTypeParametersInBound boolean substituteOtherTypeParametersInBound
) { ) {
KotlinType type = constraintSystem.getTypeBounds(constraintSystem.descriptorToVariable(typeParameter)).getValue(); TypeVariable typeVariable = constraintSystem.descriptorToVariable(TypeVariableKt.toHandle(call), typeParameter);
KotlinType type = constraintSystem.getTypeBounds(typeVariable).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 &&
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.inference;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.psi.Call;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinType;
import java.util.List; import java.util.List;
@@ -34,22 +35,34 @@ public class InferenceErrorData {
public final KotlinType expectedType; public final KotlinType expectedType;
@NotNull @NotNull
public final List<KotlinType> valueArgumentsTypes; public final List<KotlinType> valueArgumentsTypes;
@NotNull
public final Call call;
private InferenceErrorData( private InferenceErrorData(
@NotNull CallableDescriptor descriptor, @NotNull ConstraintSystem constraintSystem, @NotNull CallableDescriptor descriptor,
@NotNull List<KotlinType> valueArgumentsTypes, @Nullable KotlinType receiverArgumentType, @NotNull KotlinType expectedType @NotNull ConstraintSystem constraintSystem,
@NotNull List<KotlinType> valueArgumentsTypes,
@Nullable KotlinType receiverArgumentType,
@NotNull KotlinType expectedType,
@NotNull Call call
) { ) {
this.descriptor = descriptor; this.descriptor = descriptor;
this.constraintSystem = constraintSystem; this.constraintSystem = constraintSystem;
this.receiverArgumentType = receiverArgumentType; this.receiverArgumentType = receiverArgumentType;
this.valueArgumentsTypes = valueArgumentsTypes; this.valueArgumentsTypes = valueArgumentsTypes;
this.expectedType = expectedType; this.expectedType = expectedType;
this.call = call;
} }
@NotNull @NotNull
public static InferenceErrorData create(@NotNull CallableDescriptor descriptor, @NotNull ConstraintSystem constraintSystem, public static InferenceErrorData create(
@NotNull List<KotlinType> valueArgumentsTypes, @Nullable KotlinType receiverArgumentType, @NotNull KotlinType expectedType) { @NotNull CallableDescriptor descriptor,
return new InferenceErrorData(descriptor, constraintSystem, valueArgumentsTypes, receiverArgumentType, expectedType); @NotNull ConstraintSystem constraintSystem,
@NotNull List<KotlinType> valueArgumentsTypes,
@Nullable KotlinType receiverArgumentType,
@NotNull KotlinType expectedType,
@NotNull Call call
) {
return new InferenceErrorData(descriptor, constraintSystem, valueArgumentsTypes, receiverArgumentType, expectedType, call);
} }
} }
@@ -19,13 +19,15 @@ package org.jetbrains.kotlin.resolve.calls.inference
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.Call
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOnlyInputTypesAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.hasOnlyInputTypesAnnotation
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.KotlinTypeImpl import org.jetbrains.kotlin.types.KotlinTypeImpl
class TypeVariable( class TypeVariable(
val freshTypeParameter: TypeParameterDescriptor, val call: CallHandle,
internal val freshTypeParameter: TypeParameterDescriptor,
val originalTypeParameter: TypeParameterDescriptor, val originalTypeParameter: TypeParameterDescriptor,
val isExternal: Boolean val isExternal: Boolean
) { ) {
@@ -36,3 +38,20 @@ class TypeVariable(
fun hasOnlyInputTypesAnnotation(): Boolean = fun hasOnlyInputTypesAnnotation(): Boolean =
originalTypeParameter.hasOnlyInputTypesAnnotation() originalTypeParameter.hasOnlyInputTypesAnnotation()
} }
interface CallHandle {
object NONE : CallHandle
}
class CallBasedCallHandle(val call: Call): CallHandle {
override fun equals(other: Any?) =
other is CallBasedCallHandle && call === other.call
override fun hashCode() =
System.identityHashCode(call)
override fun toString() =
call.toString()
}
fun Call.toHandle(): CallHandle = CallBasedCallHandle(this)
@@ -24,8 +24,10 @@ import org.jetbrains.kotlin.types.TypeProjection
import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeProjectionImpl
import java.util.* import java.util.*
fun ConstraintSystem.getNestedTypeVariables(type: KotlinType): List<TypeVariable> = fun ConstraintSystem.getNestedTypeVariables(type: KotlinType): List<TypeVariable> {
type.getNestedTypeParameters().filter { it in typeParameterDescriptors }.map { descriptorToVariable(it) } val nestedTypeParameters = type.getNestedTypeParameters().toSet()
return typeVariables.filter { it.originalTypeParameter in nestedTypeParameters }
}
fun ConstraintSystem.filterConstraintsOut(excludePositionKind: ConstraintPositionKind): ConstraintSystem { fun ConstraintSystem.filterConstraintsOut(excludePositionKind: ConstraintPositionKind): ConstraintSystem {
return toBuilder { !it.derivedFrom(excludePositionKind) }.build() return toBuilder { !it.derivedFrom(excludePositionKind) }.build()
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor; import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.resolve.calls.inference.CallHandle;
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem; import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl; import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl;
import org.jetbrains.kotlin.resolve.scopes.ChainedScope; import org.jetbrains.kotlin.resolve.scopes.ChainedScope;
@@ -185,7 +186,7 @@ public class TypeIntersector {
processAllTypeParameters(withParameters, Variance.INVARIANT, processor); processAllTypeParameters(withParameters, Variance.INVARIANT, processor);
processAllTypeParameters(expected, Variance.INVARIANT, processor); processAllTypeParameters(expected, Variance.INVARIANT, processor);
ConstraintSystem.Builder constraintSystem = new ConstraintSystemBuilderImpl(); ConstraintSystem.Builder constraintSystem = new ConstraintSystemBuilderImpl();
constraintSystem.registerTypeVariables(parameters.keySet(), false); constraintSystem.registerTypeVariables(CallHandle.NONE.INSTANCE, parameters.keySet(), false);
constraintSystem.addSubtypeConstraint(withParameters, expected, SPECIAL.position()); constraintSystem.addSubtypeConstraint(withParameters, expected, SPECIAL.position());
return constraintSystem.build().getStatus().isSuccessful(); return constraintSystem.build().getStatus().isSuccessful();
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.diagnostics.rendering.Renderers import org.jetbrains.kotlin.diagnostics.rendering.Renderers
import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.TypeResolver import org.jetbrains.kotlin.resolve.TypeResolver
import org.jetbrains.kotlin.resolve.calls.inference.CallHandle
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintContext import org.jetbrains.kotlin.resolve.calls.inference.ConstraintContext
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.SPECIAL import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.SPECIAL
@@ -81,7 +82,7 @@ abstract public class AbstractConstraintSystemTest() : KotlinLiteFixture() {
val variables = parseVariables(constraintsFileText) val variables = parseVariables(constraintsFileText)
val fixVariables = constraintsFileText.contains("FIX_VARIABLES") val fixVariables = constraintsFileText.contains("FIX_VARIABLES")
val typeParameterDescriptors = variables.map { testDeclarations.getParameterDescriptor(it) } val typeParameterDescriptors = variables.map { testDeclarations.getParameterDescriptor(it) }
val substitutor = builder.registerTypeVariables(typeParameterDescriptors) val substitutor = builder.registerTypeVariables(CallHandle.NONE, typeParameterDescriptors)
val constraints = parseConstraints(constraintsFileText) val constraints = parseConstraints(constraintsFileText)
@@ -20,6 +20,7 @@ package org.jetbrains.kotlin.idea.util
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.inference.CallHandle
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
@@ -115,7 +116,7 @@ class FuzzyType(
} }
val builder = ConstraintSystemBuilderImpl() val builder = ConstraintSystemBuilderImpl()
val typeVariableSubstitutor = builder.registerTypeVariables(freeParameters + otherType.freeParameters) val typeVariableSubstitutor = builder.registerTypeVariables(CallHandle.NONE, freeParameters + otherType.freeParameters)
when (matchKind) { when (matchKind) {
MatchKind.IS_SUBTYPE -> builder.addSubtypeConstraint( MatchKind.IS_SUBTYPE -> builder.addSubtypeConstraint(
@@ -87,7 +87,8 @@ public class AddGenericUpperBoundFix(
typeParameterDescriptor -> typeParameterDescriptor ->
if (ConstraintsUtil.checkUpperBoundIsSatisfied( if (ConstraintsUtil.checkUpperBoundIsSatisfied(
successfulConstraintSystem, typeParameterDescriptor, /* substituteOtherTypeParametersInBound */ true successfulConstraintSystem, typeParameterDescriptor, inferenceData.call,
/* substituteOtherTypeParametersInBound */ true
)) return@factory null )) return@factory null
val upperBound = typeParameterDescriptor.upperBounds.singleOrNull() ?: return@factory null val upperBound = typeParameterDescriptor.upperBounds.singleOrNull() ?: return@factory null