Refactor synthesized invokes creation in resolution
Instead of verifying that the container of an 'invoke' is a FunctionClassDescriptor instance, make sure that it's a function class checking its FQ name instead (classId + isBuiltinFunctionClass calls). This makes sure that we will create synthesized invokes in a setting where function classes are not FunctionClassDescriptor instances synthesized by the compiler, but ordinary classes from sources or binaries as well, as is going to be the case in kotlin-native
This commit is contained in:
+17
-12
@@ -16,35 +16,40 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.tasks
|
package org.jetbrains.kotlin.resolve.calls.tasks
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor.Kind.Function
|
import org.jetbrains.kotlin.builtins.isBuiltinFunctionClass
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor.Kind.SuspendFunction
|
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden
|
import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
private val BUILTIN_FUNCTIONS = setOf(Function, SuspendFunction)
|
// Creates a descriptor denoting an extension function for a collection of non-extension "invoke"s from function types.
|
||||||
|
// For example, `fun invoke(param: P): R` becomes `fun P.invoke(): R`
|
||||||
fun createSynthesizedInvokes(functions: Collection<FunctionDescriptor>): Collection<FunctionDescriptor> {
|
fun createSynthesizedInvokes(functions: Collection<FunctionDescriptor>): Collection<FunctionDescriptor> {
|
||||||
val result = ArrayList<FunctionDescriptor>(1)
|
val result = ArrayList<FunctionDescriptor>(1)
|
||||||
|
|
||||||
for (invoke in functions) {
|
for (invoke in functions) {
|
||||||
if (invoke !is FunctionInvokeDescriptor || invoke.getValueParameters().isEmpty()) continue
|
if (invoke.name != OperatorNameConventions.INVOKE) continue
|
||||||
|
|
||||||
val synthesized = if ((invoke.getContainingDeclaration() as? FunctionClassDescriptor)?.functionKind in BUILTIN_FUNCTIONS) {
|
// "invoke" must have at least one parameter, which will become the receiver parameter of the synthesized "invoke"
|
||||||
|
if (invoke.valueParameters.isEmpty()) continue
|
||||||
|
|
||||||
|
val containerClassId = (invoke.containingDeclaration as ClassDescriptor).classId
|
||||||
|
val synthesized = if (containerClassId != null && isBuiltinFunctionClass(containerClassId)) {
|
||||||
createSynthesizedFunctionWithFirstParameterAsReceiver(invoke)
|
createSynthesizedFunctionWithFirstParameterAsReceiver(invoke)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val invokeDeclaration = invoke.getOverriddenDescriptors().single()
|
val invokeDeclaration = invoke.overriddenDescriptors.singleOrNull()
|
||||||
|
?: error("No single overridden invoke for $invoke: ${invoke.overriddenDescriptors}")
|
||||||
val synthesizedSuperFun = createSynthesizedFunctionWithFirstParameterAsReceiver(invokeDeclaration)
|
val synthesizedSuperFun = createSynthesizedFunctionWithFirstParameterAsReceiver(invokeDeclaration)
|
||||||
val fakeOverride = synthesizedSuperFun.copy(
|
val fakeOverride = synthesizedSuperFun.copy(
|
||||||
invoke.getContainingDeclaration(),
|
invoke.containingDeclaration,
|
||||||
synthesizedSuperFun.modality,
|
synthesizedSuperFun.modality,
|
||||||
synthesizedSuperFun.visibility,
|
synthesizedSuperFun.visibility,
|
||||||
CallableMemberDescriptor.Kind.FAKE_OVERRIDE,
|
CallableMemberDescriptor.Kind.FAKE_OVERRIDE,
|
||||||
@@ -54,7 +59,7 @@ fun createSynthesizedInvokes(functions: Collection<FunctionDescriptor>): Collect
|
|||||||
fakeOverride
|
fakeOverride
|
||||||
}
|
}
|
||||||
|
|
||||||
result.add(synthesized.substitute(TypeSubstitutor.create(invoke.getDispatchReceiverParameter()!!.type)) ?: continue)
|
result.add(synthesized.substitute(TypeSubstitutor.create(invoke.dispatchReceiverParameter!!.type)) ?: continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
@@ -80,5 +85,5 @@ fun isSynthesizedInvoke(descriptor: DeclarationDescriptor): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return real.kind == CallableMemberDescriptor.Kind.SYNTHESIZED &&
|
return real.kind == CallableMemberDescriptor.Kind.SYNTHESIZED &&
|
||||||
real.containingDeclaration is FunctionClassDescriptor
|
real.containingDeclaration.getFunctionalClassKind() != null
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -150,7 +150,9 @@ private fun ImplicitScopeTower.getExtensionInvokeCandidateDescriptor(
|
|||||||
if (!type.isBuiltinExtensionFunctionalType) return null // todo: missing smart cast?
|
if (!type.isBuiltinExtensionFunctionalType) return null // todo: missing smart cast?
|
||||||
|
|
||||||
val invokeDescriptor = type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, location).single()
|
val invokeDescriptor = type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, location).single()
|
||||||
val synthesizedInvoke = createSynthesizedInvokes(listOf(invokeDescriptor)).single()
|
val synthesizedInvokes = createSynthesizedInvokes(listOf(invokeDescriptor))
|
||||||
|
val synthesizedInvoke = synthesizedInvokes.singleOrNull()
|
||||||
|
?: error("No single synthesized invoke for $invokeDescriptor: $synthesizedInvokes")
|
||||||
|
|
||||||
// here we don't add SynthesizedDescriptor diagnostic because it should has priority as member
|
// here we don't add SynthesizedDescriptor diagnostic because it should has priority as member
|
||||||
return CandidateWithBoundDispatchReceiverImpl(extensionFunctionReceiver, synthesizedInvoke, listOf())
|
return CandidateWithBoundDispatchReceiverImpl(extensionFunctionReceiver, synthesizedInvoke, listOf())
|
||||||
|
|||||||
Reference in New Issue
Block a user