Olaf Gottschalk
07/17/2025, 10:47 AMholds
for a DSL that is a generic function very similar to in
- it checks the contents of something against another value.
My current implementation looks like this:
@TransformationDsl
infix fun <V> ValueProvider<S, V>.holds(value: V): Boolean = value in this
The problem is, written like this, the user loses type safety as the generic V
will always look for the first suitable "upper" type, being Any
in the worst case.
So, usage like this is not prohibited by the compiler:
val x: Value<String> = TODO()
if (x holds 42) {
// ...
}
In this case, I want the compiler to note that the Integer 42 can never be contained in the Value<String>
!
Looking at the declaration of the operator fun in
for an Iterable reveals this hack:
public operator fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.contains(element: T): Boolean {
if (this is Collection)
return contains(element)
return indexOf(element) >= 0
}
If you try to check whether an Iterable of String contains an Int value, the compiler does not allow this.
I want exactly the same behaviour, but I cannot use the annotation, because it is internal...
Any other way to not allow the generic V to be allowed to be Any?
Thanks!Dan Rusu
07/21/2025, 5:18 PMout V
in the function to signify that only subtypes are allowed. I would also consider using declaration-site variance in the ValueProvider classOlaf Gottschalk
07/22/2025, 4:50 AMValueProvider<out V>
already. That does not help.Olaf Gottschalk
07/22/2025, 7:57 AMinterface ValueProvider<out V> {
val value: V
}
infix fun <V> ValueProvider<V>.holds(value: V) = this.value == value
fun demoValueProvider(v: ValueProvider<Int>) {
if (v holds "42") { // this should not work
println("Value is 42")
} else {
println("Value is not 42")
}
}
fun demoList(l: List<Int>) {
if ("42" in l) { // rightfully fails to compile
println("List contains 42")
} else {
println("List does not contain 42")
}
}
I want to have the same behaviour as seen with the in
operator. The error you see on the demoList
fun is: Type inference failed. The value of the type parameter 'T' must be mentioned in input types (argument types, receiver type, or expected type). Try to specify it explicitly.
Which is hinting me at that the @kotlin.internal.OnlyInputTypes
is doing this. But this annotation is internal. 😞CLOVIS
08/14/2025, 8:12 AM