Support non-trivial default argument values in expected functions on JVM
#KT-22818 Fixed
This commit is contained in:
@@ -100,7 +100,8 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isBoxedLocalCapturedInClosure;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression;
|
||||
@@ -2900,7 +2901,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
while (cur != null) {
|
||||
ClassDescriptor thisDescriptor = cur.getThisDescriptor();
|
||||
|
||||
if (!isSuper && thisDescriptor == thisOrOuterClass) {
|
||||
// We use equals on type constructors (instead of reference equality on classes) to support the case where default parameter
|
||||
// values of actual functions loaded from the expected function refer to the expected class.
|
||||
if (!isSuper && thisDescriptor.getTypeConstructor().equals(thisOrOuterClass.getTypeConstructor())) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,9 @@ import com.intellij.openapi.util.Trinity
|
||||
import gnu.trove.TObjectIntHashMap
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import java.util.*
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
class FrameMap : FrameMapBase<DeclarationDescriptor>()
|
||||
open class FrameMap : FrameMapBase<DeclarationDescriptor>()
|
||||
|
||||
open class FrameMapBase<T : Any> {
|
||||
private val myVarIndex = TObjectIntHashMap<T>()
|
||||
@@ -61,7 +60,7 @@ open class FrameMapBase<T : Any> {
|
||||
currentSize -= type.size
|
||||
}
|
||||
|
||||
fun getIndex(descriptor: T): Int {
|
||||
open fun getIndex(descriptor: T): Int {
|
||||
return if (myVarIndex.contains(descriptor)) myVarIndex.get(descriptor) else -1
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.codegen
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
|
||||
|
||||
/**
|
||||
* This [FrameMap] subclass substitutes values declared in the expected declaration with the corresponding value in the actual declaration,
|
||||
* which is needed for the case when expected function declares parameters with default values, which refer to other parameters.
|
||||
*/
|
||||
class FrameMapWithExpectActualSupport(private val module: ModuleDescriptor) : FrameMap() {
|
||||
override fun getIndex(descriptor: DeclarationDescriptor): Int {
|
||||
val tmp = if (descriptor is ParameterDescriptor) findActualParameter(descriptor) ?: descriptor else descriptor
|
||||
return super.getIndex(tmp)
|
||||
}
|
||||
|
||||
private fun findActualParameter(parameter: ParameterDescriptor): ParameterDescriptor? {
|
||||
val container = parameter.containingDeclaration
|
||||
if (container !is CallableMemberDescriptor || !container.isExpect) return null
|
||||
|
||||
// Generation of value parameters is supported by the fact that FunctionCodegen.generateDefaultImplBody substitutes value parameters
|
||||
// of the generated actual function with the parameters of the expected declaration in the first place.
|
||||
// Generation of dispatch receiver parameters (this and outer receiver values) is supported
|
||||
// in ExpressionCodegen.generateThisOrOuterFromContext by comparing classes by type constructor equality.
|
||||
if (parameter !is ReceiverParameterDescriptor || parameter.value !is ExtensionReceiver) return null
|
||||
|
||||
val actual = with(ExpectedActualResolver) {
|
||||
container.findCompatibleActualForExpected(module).firstOrNull()
|
||||
}
|
||||
|
||||
return (actual as? CallableDescriptor)?.extensionReceiverParameter
|
||||
}
|
||||
}
|
||||
@@ -1360,7 +1360,7 @@ public class FunctionCodegen {
|
||||
@NotNull List<ValueParameterDescriptor> valueParameters,
|
||||
boolean isStatic
|
||||
) {
|
||||
FrameMap frameMap = new FrameMap();
|
||||
FrameMap frameMap = new FrameMapWithExpectActualSupport(state.getModule());
|
||||
if (!isStatic) {
|
||||
frameMap.enterTemp(OBJECT_TYPE);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user