Проблема на самом деле более общая:
configure(Foo::bar, { Object() })
тоже будет работать.Поскольку KProperty1
является ковариантным в параметре второго типа, KProperty1<R, String>
(например) также является KProperty1<R, String?>
, KProperty1<R, CharSequence>
и т. Д. Это также относится к типу функции (source: S) -> P
.Таким образом, что бы вы ни передавали (один параметр) transform
, компилятор всегда найдет P
такой, что типы будут соответствовать: наименьшая верхняя граница значений свойства и возвращаемые функцией функции.
Один довольно уродливыйОбходной путь, о котором я могу подумать, - это создание нековариантного типа оболочки:
class NonCov<A>(val value: A)
fun <P> configure(property: NonCov<KProperty1<R, P>>, transform: NonCov<(source: S) -> P)>) {
... // use property.value and transform.value
}
Тогда
class A(val x: String)
fun <P> configure(property: NonCov<kotlin.reflect.KProperty1<A, P>>, transform: NonCov<(source: A) -> P>) {}
fun main(args: Array<String>) {
configure(NonCov(A::x), NonCov { "" }) // compiles
configure(NonCov(A::x), NonCov { null }) // doesn't compile
}