Sorry for my English. I would like to use function test with parameter value exactly type of some property. But it declared as out R, and compiler inference type to Any if types is distinct.
For example:
open class Foo(var barInt: Int)
// public interface KProperty1<T, out R> : KProperty<R>, (T) -> R
fun <E : Foo, T> test(field: kotlin.reflect.KProperty1<E, T>, value: T) {}
fun main(args: Array<String>) {
test(Foo::barInt, 12345) // ok
test(Foo::barInt, "NotInt") // ok! Type T is Any, but I would like compile error
}
As far as I know it is not possible yet. There are a few internal annotations used for this in the standard library but they are not publicly usable. There is another discussion with the same problem here where Ilya explains this
TL;DR of it: they know that this is useful but have not made it public yet because they are not sure of the design of those annotations.
I found temporary workaround for those who are ready to possible future refactoring.
It may be kotlin compiler or ide bug:
Create file kotlin/internal/Annotations.kt in source root of your project:
package kotlin.internal
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.BINARY)
annotation class Exact
Add compiler command line parameter: -Xallow-kotlin-package
Using this annotation:
import kotlin.internal.Exact
open class Foo(val barInt: Int)
// public interface KProperty1<T, out R> : KProperty<R>, (T) -> R
fun <E : Foo, T> test(field: kotlin.reflect.KProperty1<E, @Exact T>, value: T): T = TODO()
fun main(args: Array<String>) {
test(Foo::barInt, 123) // ok
test(Foo::barInt, "NotInt") // expected compile error:
/*
Error:(13, 5) Kotlin: Type inference failed: Cannot infer type parameter T in fun <E : Foo, T> test(field: KProperty1<E, T>, value: T): T
None of the following substitutions
(KProperty1<Foo, Int>,Int)
(KProperty1<Foo, String>,String)
can be applied to
(KProperty1<Foo, Int>,String)
*/
}
I guess it is, so I would not rely on this in production code.
The @Exact annotation means, that the compiler will only accept arguments with the exact type.
fun <A, B: List<A>>foo(a: A, list: B) {}
foo(1, listOf(1, 2, 3)) // this should always work
foo(1, lisOf(true, false)) // this also works: B is now List<Any> and A is Any
fun <A> bar(a: A, list: List<A>) {} // has the same results
With the @Exact annotation the kotlin standard library forces this to work in a way where when a is an integer the list also needs to be a list of integers.
That way you can create functions like contains.
Ok it uses another internal annotation but the idea is the same. This is also the reason I guess why they are still internal. They are not that obvious to use and the design for them is not yet settled enough to make them public.