Compile time reflection/type checks for class fields

This isn’t what we usually do in JVM languages. But if you really want to do this, then you can use a very similar code to your own:

fun <T> compileCheck(a: KProperty1<*, T>, b: KProperty1<*, T>) { }

Unfortunately, V param of KProperty1 is covariant, so above code will work without problems for conflicting types - it will infer T to Any. I believe right now there is no official way to prevent this behavior, but considering that you do “weird stuff” already, you can use a workaround here.

Create kotlin/internal/Annotations.kt file with this contents:

package kotlin.internal

@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.BINARY)
internal annotation class Exact

Use above annotation to disable upcasting of T:

fun <T> compileCheck(a: KProperty1<*, @Exact T>, b: KProperty1<*, @Exact T>) { }

Result:

fun main() {
    compileCheck(Foo::f1, Bar::f1) // ok
    compileCheck(Foo::f1, Baz::f1) // compile error
}
2 Likes