K2/Java: cleanup code around processOverridesForFunctionsWithErasedValueParameter
#KT-64846 In Progress
This commit is contained in:
committed by
Space Team
parent
ac729e28da
commit
c0e0b4d32b
+79
-53
@@ -415,9 +415,7 @@ class JavaClassUseSiteMemberScope(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (processOverridesForFunctionsWithErasedValueParameter(
|
if (processOverridesForFunctionsWithErasedValueParameter(
|
||||||
resultOfIntersectionWithNaturalName.overriddenMembers,
|
|
||||||
requestedName,
|
requestedName,
|
||||||
explicitlyDeclaredFunctionsWithNaturalName,
|
|
||||||
destination,
|
destination,
|
||||||
resultOfIntersectionWithNaturalName,
|
resultOfIntersectionWithNaturalName,
|
||||||
explicitlyDeclaredFunctionWithNaturalName
|
explicitlyDeclaredFunctionWithNaturalName
|
||||||
@@ -444,93 +442,121 @@ class JavaClassUseSiteMemberScope(
|
|||||||
functionsFromSupertypes[requestedName] = resultsOfIntersectionToSaveInCache
|
functionsFromSupertypes[requestedName] = resultsOfIntersectionToSaveInCache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function collects in [destination] an overriding method for base method group [resultOfIntersectionWithNaturalName],
|
||||||
|
* in case base methods should have their value parameters erased in Java,
|
||||||
|
* e.g. Collection.contains(T) in Kotlin is paired with Collection.contains(Object) in Java.
|
||||||
|
*
|
||||||
|
* Given we have a Java class [klass] and some its method(s) name [name]
|
||||||
|
* with base method group [resultOfIntersectionWithNaturalName] and (maybe)
|
||||||
|
* explicitly declared [explicitlyDeclaredFunctionWithNaturalName],
|
||||||
|
* this function builds a synthetic override for [resultOfIntersectionWithNaturalName] in the Java class,
|
||||||
|
* binds it with this intersection result using the override relation,
|
||||||
|
* and collects it as a matching method with this name.
|
||||||
|
*
|
||||||
|
* Important: all explicitly declared functions are already collected at this point, there is no reason to collect them once more!
|
||||||
|
*
|
||||||
|
* @param name a given method name
|
||||||
|
* @param destination used to collect base functions for [explicitlyDeclaredFunctionWithNaturalName] with erased value parameters in Java
|
||||||
|
* @param resultOfIntersectionWithNaturalName one group of intersected base methods, each "overridden member" inside is a pair of (base method, its scope)
|
||||||
|
* @param explicitlyDeclaredFunctionWithNaturalName the function in the Java class [klass] with the name [name], which overrides [resultOfIntersectionWithNaturalName] (if any)
|
||||||
|
* @return true if we collected something, false otherwise
|
||||||
|
* @see [SpecialGenericSignatures.GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP] and
|
||||||
|
* [SpecialGenericSignatures.ERASED_COLLECTION_PARAMETER_NAME_AND_SIGNATURES]
|
||||||
|
*/
|
||||||
private fun processOverridesForFunctionsWithErasedValueParameter(
|
private fun processOverridesForFunctionsWithErasedValueParameter(
|
||||||
overriddenMembers: List<MemberWithBaseScope<FirNamedFunctionSymbol>>,
|
name: Name,
|
||||||
naturalName: Name,
|
|
||||||
explicitlyDeclaredFunctionsWithNaturalName: Collection<FirNamedFunctionSymbol>,
|
|
||||||
destination: MutableCollection<FirNamedFunctionSymbol>,
|
destination: MutableCollection<FirNamedFunctionSymbol>,
|
||||||
resultOfIntersectionWithNaturalName: ResultOfIntersection<FirNamedFunctionSymbol>,
|
resultOfIntersectionWithNaturalName: ResultOfIntersection<FirNamedFunctionSymbol>,
|
||||||
explicitlyDeclaredFunctionWithNaturalName: FirNamedFunctionSymbol?
|
explicitlyDeclaredFunctionWithNaturalName: FirNamedFunctionSymbol?
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val overriddenMemberWithErasedValueParameters = overriddenMembers.firstOrNull {
|
val membersFromSupertypesWithScopes = resultOfIntersectionWithNaturalName.overriddenMembers
|
||||||
BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(it) != null
|
// E.g. contains(String) or contains(T)
|
||||||
|
val memberFromSupertypeWithValueParametersToBeErased = membersFromSupertypesWithScopes.firstOrNull { (member, scope) ->
|
||||||
|
BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(member, scope) != null
|
||||||
}?.member ?: return false
|
}?.member ?: return false
|
||||||
|
|
||||||
val unwrappedSubstitutionOverride = overriddenMemberWithErasedValueParameters.fir.originalForSubstitutionOverride
|
// E.g. contains(T)
|
||||||
?: overriddenMemberWithErasedValueParameters.fir
|
val unwrappedMemberFromSupertypeWithValueParametersToBeErased =
|
||||||
|
memberFromSupertypeWithValueParametersToBeErased.fir.originalForSubstitutionOverride
|
||||||
|
?: memberFromSupertypeWithValueParametersToBeErased.fir
|
||||||
|
|
||||||
val functionFromSupertypeWithErasedParameterType = unwrappedSubstitutionOverride
|
val functionFromSupertypeWithValueParametersToBeErased = unwrappedMemberFromSupertypeWithValueParametersToBeErased
|
||||||
.initialSignatureAttr
|
.initialSignatureAttr
|
||||||
?.symbol as? FirNamedFunctionSymbol
|
?.symbol as? FirNamedFunctionSymbol
|
||||||
?: unwrappedSubstitutionOverride.symbol
|
?: unwrappedMemberFromSupertypeWithValueParametersToBeErased.symbol
|
||||||
val originalDeclaredFunction = declaredMemberScope.getFunctions(naturalName).firstOrNull {
|
|
||||||
it.hasSameJvmDescriptor(functionFromSupertypeWithErasedParameterType) && it.hasErasedParameters() &&
|
// E.g. contains(Object) from Java
|
||||||
javaOverrideChecker.doesReturnTypesHaveSameKind(functionFromSupertypeWithErasedParameterType.fir, it.fir)
|
val explicitlyDeclaredFunctionWithErasedValueParameters =
|
||||||
} ?: return false
|
declaredMemberScope.getFunctions(name).firstOrNull { declaredFunction ->
|
||||||
/*
|
declaredFunction.hasSameJvmDescriptor(functionFromSupertypeWithValueParametersToBeErased) &&
|
||||||
* See the comment to shouldBeVisibleAsOverrideOfBuiltInWithErasedValueParameters function
|
declaredFunction.hasErasedParameters() &&
|
||||||
|
javaOverrideChecker.doesReturnTypesHaveSameKind(
|
||||||
|
functionFromSupertypeWithValueParametersToBeErased.fir,
|
||||||
|
declaredFunction.fir
|
||||||
|
)
|
||||||
|
} ?: return false // No declared functions with erased parameters => no additional processing needed
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See the comment to [shouldBeVisibleAsOverrideOfBuiltInWithErasedValueParameters] function
|
||||||
* It explains why we should check value parameters for `Any` type
|
* It explains why we should check value parameters for `Any` type
|
||||||
*/
|
*/
|
||||||
var allParametersAreAny = true
|
var allParametersAreAny = true
|
||||||
val renamedDeclaredFunction = buildJavaMethodCopy(originalDeclaredFunction.fir as FirJavaMethod) {
|
// It's a copy like contains(T) or contains(String) in Java, we perform "unerasing" here
|
||||||
name = naturalName
|
val declaredFunctionCopyWithParameterTypesFromSupertype = buildJavaMethodCopy(
|
||||||
symbol = FirNamedFunctionSymbol(originalDeclaredFunction.callableId)
|
explicitlyDeclaredFunctionWithErasedValueParameters.fir as FirJavaMethod
|
||||||
|
) {
|
||||||
|
this.name = name
|
||||||
|
symbol = FirNamedFunctionSymbol(explicitlyDeclaredFunctionWithErasedValueParameters.callableId)
|
||||||
this.valueParameters.clear()
|
this.valueParameters.clear()
|
||||||
originalDeclaredFunction.fir.valueParameters.zip(overriddenMemberWithErasedValueParameters.fir.valueParameters)
|
explicitlyDeclaredFunctionWithErasedValueParameters.fir.valueParameters.zip(
|
||||||
.mapTo(this.valueParameters) { (overrideParameter, parameterFromSupertype) ->
|
memberFromSupertypeWithValueParametersToBeErased.fir.valueParameters
|
||||||
if (!parameterFromSupertype.returnTypeRef.coneType.lowerBoundIfFlexible().isAny) {
|
).mapTo(this.valueParameters) { (overrideParameter, parameterFromSupertype) ->
|
||||||
allParametersAreAny = false
|
if (!parameterFromSupertype.returnTypeRef.coneType.lowerBoundIfFlexible().isAny) {
|
||||||
}
|
allParametersAreAny = false
|
||||||
buildJavaValueParameterCopy(overrideParameter) {
|
|
||||||
this@buildJavaValueParameterCopy.returnTypeRef = parameterFromSupertype.returnTypeRef
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
buildJavaValueParameterCopy(overrideParameter) {
|
||||||
|
this@buildJavaValueParameterCopy.returnTypeRef = parameterFromSupertype.returnTypeRef
|
||||||
|
}
|
||||||
|
}
|
||||||
}.apply {
|
}.apply {
|
||||||
initialSignatureAttr = originalDeclaredFunction.fir
|
initialSignatureAttr = explicitlyDeclaredFunctionWithErasedValueParameters.fir
|
||||||
}.symbol
|
}.symbol
|
||||||
|
|
||||||
if (allParametersAreAny) {
|
if (allParametersAreAny) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val accidentalOverrideWithDeclaredFunction = explicitlyDeclaredFunctionsWithNaturalName.find {
|
// E.g. contains(String) from Java, if any
|
||||||
|
val accidentalOverrideWithDeclaredFunction = explicitlyDeclaredFunctionWithNaturalName?.takeIf {
|
||||||
overrideChecker.isOverriddenFunction(
|
overrideChecker.isOverriddenFunction(
|
||||||
renamedDeclaredFunction,
|
declaredFunctionCopyWithParameterTypesFromSupertype,
|
||||||
it
|
it
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (accidentalOverrideWithDeclaredFunction == null) {
|
val symbolToBeCollected = if (accidentalOverrideWithDeclaredFunction == null) {
|
||||||
destination += renamedDeclaredFunction
|
// Collect synthetic function which is an "unerased" copy of declared one with erased parameters
|
||||||
directOverriddenFunctions[renamedDeclaredFunction] = listOf(resultOfIntersectionWithNaturalName)
|
declaredFunctionCopyWithParameterTypesFromSupertype
|
||||||
for (overriddenMember in overriddenMembers) {
|
|
||||||
overrideByBase[overriddenMember.member] = renamedDeclaredFunction
|
|
||||||
}
|
|
||||||
if (explicitlyDeclaredFunctionWithNaturalName != null) {
|
|
||||||
destination += explicitlyDeclaredFunctionWithNaturalName
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
} else {
|
} else {
|
||||||
val newSymbol = FirNamedFunctionSymbol(accidentalOverrideWithDeclaredFunction.callableId)
|
val newSymbol = FirNamedFunctionSymbol(accidentalOverrideWithDeclaredFunction.callableId)
|
||||||
val original = accidentalOverrideWithDeclaredFunction.fir
|
val original = accidentalOverrideWithDeclaredFunction.fir
|
||||||
val hiddenFunction = buildSimpleFunctionCopy(original) {
|
val accidentalOverrideWithDeclaredFunctionHiddenCopy = buildSimpleFunctionCopy(original) {
|
||||||
name = naturalName
|
this.name = name
|
||||||
symbol = newSymbol
|
symbol = newSymbol
|
||||||
dispatchReceiverType = klass.defaultType()
|
dispatchReceiverType = klass.defaultType()
|
||||||
}.apply {
|
}.apply {
|
||||||
initialSignatureAttr = original
|
initialSignatureAttr = original
|
||||||
isHiddenToOvercomeSignatureClash = true
|
isHiddenToOvercomeSignatureClash = true
|
||||||
}
|
}
|
||||||
destination += hiddenFunction.symbol
|
// Collect synthetic function which is a hidden copy of declared one with unerased parameters
|
||||||
directOverriddenFunctions[hiddenFunction.symbol] = listOf(resultOfIntersectionWithNaturalName)
|
accidentalOverrideWithDeclaredFunctionHiddenCopy.symbol
|
||||||
for (overriddenMember in overriddenMembers) {
|
|
||||||
overrideByBase[overriddenMember.member] = hiddenFunction.symbol
|
|
||||||
}
|
|
||||||
if (explicitlyDeclaredFunctionWithNaturalName != null) {
|
|
||||||
destination += explicitlyDeclaredFunctionWithNaturalName
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
destination += symbolToBeCollected
|
||||||
|
directOverriddenFunctions[symbolToBeCollected] = listOf(resultOfIntersectionWithNaturalName)
|
||||||
|
for ((member, _) in membersFromSupertypesWithScopes) {
|
||||||
|
overrideByBase[member] = symbolToBeCollected
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirNamedFunctionSymbol.hasSameJvmDescriptor(
|
private fun FirNamedFunctionSymbol.hasSameJvmDescriptor(
|
||||||
|
|||||||
@@ -60,13 +60,6 @@ object BuiltinMethodsWithSpecialGenericSignature {
|
|||||||
private val FirNamedFunctionSymbol.hasErasedValueParametersInJava: Boolean
|
private val FirNamedFunctionSymbol.hasErasedValueParametersInJava: Boolean
|
||||||
get() = fir.computeJvmSignature() in ERASED_VALUE_PARAMETERS_SIGNATURES
|
get() = fir.computeJvmSignature() in ERASED_VALUE_PARAMETERS_SIGNATURES
|
||||||
|
|
||||||
fun getOverriddenBuiltinFunctionWithErasedValueParametersInJava(
|
|
||||||
memberWithBaseScope: MemberWithBaseScope<FirNamedFunctionSymbol>
|
|
||||||
): FirNamedFunctionSymbol? {
|
|
||||||
return getOverriddenBuiltinFunctionWithErasedValueParametersInJava(memberWithBaseScope.member, memberWithBaseScope.baseScope)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getOverriddenBuiltinFunctionWithErasedValueParametersInJava(
|
fun getOverriddenBuiltinFunctionWithErasedValueParametersInJava(
|
||||||
functionSymbol: FirNamedFunctionSymbol,
|
functionSymbol: FirNamedFunctionSymbol,
|
||||||
|
|||||||
+2
-1
@@ -45,7 +45,8 @@ class FirTypeIntersectionScopeContext(
|
|||||||
|
|
||||||
sealed class ResultOfIntersection<D : FirCallableSymbol<*>>(
|
sealed class ResultOfIntersection<D : FirCallableSymbol<*>>(
|
||||||
val overriddenMembers: List<MemberWithBaseScope<D>>,
|
val overriddenMembers: List<MemberWithBaseScope<D>>,
|
||||||
val containingScope: FirTypeScope?
|
// This member is for debug-purposes only
|
||||||
|
private val containingScope: FirTypeScope?
|
||||||
) {
|
) {
|
||||||
abstract val chosenSymbol: D
|
abstract val chosenSymbol: D
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user