Support inline classes working with collection elements (get/set)
This commit is contained in:
@@ -4050,9 +4050,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
List<KtExpression> indices = expression.getIndexExpressions();
|
||||
FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(REFERENCE_TARGET, expression);
|
||||
assert operationDescriptor != null;
|
||||
boolean isInlineClassType = type != null && InlineClassesUtilsKt.isInlineClassType(type);
|
||||
if (arrayType.getSort() == Type.ARRAY &&
|
||||
indices.size() == 1 &&
|
||||
isInt(operationDescriptor.getValueParameters().get(0).getType())) {
|
||||
isInt(operationDescriptor.getValueParameters().get(0).getType()) &&
|
||||
!isInlineClassType) {
|
||||
assert type != null;
|
||||
Type elementType;
|
||||
if (KotlinBuiltIns.isArray(type)) {
|
||||
@@ -4084,7 +4086,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
);
|
||||
|
||||
Type elementType = isGetter ? callableMethod.getReturnType() : ArrayUtil.getLastElement(argumentTypes);
|
||||
return StackValue.collectionElement(collectionElementReceiver, elementType, resolvedGetCall, resolvedSetCall, this);
|
||||
KotlinType elementKotlinType = isGetter ?
|
||||
operationDescriptor.getReturnType() :
|
||||
CollectionsKt.last(operationDescriptor.getValueParameters()).getType();
|
||||
return StackValue.collectionElement(
|
||||
collectionElementReceiver, elementType, elementKotlinType, resolvedGetCall, resolvedSetCall, this
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.codegen;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import kotlin.Unit;
|
||||
import kotlin.collections.ArraysKt;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -282,11 +283,12 @@ public abstract class StackValue {
|
||||
public static StackValue collectionElement(
|
||||
CollectionElementReceiver collectionElementReceiver,
|
||||
Type type,
|
||||
KotlinType kotlinType,
|
||||
ResolvedCall<FunctionDescriptor> getter,
|
||||
ResolvedCall<FunctionDescriptor> setter,
|
||||
ExpressionCodegen codegen
|
||||
) {
|
||||
return new CollectionElement(collectionElementReceiver, type, getter, setter, codegen);
|
||||
return new CollectionElement(collectionElementReceiver, type, kotlinType, getter, setter, codegen);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -1167,11 +1169,12 @@ public abstract class StackValue {
|
||||
public CollectionElement(
|
||||
@NotNull CollectionElementReceiver collectionElementReceiver,
|
||||
@NotNull Type type,
|
||||
@Nullable KotlinType kotlinType,
|
||||
@Nullable ResolvedCall<FunctionDescriptor> resolvedGetCall,
|
||||
@Nullable ResolvedCall<FunctionDescriptor> resolvedSetCall,
|
||||
@NotNull ExpressionCodegen codegen
|
||||
) {
|
||||
super(type, null, false, false, collectionElementReceiver, true);
|
||||
super(type, kotlinType, false, false, collectionElementReceiver, true);
|
||||
this.resolvedGetCall = resolvedGetCall;
|
||||
this.resolvedSetCall = resolvedSetCall;
|
||||
this.setter = resolvedSetCall == null ? null :
|
||||
@@ -1246,13 +1249,16 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeSelector(@NotNull Type topOfStackType, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) {
|
||||
public void storeSelector(@NotNull Type topOfStackType, @Nullable KotlinType topOfStackKotlinType, @NotNull InstructionAdapter v) {
|
||||
if (setter == null) {
|
||||
throw new UnsupportedOperationException("no setter specified");
|
||||
}
|
||||
|
||||
Type lastParameterType = ArraysKt.last(setter.getParameterTypes());
|
||||
coerce(topOfStackType, lastParameterType, v);
|
||||
KotlinType lastParameterKotlinType =
|
||||
CollectionsKt.last(resolvedSetCall.getResultingDescriptor().getValueParameters()).getType();
|
||||
|
||||
coerce(topOfStackType, topOfStackKotlinType, lastParameterType, lastParameterKotlinType, v);
|
||||
|
||||
getCallGenerator().putValueIfNeeded(lastParameterType, StackValue.onStack(lastParameterType));
|
||||
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
|
||||
inline class UInt(private val value: Int) {
|
||||
fun asInt() = value
|
||||
}
|
||||
|
||||
inline class UIntArray(private val intArray: IntArray) {
|
||||
operator fun get(index: Int): UInt = UInt(intArray[index])
|
||||
|
||||
operator fun set(index: Int, value: UInt) {
|
||||
intArray[index] = value.asInt()
|
||||
}
|
||||
}
|
||||
|
||||
fun UIntArray.swap(i: Int, j: Int) {
|
||||
this[j] = this[i].also { this[i] = this[j] }
|
||||
}
|
||||
|
||||
fun uIntArrayOf(vararg elements: Int) = UIntArray(intArrayOf(*elements))
|
||||
|
||||
fun box(): String {
|
||||
val a = uIntArrayOf(1, 2, 3, 4)
|
||||
a.swap(0, 3)
|
||||
a.swap(1, 2)
|
||||
|
||||
if (a[0].asInt() != 4) return "fail"
|
||||
if (a[1].asInt() != 3) return "fail"
|
||||
if (a[2].asInt() != 2) return "fail"
|
||||
if (a[3].asInt() != 1) return "fail"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
|
||||
inline class UInt(private val value: Int) {
|
||||
fun asInt() = value
|
||||
}
|
||||
|
||||
inline class UIntArray(private val intArray: IntArray) {
|
||||
operator fun get(index: Int): UInt = UInt(intArray[index])
|
||||
|
||||
operator fun set(index: Int, value: UInt) {
|
||||
intArray[index] = value.asInt()
|
||||
}
|
||||
}
|
||||
|
||||
fun UIntArray.swap(i: Int, j: Int) {
|
||||
this[j] = this[i].also { this[i] = this[j] }
|
||||
}
|
||||
|
||||
// 2 INVOKEVIRTUAL UInt.unbox
|
||||
// 1 INVOKESTATIC UInt\$Erased.box
|
||||
|
||||
// 0 intValue
|
||||
// 0 valueOf
|
||||
Generated
+6
@@ -10389,6 +10389,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("boxUnboxInlineClassesWithOperatorsGetSet.kt")
|
||||
public void testBoxUnboxInlineClassesWithOperatorsGetSet() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/boxUnboxInlineClassesWithOperatorsGetSet.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("boxUnboxOfInlineClassForCapturedVars.kt")
|
||||
public void testBoxUnboxOfInlineClassForCapturedVars() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
|
||||
|
||||
+6
@@ -10389,6 +10389,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("boxUnboxInlineClassesWithOperatorsGetSet.kt")
|
||||
public void testBoxUnboxInlineClassesWithOperatorsGetSet() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/boxUnboxInlineClassesWithOperatorsGetSet.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("boxUnboxOfInlineClassForCapturedVars.kt")
|
||||
public void testBoxUnboxOfInlineClassForCapturedVars() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
|
||||
|
||||
@@ -1968,6 +1968,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("uIntArraySwapBoxing.kt")
|
||||
public void testUIntArraySwapBoxing() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/uIntArraySwapBoxing.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("unboxInlineClassAfterElvis.kt")
|
||||
public void testUnboxInlineClassAfterElvis() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/unboxInlineClassAfterElvis.kt");
|
||||
|
||||
+6
@@ -10389,6 +10389,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("boxUnboxInlineClassesWithOperatorsGetSet.kt")
|
||||
public void testBoxUnboxInlineClassesWithOperatorsGetSet() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/boxUnboxInlineClassesWithOperatorsGetSet.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("boxUnboxOfInlineClassForCapturedVars.kt")
|
||||
public void testBoxUnboxOfInlineClassForCapturedVars() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
|
||||
|
||||
+6
@@ -11373,6 +11373,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("boxUnboxInlineClassesWithOperatorsGetSet.kt")
|
||||
public void testBoxUnboxInlineClassesWithOperatorsGetSet() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/boxUnboxInlineClassesWithOperatorsGetSet.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("boxUnboxOfInlineClassForCapturedVars.kt")
|
||||
public void testBoxUnboxOfInlineClassForCapturedVars() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
|
||||
|
||||
Reference in New Issue
Block a user