Well, if it was in standard library then it would not be the problem, because annotations from kotlin.internal
could be used to enforce specific behavior of type inference, e.g.
package kotlin.internal
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.BINARY)
internal annotation class Exact
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.BINARY)
internal annotation class NoInfer
// Hack above - you can copy Kotlin's internal annotations to your module
// to use them in your module. Not recommended for production ;)
fun <T: Number> plus(a: @Exact T, b: @Exact T): Int {
return a.toInt() + b.toInt()
}
fun <T: Number> @Exact T.plus2(b: @Exact T): Int {
return this.toInt() + b.toInt()
}
fun <T: Number> plus3(a: T, b: @NoInfer T): Int {
return a.toInt() + b.toInt()
}
fun <T: Number> T.plus4(b: @NoInfer T): Int {
return this.toInt() + b.toInt()
}
fun main() {
val int: Int = 5
val double: Double = 3.7
plus(int, int)
plus(double, double)
plus(int, double) // errors for both arguments - because parameters must have equal types
int.plus2(int)
double.plus2(double)
int.plus2(double) // errors for both arguments - because parameters must have equal types
plus3(int, int)
plus3(double, double)
plus3(int, double) // error for second argument only - because inference takes into account only first parameter
int.plus4(int)
double.plus4(double)
int.plus4(double) // error for second argument only - because inference takes into account only first parameter
}
However, as these annotations are internal, I believe they cannot really be used on an operator fun
in Number
, because then it cannot be subclassed outside of the standard library.
As a bit on a side note, it would be nice for these annotations to be made public or promoted to some language construct, because they could be really helpful for designing APIs using generics. I guess it could be especially useful for library writers.