Restrict type by receiver

The extension function

fun <T> T.and(other : T) {
                      
}                       

allows you to run

"Hello".and(21) // compiles fine

and the only way to ensure the type is preserved is to specify it

"Hello".and<String>(21) // compiler error

At which point if you fix it, the specified type becomes redundant

It would be nice if there was a way we could tell the compiler to only allow the specific type when declaring these functions.

ie.

fun <only T> T.and(other : T) {
                      
}

This may not be a huge problem for such a simple function, but its an issue when you want to declare an infix function, you won’t be able to use infix syntax while retaining strict typing.

3 Likes

There’s @OnlyInputTypes type parameter annotation exactly for that case, but unfortunately it’s internal now. However we have some plans to expose it later: https://youtrack.jetbrains.com/issue/KT-13198

I don’t think this is exactly what I had in mind. Based on this comment, I’m sort of doubtful:

“Also please note that @OnlyInputTypes doesn’t prohibit invoking such functions with R = Any, it just requires it to be specified explicitly, if one wants to.”

What I would want is a pure type restriction, it can only be what the receiver is.

After review and following the recommendation of Andrey in the issue, exposing a copy of the annotation in my own project does to seem to solve this issue for me.
However I do hope that the annotation becomes exposed publically in the near future as well.

fun <T> T.and(other: @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @kotlin.internal.NoInfer T) {}

fun <@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @kotlin.internal.OnlyInputTypes T> T.and(other: T) { }

You can also use NoInfer and use these annotations much easier by using @Suppress

1 Like