Does Kotlin compiler always retain parameter names in bytecode? - reflection

In kotlin-reflect, class KParameter has nullable name, and its KDoc says:
Name of this parameter as it was declared in the source code, or null if the parameter has no name or its name is not available at runtime. Examples of nameless parameters include this instance for member functions, extension receiver for extension functions or properties, parameters of Java methods compiled without the debug information, and others.
It says about well-known fact that Java doesn't always include parameter names in bytecode, but it says nothing about Kotlin classes, though there are some others.
Can I assume that Kotlin compiler retains parameter names declared for functions in Kotlin sources? (In particular, I need constructor parameter names).

Just to complete Alexander's answer above as it may not be immediately obvious, to provide parameter names for Java reflection of Kotlin classes (i.e. for Java code using reflection to view parameter names of Kotlin code), you must supply the -java-parameters argument (since Kotlin 1.1).
Gradle
In your build.gradle > compileKotlin closure
compileKotlin {
kotlinOptions {
jvmTarget = '1.8' //Good to target Java 8 unless you need 7
javaParameters = true //Will retain parameter names for Java reflection
}
}
Maven
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<configuration>
<args>
<arg>-java-parameters</arg>
</args>
...
IntelliJ
In Preferences > Kotlin Compiler > Additional command line parameters
Append -java-parameters to the list
Ensure you run a clean before running any reflection based code.

Unless the bytecode was modified in some way, it's safe to assume that all parameters which are given names in the sources will have those names at runtime. This is true for Kotlin 1.0 and there's no plans to change this.
If you're interested which unnamed parameters does others include, there's also the single parameter of a default property setter and the outer class parameter for an inner class constructor. Such parameters don't have names neither in the source code nor at runtime.
UPD: since this may seem confusing to some, this question and the answer are only related to retaining parameter names for Kotlin reflection and specifically so that KParameter.name would work. This is not related to the parameter names that Java reflection would see for compiled Kotlin code. To retain parameter names for Java reflection, pass the -java-parameters option to the Kotlin compiler.

Related

Is there a fix for InheritanceManager breaking static type checking?

I have added django-model-utils to an existing (large) project, and the build is now failing, as part of the build includes static type checking with mypy.
It complains that models that I have added objects = InheritanceManager() to, don't have attributes for reverse ForeignKeys, if the reverse FK is accessed in a method on that model. For example, take the following:
class Student(Model):
school = ForeignKey(School, related_name='students')
class School(Model):
objects = InheritanceManager() # IRL School is a subclass of some other model
def something(self):
return self.students.filter(...)
Then running mypy on it, will return:
error: "School" has no attribute "students"
And even if I remove the related_name, and use self.student_set (i.e. the default django relation), it will still produce the same type of error. Only removing the InheritanceManager fixes the static type checking. Of course, I'm using it for a reason as I need to select_subclasses elsewhere in the code.
Has anyone come across this, or have a fix?
django-stubs uses plugin to add all managers. This plugin is triggered only if added manager is a "subclass" (not just real subclass, but also recognizable by mypy as such) of models.Manager.
django-model-utils is untyped, so InheritanceManager is in fact Any for mypy, and plugin does not see it. To solve exactly this issue I was adding py.typed marker to django-model-utils as a CI stage after package installation. You can also use a fork with py.typed or create a stub package for django-model-utils. This can result in other issues and doesn't give good type checking (all unannotated methods have Any as implicit arguments and return type), but is better than nothing. For my needs the marker was sufficient.
py.typed marker is an empty file located in package root (venv/lib/.../django_model_utils/py.typed) - it tells mypy that package does not need separate stubs and contains all necessary types.

How to convert vavr collection to Java array?

I know about https://www.javadoc.io/doc/io.vavr/vavr/latest/io/vavr/Value.html#toJavaArray but it's deprecated. Is there a non-deprecated method that can be used?
Out of the three toJavaArray variants, only the toJavaArray(Class) variant is deprecated directly, the other two are marked as deprecated because the Value class itself is deprecated. The generated javadoc is not very helpful in distinguishing between the two, unfortunately, but you can check the source code directly. This picture is probably a more precise representation of the current state:
Value is deprecated in favor of io.vavr.Iterable. This new interface is an extension of the java.lang.Iterable type, that differs mainly in that it returns an io.vavr.collection.Iterator instead of a simple java.util.Iterator. io.vavr.collection.Iterator extends Value, and I expect that after the removal of the Value interface, all methods which are not explicitly deprecated in the Value interface will be moved to io.vavr.collection.Iterator.
Out of the two not explicitly deprecated toJavaArray methods I would use the T[] toJavaArray(IntFunction<T[]> arrayFactory) variant – which was one of my contributions to the vavr project –, as it returns a typed array of the correct type instead of an Object[].
To sum it up, instead of using vavrValue.toJavaArray(), I would use vavrValue.iterator().toJavaArray(SomeType[]::new).

How to safely cast a reflected class in Kotlin

I need to dynamically load classes at runtime in Kotlin. I would like to check that they implement my interface, and if so, all green. Unfortunately, Kotlin's "smart casts" is failing me:
var className = "some.class.Name"
val unsafeClass = Class.forName(className).kotlin
require(unsafeClass.isSubclassOf(MyInterface::class)) {
"Class '$className' is not a MyInterface"
}
val safeClass = unsafeClass as KClass<MyInterface>
^^^^^^^^^^^^^^^^^^^^^^
Unchecked cast: KClass<out Any!> to KClass<MyInterface>
I'm clearly checking that the class implements the given interface. Can I re-phrase this code to avoid the warning?
I tried to test with is KClass<MyInterface> but I get a type erasure error (obviously, because the generic type information disappears at runtime.)
Edit: to clarify, my application needs to read class names "some.class.Name" at startup, during configuration; load those classes; check that they satisfy an interface; and store a Class or KClass reference for later. During runtime, it will use those references to create objects, using cls.createInstance() or such.
My question: is there any way to do so without getting unsafe cast warnings?
I can either get a warning at configuration time, when I cast the KClass<*> to KClass<MyInterface> (even though I required the class to be a subclass) but then I get no warning later on, because .createInstance() on a KClass<MyInterface> class reference returns a type-checked MyInterface instance.
Or, I can store the references as KClass<*>, without warnings at configuration time, but then I'll get the warning in the place where I create the instances, because I'll need to unsafe cast Object instances to MyInterface.
Is there any solution that will satisfy the compiler?
JVM and Kotlin implement generics only at the compiler level. One cannot see generic parameters of a generic class at runtime.
https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
At runtime, there is no difference between Class<*> and Class<MyInterface>. These two are the same instance of Class type.
The warning that you have means that you have no information in the generic parameter at runtime, a compiler cannot validate it too, and it only can trust you
I do not see the reason cast the KClass to the KClass<MyInterface>. It is only necessary for an object, not it's class. Also, it probably can be simplified to use Class<*> instead, e.g:
val className = "some.class.Name"
val unsafeClass = Class.forName(className)
require(MyInterface::class.java.isAssignableFrom(unsafeClass)) {
"Class '$className' is not a MyInterface"
}
val safe = unsafeClass.newInstance() as MyInterface
This cast is not only unchecked, it's actually incorrect: because AMyInterfaceImpl::class has type KClass<AMyInterfaceImpl> and KClass is not covariant (for good reason), it does not have the type KClass<MyInterface>. You can see that from this code not compiling:
class AMyInterfaceImpl : MyInterface { ... }
val cls: KClass<MyInterface> = AMyInterfaceImpl::class
So if the cast could be checked, it would fail.
KClass<out MyInterface> would be correct, but I don't think the compiler will understand this and allow smart cast. It's just too rarely useful to teach the compiler.

What are the uses of constructor reference in java 8

I was reading about Java 8 features, which lead me to this article and I was wondering about the actual uses of constructor reference, I mean why not just use new Obj ?
P.S, I tried googling, but I failed to find something meaningful, if someone has a code example, link or tut it will be great
First of all, you should understand that constructor references are just a special form of method references. The point about method references is that they do not invoke the referenced method but provide a way to define a function which will invoke the method when being evaluated.
The linked article’s examples might not look that useful but that’s the general problem of short self-contained example code. It’s just the same as with the “hello world” program. It’s not more useful than typing the text “hello world” directly into the console but it’s not meant to be anyway. It’s purpose is to demonstrate the programming language.
As assylias has shown, there are use cases involving already existing functional interfaces using the JFC API.
Regarding the usefulness of a custom functional interface that’ll be used together with a constructor reference, you have to think about the reason to use (functional) interface in general: abstraction.
Since the purpose of an interface is to abstract the underlying operation, the use cases are the places where you do not want to perform an unconditional new SomeType(…) operation.
So one example is the commonly known Factory pattern where you define an interface to construct an object and implementing the factory via constructor reference is only one option out of the infinite possibilities.
Another important point are all kinds of Generic methods where the possibility to construct instances of the type, that is not known due to type erasure, is needed. They can be implemented via a function which is passed as parameter and whether one of the existing functional interfaces fits or a custom one is needed simply depends on the required number and types of parameters.
It's useful when you need to provide a constructor as a supplier or a function. Examples:
List<String> filtered = stringList.stream()
.filter(s -> !s.isEmpty())
.collect(Collectors.toCollection(ArrayList::new)); //() -> new ArrayList<> ()
Map<String, BigDecimal> numbersMap = new HashMap<>();
numbersMap.computeIfAbsent("2", BigDecimal::new); // s -> new BigDecimal(s)
someStream.toArray(Object[]::new); // i -> new Object[i]
etc.

Why is object returned from getDefinitionByName()?

In Actionscript 3, why does getDefinitionByName() return an Object when the docs say:
Returns a reference to the class object of the class specified by the name parameter.
Based on that, I would conclude that the returned object should be Class instead of Object. Can someone enlighten me why that is not the case?
getDefinitionByName can also return a Function, such as getDefinitionByName('flash.utils.getDefinitionByName').
This only works on namespace-level functions, though, not static class methods.
Despite the method signature, getDefinitionByName does return Class. I think the misleading signature is due to the method existing before the Class object (when it used to return an anonymous/extended object instance).
Perhaps Adobe considered that this function might return different values in a future version of Flash Player. For instance, ECMAScript, the standard on which ActionScript is based, has historically used Function objects with prototypes as the basis for class-like objects. During discussions of the newest versions of the ECMAScript standard, there has been sugestions for "freezing" function-based classes at run-time to make them into something like compile-time Class objects. What if you could also specify a definition name for them? Are they actually of type Class at this point, or are they still or type Function? Probably the later, in my opinion. Both 'Class' and 'Function' references can be generalized as Object, so that return type makes sense in this context.
Note: This explanation is purely speculation based on what I've read in the ECMAScript specification wiki and the blogs of various committee members.

Resources