Process default arguments in array convention calls
#KT-16520 Fixed
This commit is contained in:
@@ -15,7 +15,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType;
|
||||
import org.jetbrains.kotlin.builtins.UnsignedTypes;
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||
@@ -47,6 +46,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -1526,29 +1526,66 @@ public abstract class StackValue {
|
||||
|
||||
coerce(topOfStackType, topOfStackKotlinType, lastParameterType, lastParameterKotlinType, v);
|
||||
|
||||
getCallGenerator().putValueIfNeeded(
|
||||
CallGenerator callGenerator = getCallGenerator();
|
||||
callGenerator.putValueIfNeeded(
|
||||
new JvmKotlinType(lastParameterType, lastParameterKotlinType),
|
||||
StackValue.onStack(lastParameterType, lastParameterKotlinType)
|
||||
);
|
||||
|
||||
//Convention setter couldn't have default parameters, just getter can have it at last positions
|
||||
//We should remove default parameters of getter from stack*/
|
||||
//Note that it works only for non-inline case
|
||||
CollectionElementReceiver collectionElementReceiver = (CollectionElementReceiver) receiver;
|
||||
boolean callDefault = false;
|
||||
if (collectionElementReceiver.isGetter) {
|
||||
List<ResolvedValueArgument> arguments = collectionElementReceiver.valueArguments;
|
||||
List<Type> types = getter.getValueParameterTypes();
|
||||
for (int i = arguments.size() - 1; i >= 0; i--) {
|
||||
ResolvedValueArgument argument = arguments.get(i);
|
||||
if (argument instanceof DefaultValueArgument) {
|
||||
Type defaultType = types.get(i);
|
||||
AsmUtil.swap(v, lastParameterType, defaultType);
|
||||
AsmUtil.pop(v, defaultType);
|
||||
//Convention setter/getter could have default parameters at the end of parameter list (in case of setter before last parameter)
|
||||
//We should remove default parameters of getter from stack if they don't match setter ones and regenerate mask for setter
|
||||
//Note that it works only for non-inline cases
|
||||
|
||||
//TODO: try to don't generate defaults at all in CollectionElementReceiver
|
||||
|
||||
List<ResolvedValueArgument> getterArguments = new ArrayList(collectionElementReceiver.valueArguments);
|
||||
List<ResolvedValueArgument> getterDefaults = CollectionsKt.takeLastWhile(getterArguments,
|
||||
argument -> argument instanceof DefaultValueArgument);
|
||||
|
||||
List<ResolvedValueArgument> setterArguments = resolvedSetCall.getValueArgumentsByIndex();
|
||||
List<ResolvedValueArgument> setterDefaults = CollectionsKt.takeLastWhile(CollectionsKt.dropLast(setterArguments, 1),
|
||||
argument -> argument instanceof DefaultValueArgument);
|
||||
|
||||
if (!getterDefaults.isEmpty() || !setterDefaults.isEmpty()) {
|
||||
Local rhsValue = StackValue.local(codegen.myFrameMap.enterTemp(lastParameterType), lastParameterType);
|
||||
rhsValue.store(StackValue.onStack(type), v);
|
||||
|
||||
List<Type> types = getter.getValueParameterTypes();
|
||||
for (int i = collectionElementReceiver.valueArguments.size() - 1; i >= 0; i--) {
|
||||
ResolvedValueArgument argument = collectionElementReceiver.valueArguments.get(i);
|
||||
if (argument instanceof DefaultValueArgument) {
|
||||
AsmUtil.pop(v, types.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
DefaultCallArgs defaultArgs = new DefaultCallArgs(
|
||||
CodegenUtilKt.unwrapFrontendVersion(resolvedSetCall.getResultingDescriptor()).getValueParameters().size());
|
||||
if (!setterDefaults.isEmpty()) {
|
||||
ArgumentGenerator setterArgumentGenerator = new CallBasedArgumentGenerator(
|
||||
codegen,
|
||||
callGenerator,
|
||||
resolvedSetCall.getResultingDescriptor().getValueParameters(), setter.getValueParameterTypes()
|
||||
);
|
||||
|
||||
int defaultIndex = CollectionsKt.getLastIndex(setterArguments) - 1/*rhs value*/ - setterDefaults.size();
|
||||
for (ResolvedValueArgument aDefault : setterDefaults) {
|
||||
defaultArgs.mark(++defaultIndex);
|
||||
setterArgumentGenerator.generateDefault(defaultIndex, (DefaultValueArgument)aDefault);
|
||||
}
|
||||
callDefault = true;
|
||||
}
|
||||
rhsValue.put(v);
|
||||
codegen.myFrameMap.leaveTemp(lastParameterType);
|
||||
defaultArgs.generateOnStackIfNeeded(callGenerator, false);
|
||||
}
|
||||
} else {
|
||||
callDefault = genDefaultMaskIfPresent(callGenerator);
|
||||
}
|
||||
|
||||
getCallGenerator().genCall(setter, resolvedSetCall, false, codegen);
|
||||
callGenerator.genCall(setter, resolvedSetCall, callDefault, codegen);
|
||||
Type returnType = setter.getReturnType();
|
||||
if (returnType != Type.VOID_TYPE) {
|
||||
pop(v, returnType);
|
||||
|
||||
Generated
+15
@@ -8846,6 +8846,16 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/incWithDefaultInGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("incWithDefaults.kt")
|
||||
public void testIncWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/incWithDefaults.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt16520.kt")
|
||||
public void testKt16520() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/kt16520.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt9140.kt")
|
||||
public void testKt9140() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/kt9140.kt");
|
||||
@@ -8855,6 +8865,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
public void testPlusAssignWithDefaultInGetter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/plusAssignWithDefaultInGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("plusAssignWithDefaults.kt")
|
||||
public void testPlusAssignWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/plusAssignWithDefaults.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/defaultArguments/function")
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
var inc: String = ""
|
||||
|
||||
class X {
|
||||
var result: String = "fail"
|
||||
|
||||
operator fun get(name: String, type: Int = 100) = name + type
|
||||
|
||||
operator fun set(name: String, defaultParam: String = "_default_", value: String) {
|
||||
result = name + defaultParam + value;
|
||||
}
|
||||
}
|
||||
|
||||
class Y {
|
||||
var result: String = "fail"
|
||||
|
||||
operator fun get(name: String, type: String = "_default2_", type2: String = "_default1_") = name + type + type2
|
||||
|
||||
operator fun set(name: String, defaultParam: String = "_default_in_setter_", value: String) {
|
||||
result = name + defaultParam + value;
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var x = X()
|
||||
x["index"] += "OK"
|
||||
if (x.result != "index_default_index100OK") return "fail 1: ${x.result}"
|
||||
|
||||
var y = Y()
|
||||
y["index"] += "OK"
|
||||
if (y.result != "index_default_in_setter_index_default2__default1_OK") return "fail 2: ${y.result}"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
var result = "fail"
|
||||
|
||||
class A {
|
||||
operator fun set(
|
||||
i1: Int,
|
||||
i2: Int = 1,
|
||||
v: String
|
||||
) {
|
||||
result = "" + i1 + i2 + v
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
A()[1] = "OK"
|
||||
return if (result != "11OK") "fail: $result" else "OK"
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
var inc: String = ""
|
||||
|
||||
class X {
|
||||
var result: String = "fail"
|
||||
|
||||
operator fun get(name: String, type: Int = 100) = name + type
|
||||
|
||||
operator fun set(name: String, defaultParam: String = "_default_", value: String) {
|
||||
result = name + defaultParam + value;
|
||||
}
|
||||
}
|
||||
|
||||
class Y {
|
||||
var result: String = "fail"
|
||||
|
||||
operator fun get(name: String, type: String = "_default_", type2: Int = 2) = name + type + type2
|
||||
|
||||
operator fun set(name: String, defaultParam: String = "_default_in_setter_", value: String) {
|
||||
result = name + defaultParam + value;
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var x = X()
|
||||
x["index"] += "OK"
|
||||
if (x.result != "index_default_index100OK") return "fail 1: ${x.result}"
|
||||
|
||||
var y = Y()
|
||||
y["index"] += "OK"
|
||||
if (y.result != "index_default_in_setter_index_default_2OK") return "fail 2: ${y.result}"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+15
@@ -10061,6 +10061,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/incWithDefaultInGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("incWithDefaults.kt")
|
||||
public void testIncWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/incWithDefaults.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt16520.kt")
|
||||
public void testKt16520() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/kt16520.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt9140.kt")
|
||||
public void testKt9140() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/kt9140.kt");
|
||||
@@ -10070,6 +10080,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
public void testPlusAssignWithDefaultInGetter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/plusAssignWithDefaultInGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("plusAssignWithDefaults.kt")
|
||||
public void testPlusAssignWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/plusAssignWithDefaults.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/defaultArguments/function")
|
||||
|
||||
+15
@@ -10061,6 +10061,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/incWithDefaultInGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("incWithDefaults.kt")
|
||||
public void testIncWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/incWithDefaults.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt16520.kt")
|
||||
public void testKt16520() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/kt16520.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt9140.kt")
|
||||
public void testKt9140() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/kt9140.kt");
|
||||
@@ -10070,6 +10080,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
public void testPlusAssignWithDefaultInGetter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/plusAssignWithDefaultInGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("plusAssignWithDefaults.kt")
|
||||
public void testPlusAssignWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/plusAssignWithDefaults.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/defaultArguments/function")
|
||||
|
||||
+15
@@ -8846,6 +8846,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/incWithDefaultInGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("incWithDefaults.kt")
|
||||
public void testIncWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/incWithDefaults.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt16520.kt")
|
||||
public void testKt16520() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/kt16520.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt9140.kt")
|
||||
public void testKt9140() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/kt9140.kt");
|
||||
@@ -8855,6 +8865,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
public void testPlusAssignWithDefaultInGetter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/plusAssignWithDefaultInGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("plusAssignWithDefaults.kt")
|
||||
public void testPlusAssignWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/plusAssignWithDefaults.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/defaultArguments/function")
|
||||
|
||||
Generated
+15
@@ -7511,6 +7511,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/incWithDefaultInGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("incWithDefaults.kt")
|
||||
public void testIncWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/incWithDefaults.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt16520.kt")
|
||||
public void testKt16520() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/kt16520.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt9140.kt")
|
||||
public void testKt9140() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/kt9140.kt");
|
||||
@@ -7520,6 +7530,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
public void testPlusAssignWithDefaultInGetter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/plusAssignWithDefaultInGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("plusAssignWithDefaults.kt")
|
||||
public void testPlusAssignWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/plusAssignWithDefaults.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/defaultArguments/function")
|
||||
|
||||
+15
@@ -7511,6 +7511,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/incWithDefaultInGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("incWithDefaults.kt")
|
||||
public void testIncWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/incWithDefaults.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt16520.kt")
|
||||
public void testKt16520() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/kt16520.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt9140.kt")
|
||||
public void testKt9140() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/kt9140.kt");
|
||||
@@ -7520,6 +7530,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
public void testPlusAssignWithDefaultInGetter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/plusAssignWithDefaultInGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("plusAssignWithDefaults.kt")
|
||||
public void testPlusAssignWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/convention/plusAssignWithDefaults.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/defaultArguments/function")
|
||||
|
||||
Reference in New Issue
Block a user