Cone conflict resolver: extract JVM equivalent call filtering to a separate class
This commit is contained in:
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedQualifierImpl
|
||||
@@ -19,6 +18,7 @@ import org.jetbrains.kotlin.fir.references.impl.FirResolvedNamedReferenceImpl
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.jvm.ConeEquivalentCallConflictResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.FirAmbiguityError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.FirInapplicableCandidateError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.FirUnresolvedNameError
|
||||
@@ -61,7 +61,11 @@ class FirCallResolver(
|
||||
topLevelScopes = topLevelScopes.asReversed(),
|
||||
localScopes = localScopes.asReversed()
|
||||
)
|
||||
private val conflictResolver = ConeOverloadConflictResolver(TypeSpecificityComparator.NONE, inferenceComponents)
|
||||
|
||||
private val conflictResolver = ConeCompositeConflictResolver(
|
||||
ConeOverloadConflictResolver(TypeSpecificityComparator.NONE, inferenceComponents),
|
||||
ConeEquivalentCallConflictResolver(TypeSpecificityComparator.NONE, inferenceComponents)
|
||||
)
|
||||
|
||||
fun resolveCallAndSelectCandidate(functionCall: FirFunctionCall, expectedTypeRef: FirTypeRef?, file: FirFile): FirFunctionCall {
|
||||
qualifiedResolver.reset()
|
||||
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.arrayElementType
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
|
||||
import org.jetbrains.kotlin.resolve.OverloadabilitySpecificityCallbacks
|
||||
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature
|
||||
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||
import org.jetbrains.kotlin.resolve.calls.results.isSignatureNotLessSpecific
|
||||
|
||||
abstract class AbstractConeCallConflictResolver(
|
||||
private val specificityComparator: TypeSpecificityComparator,
|
||||
protected val inferenceComponents: InferenceComponents
|
||||
) : ConeCallConflictResolver {
|
||||
protected fun Collection<Candidate>.setIfOneOrEmpty(): Set<Candidate>? = when (size) {
|
||||
0 -> emptySet()
|
||||
1 -> setOf(single())
|
||||
else -> null
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if [call1] is definitely more or equally specific [call2],
|
||||
* `false` otherwise.
|
||||
*/
|
||||
protected fun compareCallsByUsedArguments(
|
||||
call1: FlatSignature<Candidate>,
|
||||
call2: FlatSignature<Candidate>,
|
||||
discriminateGenerics: Boolean
|
||||
): Boolean {
|
||||
if (discriminateGenerics) {
|
||||
val isGeneric1 = call1.isGeneric
|
||||
val isGeneric2 = call2.isGeneric
|
||||
// generic loses to non-generic
|
||||
if (isGeneric1 && !isGeneric2) return false
|
||||
if (!isGeneric1 && isGeneric2) return true
|
||||
// two generics are non-comparable
|
||||
if (isGeneric1 && isGeneric2) return false
|
||||
}
|
||||
|
||||
if (!call1.isExpect && call2.isExpect) return true
|
||||
if (call1.isExpect && !call2.isExpect) return false
|
||||
|
||||
return createEmptyConstraintSystem().isSignatureNotLessSpecific(
|
||||
call1,
|
||||
call2,
|
||||
OverloadabilitySpecificityCallbacks,
|
||||
specificityComparator
|
||||
)
|
||||
}
|
||||
|
||||
protected fun createFlatSignature(call: Candidate): FlatSignature<Candidate> {
|
||||
return when (val declaration = call.symbol.fir) {
|
||||
is FirSimpleFunction -> createFlatSignature(call, declaration)
|
||||
is FirConstructor -> createFlatSignature(call, declaration)
|
||||
is FirVariable<*> -> createFlatSignature(call, declaration)
|
||||
is FirClass<*> -> createFlatSignature(call, declaration)
|
||||
else -> error("Not supported: $declaration")
|
||||
}
|
||||
}
|
||||
|
||||
protected fun createFlatSignature(call: Candidate, variable: FirVariable<*>): FlatSignature<Candidate> {
|
||||
return FlatSignature(
|
||||
call,
|
||||
(variable as? FirProperty)?.typeParameters?.map { it.symbol }.orEmpty(),
|
||||
listOfNotNull<ConeKotlinType>(variable.receiverTypeRef?.coneTypeUnsafe()),
|
||||
variable.receiverTypeRef != null,
|
||||
false,
|
||||
0,
|
||||
(variable as? FirProperty)?.isExpect == true,
|
||||
false // TODO
|
||||
)
|
||||
}
|
||||
|
||||
protected fun createFlatSignature(call: Candidate, constructor: FirConstructor): FlatSignature<Candidate> {
|
||||
return FlatSignature(
|
||||
call,
|
||||
constructor.typeParameters.map { it.symbol },
|
||||
computeParameterTypes(call, constructor),
|
||||
//constructor.receiverTypeRef != null,
|
||||
false,
|
||||
constructor.valueParameters.any { it.isVararg },
|
||||
constructor.valueParameters.count { it.defaultValue != null },
|
||||
constructor.isExpect,
|
||||
false // TODO
|
||||
)
|
||||
}
|
||||
|
||||
protected fun createFlatSignature(call: Candidate, function: FirSimpleFunction): FlatSignature<Candidate> {
|
||||
return FlatSignature(
|
||||
call,
|
||||
function.typeParameters.map { it.symbol },
|
||||
computeParameterTypes(call, function),
|
||||
function.receiverTypeRef != null,
|
||||
function.valueParameters.any { it.isVararg },
|
||||
function.valueParameters.count { it.defaultValue != null },
|
||||
function.isExpect,
|
||||
false // TODO
|
||||
)
|
||||
}
|
||||
|
||||
private fun FirValueParameter.argumentType(): ConeKotlinType {
|
||||
val type = returnTypeRef.coneTypeUnsafe<ConeKotlinType>()
|
||||
if (isVararg) return type.arrayElementType(inferenceComponents.session)!!
|
||||
return type
|
||||
}
|
||||
|
||||
private fun computeParameterTypes(
|
||||
call: Candidate,
|
||||
function: FirFunction<*>
|
||||
): List<ConeKotlinType> {
|
||||
return (call.resultingTypeForCallableReference?.typeArguments?.map { it as ConeKotlinType }
|
||||
?: (listOfNotNull(function.receiverTypeRef?.coneTypeUnsafe()) +
|
||||
call.argumentMapping?.map { it.value.argumentType() }.orEmpty()))
|
||||
}
|
||||
|
||||
private fun createFlatSignature(call: Candidate, klass: FirClass<*>): FlatSignature<Candidate> {
|
||||
return FlatSignature(
|
||||
call,
|
||||
(klass as? FirRegularClass)?.typeParameters?.map { it.symbol }.orEmpty(),
|
||||
valueParameterTypes = emptyList(),
|
||||
hasExtensionReceiver = false,
|
||||
hasVarargs = false,
|
||||
numDefaults = 0,
|
||||
isExpect = (klass as? FirRegularClass)?.isExpect == true,
|
||||
isSyntheticMember = false
|
||||
)
|
||||
}
|
||||
|
||||
private fun createEmptyConstraintSystem(): SimpleConstraintSystem {
|
||||
return ConeSimpleConstraintSystemImpl(inferenceComponents.createConstraintSystem())
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
interface ConeCallConflictResolver {
|
||||
fun chooseMaximallySpecificCandidates(
|
||||
candidates: Collection<Candidate>,
|
||||
discriminateGenerics: Boolean
|
||||
): Set<Candidate> = chooseMaximallySpecificCandidates(candidates.toSet(), discriminateGenerics)
|
||||
|
||||
fun chooseMaximallySpecificCandidates(
|
||||
candidates: Set<Candidate>,
|
||||
discriminateGenerics: Boolean
|
||||
): Set<Candidate>
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
class ConeCompositeConflictResolver(
|
||||
private vararg val conflictResolvers: AbstractConeCallConflictResolver
|
||||
) : ConeCallConflictResolver {
|
||||
override fun chooseMaximallySpecificCandidates(candidates: Set<Candidate>, discriminateGenerics: Boolean): Set<Candidate> {
|
||||
if (candidates.size <= 1) return candidates
|
||||
var currentCandidates = candidates
|
||||
var index = 0
|
||||
while (currentCandidates.size > 1 && index < conflictResolvers.size) {
|
||||
val conflictResolver = conflictResolvers[index++]
|
||||
currentCandidates = conflictResolver.chooseMaximallySpecificCandidates(candidates, discriminateGenerics)
|
||||
}
|
||||
return currentCandidates
|
||||
}
|
||||
}
|
||||
+18
-193
@@ -5,19 +5,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.arrayElementType
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
|
||||
import org.jetbrains.kotlin.resolve.OverloadabilitySpecificityCallbacks
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature
|
||||
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||
import org.jetbrains.kotlin.resolve.calls.results.isSignatureNotLessSpecific
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeParameterMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
|
||||
@@ -25,154 +21,21 @@ import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
class ConeOverloadConflictResolver(
|
||||
val specificityComparator: TypeSpecificityComparator,
|
||||
val inferenceComponents: InferenceComponents
|
||||
specificityComparator: TypeSpecificityComparator,
|
||||
inferenceComponents: InferenceComponents
|
||||
) : AbstractConeCallConflictResolver(specificityComparator, inferenceComponents) {
|
||||
|
||||
) {
|
||||
|
||||
fun chooseMaximallySpecificCandidates(
|
||||
candidates: Collection<Candidate>,
|
||||
//checkArgumentsMode: CheckArgumentTypesMode,
|
||||
override fun chooseMaximallySpecificCandidates(
|
||||
candidates: Set<Candidate>,
|
||||
discriminateGenerics: Boolean
|
||||
): Set<Candidate> {
|
||||
candidates.setIfOneOrEmpty()?.let { return it }
|
||||
|
||||
val candidatesSet = filterOutEquivalentCalls(candidates)
|
||||
|
||||
findMaximallySpecificCall(candidatesSet, false)?.let { return setOf(it) }
|
||||
findMaximallySpecificCall(candidates, false)?.let { return setOf(it) }
|
||||
|
||||
if (discriminateGenerics) {
|
||||
findMaximallySpecificCall(candidatesSet, true)?.let { return setOf(it) }
|
||||
findMaximallySpecificCall(candidates, true)?.let { return setOf(it) }
|
||||
}
|
||||
|
||||
return candidatesSet
|
||||
}
|
||||
|
||||
private fun filterOutEquivalentCalls(candidates: Collection<Candidate>): Set<Candidate> {
|
||||
val result = mutableSetOf<Candidate>()
|
||||
outerLoop@ for (myCandidate in candidates) {
|
||||
val me = myCandidate.symbol.fir
|
||||
if (me is FirCallableMemberDeclaration<*> && me.symbol.callableId.className == null) {
|
||||
for (otherCandidate in result) {
|
||||
val other = otherCandidate.symbol.fir
|
||||
if (other is FirCallableMemberDeclaration<*> && other.symbol.callableId.className == null) {
|
||||
if (areEquivalentTopLevelCallables(me, myCandidate, other, otherCandidate)) {
|
||||
continue@outerLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result += myCandidate
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun areEquivalentTopLevelCallables(
|
||||
first: FirCallableMemberDeclaration<*>,
|
||||
firstCandidate: Candidate,
|
||||
second: FirCallableMemberDeclaration<*>,
|
||||
secondCandidate: Candidate
|
||||
): Boolean {
|
||||
if (first.symbol.callableId != second.symbol.callableId) return false
|
||||
if (first.isExpect != second.isExpect) return false
|
||||
if (first.receiverTypeRef?.coneTypeUnsafe<ConeKotlinType>() != second.receiverTypeRef?.coneTypeUnsafe()) {
|
||||
return false
|
||||
}
|
||||
val firstSignature = createFlatSignature(firstCandidate, first)
|
||||
val secondSignature = createFlatSignature(secondCandidate, second)
|
||||
return compareCallsByUsedArguments(firstSignature, secondSignature, false) &&
|
||||
compareCallsByUsedArguments(secondSignature, firstSignature, false)
|
||||
}
|
||||
|
||||
private fun createFlatSignature(call: Candidate): FlatSignature<Candidate> {
|
||||
return when (val declaration = call.symbol.fir) {
|
||||
is FirSimpleFunction -> createFlatSignature(call, declaration)
|
||||
is FirConstructor -> createFlatSignature(call, declaration)
|
||||
is FirVariable<*> -> createFlatSignature(call, declaration)
|
||||
is FirClass<*> -> createFlatSignature(call, declaration)
|
||||
else -> error("Not supported: $declaration")
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFlatSignature(call: Candidate, declaration: FirCallableMemberDeclaration<*>): FlatSignature<Candidate> {
|
||||
return when (declaration) {
|
||||
is FirSimpleFunction -> createFlatSignature(call, declaration)
|
||||
is FirConstructor -> createFlatSignature(call, declaration)
|
||||
is FirVariable<*> -> createFlatSignature(call, declaration as FirVariable<*>)
|
||||
else -> error("Not supported: $declaration")
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFlatSignature(call: Candidate, constructor: FirConstructor): FlatSignature<Candidate> {
|
||||
return FlatSignature(
|
||||
call,
|
||||
constructor.typeParameters.map { it.symbol },
|
||||
computeParameterTypes(call, constructor),
|
||||
//constructor.receiverTypeRef != null,
|
||||
false,
|
||||
constructor.valueParameters.any { it.isVararg },
|
||||
constructor.valueParameters.count { it.defaultValue != null },
|
||||
constructor.isExpect,
|
||||
false // TODO
|
||||
)
|
||||
}
|
||||
|
||||
private fun FirValueParameter.argumentType(): ConeKotlinType {
|
||||
val type = returnTypeRef.coneTypeUnsafe<ConeKotlinType>()
|
||||
if (isVararg) return type.arrayElementType(inferenceComponents.session)!!
|
||||
return type
|
||||
}
|
||||
|
||||
private fun createFlatSignature(call: Candidate, function: FirSimpleFunction): FlatSignature<Candidate> {
|
||||
return FlatSignature(
|
||||
call,
|
||||
function.typeParameters.map { it.symbol },
|
||||
computeParameterTypes(call, function),
|
||||
function.receiverTypeRef != null,
|
||||
function.valueParameters.any { it.isVararg },
|
||||
function.valueParameters.count { it.defaultValue != null },
|
||||
function.isExpect,
|
||||
false // TODO
|
||||
)
|
||||
}
|
||||
|
||||
private fun computeParameterTypes(
|
||||
call: Candidate,
|
||||
function: FirFunction<*>
|
||||
): List<ConeKotlinType> {
|
||||
return (call.resultingTypeForCallableReference?.typeArguments?.map { it as ConeKotlinType }
|
||||
?: (listOfNotNull<ConeKotlinType>(function.receiverTypeRef?.coneTypeUnsafe()) +
|
||||
call.argumentMapping?.map { it.value.argumentType() }.orEmpty()))
|
||||
}
|
||||
|
||||
private fun createFlatSignature(call: Candidate, variable: FirVariable<*>): FlatSignature<Candidate> {
|
||||
return FlatSignature(
|
||||
call,
|
||||
(variable as? FirProperty)?.typeParameters?.map { it.symbol }.orEmpty(),
|
||||
listOfNotNull<ConeKotlinType>(variable.receiverTypeRef?.coneTypeUnsafe()),
|
||||
variable.receiverTypeRef != null,
|
||||
false,
|
||||
0,
|
||||
(variable as? FirProperty)?.isExpect == true,
|
||||
false // TODO
|
||||
)
|
||||
}
|
||||
|
||||
private fun createFlatSignature(call: Candidate, klass: FirClass<*>): FlatSignature<Candidate> {
|
||||
return FlatSignature(
|
||||
call,
|
||||
(klass as? FirRegularClass)?.typeParameters?.map { it.symbol }.orEmpty(),
|
||||
valueParameterTypes = emptyList(),
|
||||
hasExtensionReceiver = false,
|
||||
hasVarargs = false,
|
||||
numDefaults = 0,
|
||||
isExpect = (klass as? FirRegularClass)?.isExpect == true,
|
||||
isSyntheticMember = false
|
||||
)
|
||||
}
|
||||
|
||||
private fun createEmptyConstraintSystem(): SimpleConstraintSystem {
|
||||
return ConeSimpleConstraintSystemImpl(inferenceComponents.createConstraintSystem())
|
||||
return candidates
|
||||
}
|
||||
|
||||
private fun findMaximallySpecificCall(
|
||||
@@ -180,11 +43,9 @@ class ConeOverloadConflictResolver(
|
||||
discriminateGenerics: Boolean//,
|
||||
//isDebuggerContext: Boolean
|
||||
): Candidate? {
|
||||
val filteredCandidates = candidates//uniquifyCandidatesSet(candidates)
|
||||
if (candidates.size <= 1) return candidates.singleOrNull()
|
||||
|
||||
if (filteredCandidates.size <= 1) return filteredCandidates.singleOrNull()
|
||||
|
||||
val conflictingCandidates = filteredCandidates.map { candidateCall ->
|
||||
val conflictingCandidates = candidates.map { candidateCall ->
|
||||
createFlatSignature(candidateCall)
|
||||
}
|
||||
|
||||
@@ -208,7 +69,7 @@ class ConeOverloadConflictResolver(
|
||||
}
|
||||
}
|
||||
if (result == null) return null
|
||||
if (any { it != result && isNotWorse(it, result!!) }) {
|
||||
if (any { it != result && isNotWorse(it, result) }) {
|
||||
return null
|
||||
}
|
||||
return result
|
||||
@@ -235,38 +96,6 @@ class ConeOverloadConflictResolver(
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns `true` if [call1] is definitely more or equally specific [call2],
|
||||
* `false` otherwise.
|
||||
*/
|
||||
private fun compareCallsByUsedArguments(
|
||||
call1: FlatSignature<Candidate>,
|
||||
call2: FlatSignature<Candidate>,
|
||||
discriminateGenerics: Boolean
|
||||
): Boolean {
|
||||
if (discriminateGenerics) {
|
||||
val isGeneric1 = call1.isGeneric
|
||||
val isGeneric2 = call2.isGeneric
|
||||
// generic loses to non-generic
|
||||
if (isGeneric1 && !isGeneric2) return false
|
||||
if (!isGeneric1 && isGeneric2) return true
|
||||
// two generics are non-comparable
|
||||
if (isGeneric1 && isGeneric2) return false
|
||||
}
|
||||
|
||||
if (!call1.isExpect && call2.isExpect) return true
|
||||
if (call1.isExpect && !call2.isExpect) return false
|
||||
|
||||
return createEmptyConstraintSystem().isSignatureNotLessSpecific(
|
||||
call1,
|
||||
call2,
|
||||
OverloadabilitySpecificityCallbacks,
|
||||
specificityComparator
|
||||
)
|
||||
}
|
||||
|
||||
private fun isOfNotLessSpecificShape(
|
||||
call1: FlatSignature<Candidate>,
|
||||
call2: FlatSignature<Candidate>
|
||||
@@ -282,12 +111,6 @@ class ConeOverloadConflictResolver(
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun <C> Collection<C>.setIfOneOrEmpty(): Set<C>? = when (size) {
|
||||
0 -> emptySet()
|
||||
1 -> setOf(single())
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
object NoSubstitutor : TypeSubstitutorMarker
|
||||
@@ -295,19 +118,21 @@ object NoSubstitutor : TypeSubstitutorMarker
|
||||
class ConeSimpleConstraintSystemImpl(val system: NewConstraintSystemImpl) : SimpleConstraintSystem {
|
||||
override fun registerTypeVariables(typeParameters: Collection<TypeParameterMarker>): TypeSubstitutorMarker = with(context) {
|
||||
val csBuilder = system.getBuilder()
|
||||
val substitutionMap = typeParameters.associate {
|
||||
val substitutionMap = typeParameters.associateWith {
|
||||
require(it is FirTypeParameterSymbol)
|
||||
val variable = TypeParameterBasedTypeVariable(it)
|
||||
csBuilder.registerVariable(variable)
|
||||
|
||||
|
||||
it to variable.defaultType
|
||||
variable.defaultType
|
||||
}
|
||||
val substitutor = substitutorByMap(substitutionMap.cast())
|
||||
for (typeParameter in typeParameters) {
|
||||
require(typeParameter is FirTypeParameterSymbol)
|
||||
for (upperBound in typeParameter.fir.bounds) {
|
||||
addSubtypeConstraint(substitutionMap[typeParameter]!!, substitutor.substituteOrSelf(upperBound.coneTypeUnsafe()))
|
||||
addSubtypeConstraint(
|
||||
substitutionMap[typeParameter] ?: error("No ${typeParameter.fir.render()} in substitution map"),
|
||||
substitutor.substituteOrSelf(upperBound.coneTypeUnsafe())
|
||||
)
|
||||
}
|
||||
}
|
||||
return substitutor
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls.jvm
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.AbstractConeCallConflictResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.InferenceComponents
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
|
||||
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature
|
||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||
|
||||
// This conflict resolver filters JVM equivalent top-level functions
|
||||
// like emptyArray() from intrinsics and built-ins
|
||||
class ConeEquivalentCallConflictResolver(
|
||||
specificityComparator: TypeSpecificityComparator,
|
||||
inferenceComponents: InferenceComponents
|
||||
) : AbstractConeCallConflictResolver(specificityComparator, inferenceComponents) {
|
||||
override fun chooseMaximallySpecificCandidates(
|
||||
candidates: Set<Candidate>,
|
||||
discriminateGenerics: Boolean
|
||||
): Set<Candidate> {
|
||||
return filterOutEquivalentCalls(candidates)
|
||||
}
|
||||
|
||||
private fun filterOutEquivalentCalls(candidates: Collection<Candidate>): Set<Candidate> {
|
||||
val result = mutableSetOf<Candidate>()
|
||||
outerLoop@ for (myCandidate in candidates) {
|
||||
val me = myCandidate.symbol.fir
|
||||
if (me is FirCallableMemberDeclaration<*> && me.symbol.callableId.className == null) {
|
||||
for (otherCandidate in result) {
|
||||
val other = otherCandidate.symbol.fir
|
||||
if (other is FirCallableMemberDeclaration<*> && other.symbol.callableId.className == null) {
|
||||
if (areEquivalentTopLevelCallables(me, myCandidate, other, otherCandidate)) {
|
||||
continue@outerLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result += myCandidate
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun areEquivalentTopLevelCallables(
|
||||
first: FirCallableMemberDeclaration<*>,
|
||||
firstCandidate: Candidate,
|
||||
second: FirCallableMemberDeclaration<*>,
|
||||
secondCandidate: Candidate
|
||||
): Boolean {
|
||||
if (first.symbol.callableId != second.symbol.callableId) return false
|
||||
if (first.isExpect != second.isExpect) return false
|
||||
if (first.receiverTypeRef?.coneTypeUnsafe<ConeKotlinType>() != second.receiverTypeRef?.coneTypeUnsafe()) {
|
||||
return false
|
||||
}
|
||||
val firstSignature = createFlatSignature(firstCandidate, first)
|
||||
val secondSignature = createFlatSignature(secondCandidate, second)
|
||||
return compareCallsByUsedArguments(firstSignature, secondSignature, false) &&
|
||||
compareCallsByUsedArguments(secondSignature, firstSignature, false)
|
||||
}
|
||||
|
||||
private fun createFlatSignature(call: Candidate, declaration: FirCallableMemberDeclaration<*>): FlatSignature<Candidate> {
|
||||
return when (declaration) {
|
||||
is FirSimpleFunction -> createFlatSignature(call, declaration)
|
||||
is FirConstructor -> createFlatSignature(call, declaration)
|
||||
is FirVariable<*> -> createFlatSignature(call, declaration as FirVariable<*>)
|
||||
else -> error("Not supported: $declaration")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user