Support 'call' for references to inline class members
This includes overriding and non-overriding functions and properties. #KT-26748
This commit is contained in:
@@ -391,8 +391,8 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||
|
||||
if (container instanceof ClassDescriptor) {
|
||||
// TODO: getDefaultType() here is wrong and won't work for arrays
|
||||
putJavaLangClassInstance(iv, state.getTypeMapper().mapType(((ClassDescriptor) container).getDefaultType()));
|
||||
// TODO: would it work for arrays?
|
||||
putJavaLangClassInstance(iv, state.getTypeMapper().mapClass((ClassDescriptor) container));
|
||||
}
|
||||
else if (container instanceof PackageFragmentDescriptor) {
|
||||
iv.aconst(state.getTypeMapper().mapOwner(descriptor));
|
||||
|
||||
@@ -28,12 +28,9 @@ import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.PropertyImportedFromObject
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.isUnderlyingPropertyOfInlineClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
@@ -252,7 +249,11 @@ class PropertyReferenceCodegen(
|
||||
else -> error("Unsupported callable reference: $callable")
|
||||
}
|
||||
val declaration = DescriptorUtils.unwrapFakeOverride(accessor).original
|
||||
val method = state.typeMapper.mapAsmMethod(declaration)
|
||||
val method =
|
||||
if (callable.containingDeclaration.isInlineClass())
|
||||
state.typeMapper.mapSignatureForInlineErasedClassSkipGeneric(declaration).asmMethod
|
||||
else
|
||||
state.typeMapper.mapAsmMethod(declaration)
|
||||
return method.name + method.descriptor
|
||||
}
|
||||
|
||||
|
||||
Vendored
+35
@@ -0,0 +1,35 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
|
||||
// WITH_REFLECT
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
inline class Z(val x: Int) {
|
||||
fun test(a: String, b: S) = "$x$a${b.x}"
|
||||
}
|
||||
|
||||
inline class L(val x: Long) {
|
||||
fun test(a: String, b: S) = "$x$a${b.x}"
|
||||
}
|
||||
|
||||
inline class S(val x: String) {
|
||||
fun test(a: String, b: S) = "$x$a${b.x}"
|
||||
}
|
||||
|
||||
inline class A(val x: Any) {
|
||||
fun test(a: String, b: S) = "$x$a${b.x}"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertEquals("42-+", Z::test.call(Z(42), "-", S("+")))
|
||||
assertEquals("42-+", Z(42)::test.call("-", S("+")))
|
||||
|
||||
assertEquals("42-+", L::test.call(L(42L), "-", S("+")))
|
||||
assertEquals("42-+", L(42L)::test.call("-", S("+")))
|
||||
|
||||
assertEquals("42-+", S::test.call(S("42"), "-", S("+")))
|
||||
assertEquals("42-+", S("42")::test.call("-", S("+")))
|
||||
|
||||
assertEquals("42-+", A::test.call(A("42"), "-", S("+")))
|
||||
assertEquals("42-+", A("42")::test.call("-", S("+")))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+81
@@ -0,0 +1,81 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
|
||||
// WITH_REFLECT
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
var global = S("")
|
||||
|
||||
inline class Z(val x: Int) {
|
||||
var test: S
|
||||
get() = S("${global.x}$x")
|
||||
set(value) {
|
||||
global = S("${value.x}$x")
|
||||
}
|
||||
}
|
||||
|
||||
inline class L(val x: Long) {
|
||||
var test: S
|
||||
get() = S("${global.x}$x")
|
||||
set(value) {
|
||||
global = S("${value.x}$x")
|
||||
}
|
||||
}
|
||||
|
||||
inline class S(val x: String) {
|
||||
var test: S
|
||||
get() = S("${global.x}$x")
|
||||
set(value) {
|
||||
global = S("${value.x}$x")
|
||||
}
|
||||
}
|
||||
|
||||
inline class A(val x: Any) {
|
||||
var test: S
|
||||
get() = S("${global.x}$x")
|
||||
set(value) {
|
||||
global = S("${value.x}$x")
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
global = S("")
|
||||
assertEquals(S("42"), Z::test.call(Z(42)))
|
||||
assertEquals(S("42"), Z(42)::test.call())
|
||||
assertEquals(S("42"), Z::test.getter.call(Z(42)))
|
||||
assertEquals(S("42"), Z(42)::test.getter.call())
|
||||
Z::test.setter.call(Z(42), S("Z-"))
|
||||
assertEquals(S("Z-42"), global)
|
||||
Z(42)::test.setter.call(S("Z+"))
|
||||
assertEquals(S("Z+42"), global)
|
||||
|
||||
global = S("")
|
||||
assertEquals(S("42"), L::test.call(L(42L)))
|
||||
assertEquals(S("42"), L(42L)::test.call())
|
||||
assertEquals(S("42"), L::test.getter.call(L(42L)))
|
||||
assertEquals(S("42"), L(42L)::test.getter.call())
|
||||
L::test.setter.call(L(42L), S("L-"))
|
||||
assertEquals(S("L-42"), global)
|
||||
L(42L)::test.setter.call(S("L+"))
|
||||
assertEquals(S("L+42"), global)
|
||||
|
||||
global = S("")
|
||||
assertEquals(S("42"), S::test.call(S("42")))
|
||||
assertEquals(S("42"), S("42")::test.call())
|
||||
assertEquals(S("42"), S::test.getter.call(S("42")))
|
||||
assertEquals(S("42"), S("42")::test.getter.call())
|
||||
S::test.setter.call(S("42"), S("S-"))
|
||||
assertEquals(S("S-42"), global)
|
||||
S("42")::test.setter.call(S("S+"))
|
||||
assertEquals(S("S+42"), global)
|
||||
|
||||
global = S("")
|
||||
assertEquals(S("42"), A::test.call(A(42)))
|
||||
assertEquals(S("42"), A(42)::test.call())
|
||||
assertEquals(S("42"), A::test.getter.call(A(42)))
|
||||
assertEquals(S("42"), A(42)::test.getter.call())
|
||||
A::test.setter.call(A(42), S("A-"))
|
||||
assertEquals(S("A-42"), global)
|
||||
A(42)::test.setter.call(S("A+"))
|
||||
assertEquals(S("A+42"), global)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
|
||||
// WITH_REFLECT
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
interface ITest {
|
||||
fun test(a: String, b: S): String
|
||||
}
|
||||
|
||||
inline class Z(val x: Int) : ITest {
|
||||
override fun test(a: String, b: S) = "$x$a${b.x}"
|
||||
}
|
||||
|
||||
inline class L(val x: Long) : ITest {
|
||||
override fun test(a: String, b: S) = "$x$a${b.x}"
|
||||
}
|
||||
|
||||
inline class S(val x: String) : ITest {
|
||||
override fun test(a: String, b: S) = "$x$a${b.x}"
|
||||
}
|
||||
|
||||
inline class A(val x: Any) : ITest {
|
||||
override fun test(a: String, b: S) = "$x$a${b.x}"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertEquals("42-+", Z::test.call(Z(42), "-", S("+")))
|
||||
assertEquals("42-+", Z(42)::test.call("-", S("+")))
|
||||
|
||||
assertEquals("42-+", L::test.call(L(42L), "-", S("+")))
|
||||
assertEquals("42-+", L(42L)::test.call("-", S("+")))
|
||||
|
||||
assertEquals("42-+", S::test.call(S("42"), "-", S("+")))
|
||||
assertEquals("42-+", S("42")::test.call("-", S("+")))
|
||||
|
||||
assertEquals("42-+", A::test.call(A("42"), "-", S("+")))
|
||||
assertEquals("42-+", A("42")::test.call("-", S("+")))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
|
||||
// WITH_REFLECT
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
var global = S("")
|
||||
|
||||
interface ITest {
|
||||
var test: S
|
||||
}
|
||||
|
||||
inline class Z(val x: Int) : ITest {
|
||||
override var test: S
|
||||
get() = S("${global.x}$x")
|
||||
set(value) {
|
||||
global = S("${value.x}$x")
|
||||
}
|
||||
}
|
||||
|
||||
inline class L(val x: Long) : ITest {
|
||||
override var test: S
|
||||
get() = S("${global.x}$x")
|
||||
set(value) {
|
||||
global = S("${value.x}$x")
|
||||
}
|
||||
}
|
||||
|
||||
inline class S(val x: String) : ITest {
|
||||
override var test: S
|
||||
get() = S("${global.x}$x")
|
||||
set(value) {
|
||||
global = S("${value.x}$x")
|
||||
}
|
||||
}
|
||||
|
||||
inline class A(val x: Any) : ITest {
|
||||
override var test: S
|
||||
get() = S("${global.x}$x")
|
||||
set(value) {
|
||||
global = S("${value.x}$x")
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
global = S("")
|
||||
assertEquals(S("42"), Z::test.call(Z(42)))
|
||||
assertEquals(S("42"), Z(42)::test.call())
|
||||
assertEquals(S("42"), Z::test.getter.call(Z(42)))
|
||||
assertEquals(S("42"), Z(42)::test.getter.call())
|
||||
Z::test.setter.call(Z(42), S("Z-"))
|
||||
assertEquals(S("Z-42"), global)
|
||||
Z(42)::test.setter.call(S("Z+"))
|
||||
assertEquals(S("Z+42"), global)
|
||||
|
||||
global = S("")
|
||||
assertEquals(S("42"), L::test.call(L(42L)))
|
||||
assertEquals(S("42"), L(42L)::test.call())
|
||||
assertEquals(S("42"), L::test.getter.call(L(42L)))
|
||||
assertEquals(S("42"), L(42L)::test.getter.call())
|
||||
L::test.setter.call(L(42L), S("L-"))
|
||||
assertEquals(S("L-42"), global)
|
||||
L(42L)::test.setter.call(S("L+"))
|
||||
assertEquals(S("L+42"), global)
|
||||
|
||||
global = S("")
|
||||
assertEquals(S("42"), S::test.call(S("42")))
|
||||
assertEquals(S("42"), S("42")::test.call())
|
||||
assertEquals(S("42"), S::test.getter.call(S("42")))
|
||||
assertEquals(S("42"), S("42")::test.getter.call())
|
||||
S::test.setter.call(S("42"), S("S-"))
|
||||
assertEquals(S("S-42"), global)
|
||||
S("42")::test.setter.call(S("S+"))
|
||||
assertEquals(S("S+42"), global)
|
||||
|
||||
global = S("")
|
||||
assertEquals(S("42"), A::test.call(A(42)))
|
||||
assertEquals(S("42"), A(42)::test.call())
|
||||
assertEquals(S("42"), A::test.getter.call(A(42)))
|
||||
assertEquals(S("42"), A(42)::test.getter.call())
|
||||
A::test.setter.call(A(42), S("A-"))
|
||||
assertEquals(S("A-42"), global)
|
||||
A(42)::test.setter.call(S("A+"))
|
||||
assertEquals(S("A+42"), global)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
|
||||
// WITH_REFLECT
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
interface IFoo {
|
||||
fun fooFun(z: Z): Z
|
||||
var fooVar: Z
|
||||
}
|
||||
|
||||
var global = Z(0)
|
||||
|
||||
|
||||
inline class Z(val x: Int) : IFoo {
|
||||
|
||||
override fun fooFun(z: Z): Z = Z(z.x + x)
|
||||
|
||||
override var fooVar: Z
|
||||
get() = Z(global.x + x)
|
||||
set(value) {
|
||||
global = Z(value.x + x)
|
||||
}
|
||||
|
||||
fun barFun(z: Z): Z = Z(z.x * 100 + x)
|
||||
|
||||
var barVar: Z
|
||||
get() = Z(global.x * 100 + x)
|
||||
set(value) {
|
||||
global = Z(value.x * 100 + x)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val fooFunR = Z::fooFun
|
||||
assertEquals(Z(53), fooFunR.callBy(mapOf(fooFunR.parameters[0] to Z(42), fooFunR.parameters[1] to Z(11))))
|
||||
|
||||
val fooFunBR = Z(42)::fooFun
|
||||
assertEquals(Z(142), fooFunBR.callBy(mapOf(fooFunBR.parameters[0] to Z(100))))
|
||||
|
||||
global = Z(0)
|
||||
val fooVarR = Z::fooVar
|
||||
assertEquals(Z(42), fooVarR.callBy(mapOf(fooVarR.parameters[0] to Z(42))))
|
||||
assertEquals(Z(42), fooVarR.getter.callBy(mapOf(fooVarR.getter.parameters[0] to Z(42))))
|
||||
fooVarR.setter.callBy(mapOf(fooVarR.setter.parameters[0] to Z(42), fooVarR.setter.parameters[1] to Z(1)))
|
||||
assertEquals(Z(43), global)
|
||||
|
||||
global = Z(100)
|
||||
val fooVarBR = Z(42)::fooVar
|
||||
assertEquals(Z(142), fooVarBR.callBy(mapOf()))
|
||||
assertEquals(Z(142), fooVarBR.getter.callBy(mapOf()))
|
||||
fooVarBR.setter.callBy(mapOf(fooVarBR.setter.parameters[0] to Z(1)))
|
||||
assertEquals(Z(43), global)
|
||||
|
||||
val barFunR = Z::barFun
|
||||
assertEquals(Z(1142), barFunR.callBy(mapOf(barFunR.parameters[0] to Z(42), barFunR.parameters[1] to Z(11))))
|
||||
|
||||
val barFunBR = Z(42)::barFun
|
||||
assertEquals(Z(2242), barFunBR.callBy(mapOf(barFunBR.parameters[0] to Z(22))))
|
||||
|
||||
global = Z(1)
|
||||
val barVarR = Z::barVar
|
||||
assertEquals(Z(142), barVarR.callBy(mapOf(barVarR.parameters[0] to Z(42))))
|
||||
assertEquals(Z(142), barVarR.getter.callBy(mapOf(barVarR.getter.parameters[0] to Z(42))))
|
||||
barVarR.setter.callBy(mapOf(barVarR.setter.parameters[0] to Z(42), barVarR.setter.parameters[1] to Z(3)))
|
||||
assertEquals(Z(342), global)
|
||||
|
||||
global = Z(2)
|
||||
val barVarBR = Z(42)::barVar
|
||||
assertEquals(Z(242), barVarBR.callBy(mapOf()))
|
||||
assertEquals(Z(242), barVarBR.getter.callBy(mapOf()))
|
||||
barVarBR.setter.callBy(mapOf(barVarBR.setter.parameters[0] to Z(4)))
|
||||
assertEquals(Z(442), global)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+25
@@ -18545,6 +18545,26 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/jvmStaticFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonOverridingFunOfInlineClass.kt")
|
||||
public void testNonOverridingFunOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/nonOverridingFunOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonOverridingVarOfInlineClass.kt")
|
||||
public void testNonOverridingVarOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/nonOverridingVarOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overridingFunOfInlineClass.kt")
|
||||
public void testOverridingFunOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/overridingFunOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overridingVarOfInlineClass.kt")
|
||||
public void testOverridingVarOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/overridingVarOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("properties.kt")
|
||||
public void testProperties() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/properties.kt");
|
||||
@@ -18599,6 +18619,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassMembers.kt")
|
||||
public void testInlineClassMembers() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassMembers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jvmStaticInCompanionObject.kt")
|
||||
public void testJvmStaticInCompanionObject() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/jvmStaticInCompanionObject.kt");
|
||||
|
||||
+25
@@ -18545,6 +18545,26 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/jvmStaticFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonOverridingFunOfInlineClass.kt")
|
||||
public void testNonOverridingFunOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/nonOverridingFunOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonOverridingVarOfInlineClass.kt")
|
||||
public void testNonOverridingVarOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/nonOverridingVarOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overridingFunOfInlineClass.kt")
|
||||
public void testOverridingFunOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/overridingFunOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overridingVarOfInlineClass.kt")
|
||||
public void testOverridingVarOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/overridingVarOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("properties.kt")
|
||||
public void testProperties() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/properties.kt");
|
||||
@@ -18599,6 +18619,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassMembers.kt")
|
||||
public void testInlineClassMembers() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassMembers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jvmStaticInCompanionObject.kt")
|
||||
public void testJvmStaticInCompanionObject() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/jvmStaticInCompanionObject.kt");
|
||||
|
||||
+25
@@ -18550,6 +18550,26 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/jvmStaticFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonOverridingFunOfInlineClass.kt")
|
||||
public void testNonOverridingFunOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/nonOverridingFunOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonOverridingVarOfInlineClass.kt")
|
||||
public void testNonOverridingVarOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/nonOverridingVarOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overridingFunOfInlineClass.kt")
|
||||
public void testOverridingFunOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/overridingFunOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overridingVarOfInlineClass.kt")
|
||||
public void testOverridingVarOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/overridingVarOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("properties.kt")
|
||||
public void testProperties() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/properties.kt");
|
||||
@@ -18604,6 +18624,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassMembers.kt")
|
||||
public void testInlineClassMembers() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassMembers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jvmStaticInCompanionObject.kt")
|
||||
public void testJvmStaticInCompanionObject() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/jvmStaticInCompanionObject.kt");
|
||||
|
||||
+35
-10
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.lang.reflect.Member
|
||||
@@ -49,15 +50,34 @@ internal class InlineClassAwareCaller<out M : Member>(
|
||||
// and in that case the number of expected arguments is one less than usual, hence -1
|
||||
-1
|
||||
}
|
||||
descriptor.dispatchReceiverParameter != null && caller !is BoundCaller -> 1
|
||||
|
||||
descriptor.dispatchReceiverParameter != null && caller !is BoundCaller -> {
|
||||
// If we have an unbound reference to the inline class member,
|
||||
// its receiver (which is passed as argument 0) should also be unboxed.
|
||||
if (descriptor.containingDeclaration.isInlineClass())
|
||||
0
|
||||
else
|
||||
1
|
||||
}
|
||||
|
||||
else -> 0
|
||||
}
|
||||
|
||||
val extraArgumentsTail = if (isDefault) 2 else 0
|
||||
|
||||
val kotlinParameterTypes =
|
||||
listOfNotNull(descriptor.extensionReceiverParameter?.type) +
|
||||
descriptor.valueParameters.map(ValueParameterDescriptor::getType)
|
||||
val kotlinParameterTypes: List<KotlinType> = ArrayList<KotlinType>().also { kotlinParameterTypes ->
|
||||
val extensionReceiverType = descriptor.extensionReceiverParameter?.type
|
||||
if (extensionReceiverType != null) {
|
||||
kotlinParameterTypes.add(extensionReceiverType)
|
||||
} else {
|
||||
val containingDeclaration = descriptor.containingDeclaration
|
||||
if (containingDeclaration is ClassDescriptor && containingDeclaration.isInline) {
|
||||
kotlinParameterTypes.add(containingDeclaration.defaultType)
|
||||
}
|
||||
}
|
||||
|
||||
descriptor.valueParameters.mapTo(kotlinParameterTypes, ValueParameterDescriptor::getType)
|
||||
}
|
||||
val expectedArgsSize = kotlinParameterTypes.size + shift + extraArgumentsTail
|
||||
if (arity != expectedArgsSize) {
|
||||
throw KotlinReflectionInternalError(
|
||||
@@ -116,10 +136,14 @@ internal fun <M : Member> CallerImpl<M>.createInlineClassAwareCallerIfNeeded(
|
||||
val needsInlineAwareCaller =
|
||||
descriptor.valueParameters.any { it.type.isInlineClassType() } ||
|
||||
descriptor.returnType?.isInlineClassType() == true ||
|
||||
(this !is BoundCaller && descriptor.extensionReceiverParameter?.type?.isInlineClassType() == true)
|
||||
this !is BoundCaller && descriptor.hasInlineClassReceiver()
|
||||
|
||||
return if (needsInlineAwareCaller) InlineClassAwareCaller(descriptor, this, isDefault) else this
|
||||
}
|
||||
|
||||
private fun CallableMemberDescriptor.hasInlineClassReceiver() =
|
||||
expectedReceiverType?.isInlineClassType() == true
|
||||
|
||||
internal fun Class<*>.getUnboxMethod(descriptor: CallableMemberDescriptor): Method = try {
|
||||
getDeclaredMethod("unbox" + JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS)
|
||||
} catch (e: NoSuchMethodException) {
|
||||
@@ -137,12 +161,13 @@ internal fun KotlinType.toInlineClass(): Class<*>? {
|
||||
return null
|
||||
}
|
||||
|
||||
internal fun Any?.coerceToExpectedReceiverType(descriptor: CallableMemberDescriptor): Any? {
|
||||
val expectedReceiverType =
|
||||
descriptor.extensionReceiverParameter?.type
|
||||
?: (descriptor.containingDeclaration as? ClassDescriptor)?.defaultType
|
||||
private val CallableMemberDescriptor.expectedReceiverType
|
||||
get() =
|
||||
extensionReceiverParameter?.type
|
||||
?: (containingDeclaration as? ClassDescriptor)?.defaultType.takeIf { dispatchReceiverParameter != null }
|
||||
|
||||
val unboxMethod = expectedReceiverType?.toInlineClass()?.getUnboxMethod(descriptor) ?: return this
|
||||
internal fun Any?.coerceToExpectedReceiverType(descriptor: CallableMemberDescriptor): Any? {
|
||||
val unboxMethod = descriptor.expectedReceiverType?.toInlineClass()?.getUnboxMethod(descriptor) ?: return this
|
||||
|
||||
return unboxMethod.invoke(this)
|
||||
}
|
||||
+25
@@ -16650,6 +16650,26 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/jvmStaticFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonOverridingFunOfInlineClass.kt")
|
||||
public void testNonOverridingFunOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/nonOverridingFunOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonOverridingVarOfInlineClass.kt")
|
||||
public void testNonOverridingVarOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/nonOverridingVarOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overridingFunOfInlineClass.kt")
|
||||
public void testOverridingFunOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/overridingFunOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overridingVarOfInlineClass.kt")
|
||||
public void testOverridingVarOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/overridingVarOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("properties.kt")
|
||||
public void testProperties() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/properties.kt");
|
||||
@@ -16704,6 +16724,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassMembers.kt")
|
||||
public void testInlineClassMembers() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassMembers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jvmStaticInCompanionObject.kt")
|
||||
public void testJvmStaticInCompanionObject() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/jvmStaticInCompanionObject.kt");
|
||||
|
||||
+25
@@ -17695,6 +17695,26 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/jvmStaticFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonOverridingFunOfInlineClass.kt")
|
||||
public void testNonOverridingFunOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/nonOverridingFunOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonOverridingVarOfInlineClass.kt")
|
||||
public void testNonOverridingVarOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/nonOverridingVarOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overridingFunOfInlineClass.kt")
|
||||
public void testOverridingFunOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/overridingFunOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overridingVarOfInlineClass.kt")
|
||||
public void testOverridingVarOfInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/overridingVarOfInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("properties.kt")
|
||||
public void testProperties() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/properties.kt");
|
||||
@@ -17749,6 +17769,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassMembers.kt")
|
||||
public void testInlineClassMembers() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassMembers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jvmStaticInCompanionObject.kt")
|
||||
public void testJvmStaticInCompanionObject() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/jvmStaticInCompanionObject.kt");
|
||||
|
||||
Reference in New Issue
Block a user