Fix reflection on top level declarations from other modules
The main problem here is that moduleName that is being passed to KPackageImpl is useless: as can be seen in ClosureCodegen.generateCallableReferenceDeclarationContainer, the name of the current module is always written to the class file for a callable reference, not the name of the module of the referenced declaration. This resulted in reflection not loading the correct .kotlin_module file and subsequently not finding the required file facade for a top-level function. The commit does not fix the issue with the incorrect module name written in the back-end, but workarounds it. It turns out, reflection can figure out the name of the module of the referenced declaration itself by parsing the header from the given java.lang.Class object for a single-file/multi-file package facade and extract the package_module_name protobuf extension. Similar code was already there in Member.getKPackage() in ReflectJvmMapping.kt but it did not support multi-file classes, of which there are a lot in the standard library; this is now supported #KT-12630 Fixed #KT-14731 Fixed
This commit is contained in:
@@ -396,6 +396,9 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
}
|
||||
else if (container instanceof PackageFragmentDescriptor) {
|
||||
iv.aconst(state.getTypeMapper().mapOwner(descriptor));
|
||||
// Note that this name is not used in reflection. There should be the name of the referenced declaration's module instead,
|
||||
// but there's no nice API to obtain that name here yet
|
||||
// TODO: write the referenced declaration's module name and use it in reflection
|
||||
iv.aconst(state.getModuleName());
|
||||
iv.invokestatic(REFLECTION, "getOrCreateKotlinPackage",
|
||||
Type.getMethodDescriptor(K_DECLARATION_CONTAINER_TYPE, getType(Class.class), getType(String.class)), false);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
// WITH_REFLECT
|
||||
|
||||
fun doStuff(fn: String.() -> String) = "ok".fn()
|
||||
import kotlin.reflect.KFunction1
|
||||
|
||||
fun doStuff(fn: KFunction1<String, String>) = fn.call("ok")
|
||||
|
||||
fun box(): String {
|
||||
return doStuff(String::toUpperCase)
|
||||
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
// KT-12630 KotlinReflectionInternalError on referencing some functions from stdlib
|
||||
|
||||
// IGNORE_BACKEND: JS
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
fun box(): String {
|
||||
val asIterable = List<Int>::asIterable
|
||||
assertEquals("fun kotlin.collections.Iterable<T>.asIterable(): kotlin.collections.Iterable<T>", asIterable.toString())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
// KT-12630 KotlinReflectionInternalError on referencing some functions from stdlib
|
||||
|
||||
// IGNORE_BACKEND: JS
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
fun box(): String {
|
||||
val lazyOf: (String) -> Lazy<String> = ::lazyOf
|
||||
assertEquals("fun lazyOf(T): kotlin.Lazy<T>", lazyOf.toString())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
@kotlin.Metadata
|
||||
public final class FunctionFromStdlibKt {
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static @org.jetbrains.annotations.NotNull method doStuff(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): java.lang.String
|
||||
public final static @org.jetbrains.annotations.NotNull method doStuff(@org.jetbrains.annotations.NotNull p0: kotlin.reflect.KFunction): java.lang.String
|
||||
}
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
@kotlin.Metadata
|
||||
public final class FunctionFromStdlibMultiFileFacadeKt {
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
@kotlin.Metadata
|
||||
public final class FunctionFromStdlibSingleFileFacadeKt {
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
+12
@@ -14380,6 +14380,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionFromStdlibMultiFileFacade.kt")
|
||||
public void testFunctionFromStdlibMultiFileFacade() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/methodsFromAny/functionFromStdlibMultiFileFacade.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionFromStdlibSingleFileFacade.kt")
|
||||
public void testFunctionFromStdlibSingleFileFacade() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/methodsFromAny/functionFromStdlibSingleFileFacade.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionToString.kt")
|
||||
public void testFunctionToString() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/methodsFromAny/functionToString.kt");
|
||||
|
||||
@@ -14380,6 +14380,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionFromStdlibMultiFileFacade.kt")
|
||||
public void testFunctionFromStdlibMultiFileFacade() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/methodsFromAny/functionFromStdlibMultiFileFacade.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionFromStdlibSingleFileFacade.kt")
|
||||
public void testFunctionFromStdlibSingleFileFacade() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/methodsFromAny/functionFromStdlibSingleFileFacade.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionToString.kt")
|
||||
public void testFunctionToString() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/methodsFromAny/functionToString.kt");
|
||||
|
||||
Reference in New Issue
Block a user