Intersection Type Compatibility Problem With Java

I can currently do something like this in java:

private static <T extends Comparable<T> & CharSequence> T thing(){
    return (T) "";
}

and just use it

var stuff=thing();

variable stuff gets a type hint of Comparable<?> & CharSequence
Doing the equivalent in Kotlin doesn’t work

fun <T> thing():T where T:CharSequence,
                        T:Comparable<T>{
                            return "" as T
                        }
fun main() {
    val stuff= thing() // ERROR, cannot infer type T
}

if I call it with thing<String>() then things work fine but defeats the purpose of the method.

Here is a practical situation I’m dealing with where this incompatibility is a problem.
I have multiple classes that may implement one or more of certain sealed interfaces. In some cases I want to filter and return a list of items that implement more than one of those interfaces (intersection). Because those are sealed I’m not allowed to create an interface that combines them (outside package where they are defined).
Potential solutions is to do casts everywhere and just know that you can do that and hope nothing changes in the code to break that assumption or create a wrapper like this

private class HasIdAndHasRef<T>(item: T) where T :HasId, T :HasRef {
        val asHasId:HasId = item
        val asHasRef:HasRef = item
    }

It seems that for similar behavior to Java that it should be possible to use thing<*>() or just omit the type if nothing else and avoid the need for what should be unnecessary wrappers.

1 Like

Can you give an actual real example of how you’re trying to use this and it’s not working? I’m struggling to understand your use case.

I think Kotlin just doesn’t have intersection types outside of generics, so if you don’t provide it a type, it doesn’t know what to use.

The main problem is that if a function like that is defined on the Java side, I simply cannot call it from Kotlin, only Java, breaking compatibility in at least one direction. I can call the function defined in Kotlin from Java without issues and it behaves the same as if I had defined it in Java inferring Comparable<?> & CharSequence in the case above. In the specific use case I have, I’m dealing with generated code where there are literally dozens of different classes that could fit in the X parameter type in thing<X>() that implements both interfaces. I changed the name but in practice that function uses a class field list and returns back only items implementing two interfaces. I simply can’t specify which type I’m expecting to come back because it could be any of the dozens and in fact it would not just be of one type anyways.

So if I’m understanding your problem, it’s basically like this.

You have two interfaces, Foo and Bar. You also have a lot of classes, some of which implement Foo, some of which implement Bar, some of which implement both, and some of which implement neither. You then have a list (or other collection) of instances of these classes, and you want to filter that to a list that contains only the classes that implement Foo and Bar. Am I right so far?

interface Foo

interface Bar

class A : Foo

class B : Bar

class C : Foo, Bar

class D

inline fun <T, reified R> Collection<T>.filterIsOneOf(): List<R> where R : Foo, R : Bar = filterIsInstance<R>()

val onlyFooAndBar = listOf(A(), B(), C(), D()).filterIsOneOf() // you want val onlyFooAndBar to be a list of C, since C is the only class that implements Foo and Bar

The problem with this is that generics don’t work that way. Generics allow you to set the type you want when you use it, but the type itself has to exist. The where clause just allows you to provide complex filters to constrain the type, but the type still needs to exist.

I’ve never seen Java having union types before; I’m guessing that’s a fairly new feature which Kotlin doesn’t have.

Ok I did a bit more reading and research. Turns out intersection types are not new to Java, they’ve been there since 8!!! Very surprising to learn that.

However, Kotlin does not currently support intersection types. There’s a big ol’ feature request for it that still hasn’t happened: https://youtrack.jetbrains.com/issue/KT-13108

I also found this thread: Current intersection-type options in Kotlin It kind of blows my mind a bit, but you might find it useful.

Yes, I’ve been through those and they haven’t been updated in a while. Main difference I got here is that some other solutions like using an interface to combine the other ones while using delegate implementations doesn’t work when dealing with sealed interfaces. Also Java only supported it in the way it works today with the addition of the var keyword in Java 10 since you can’t really explicitly define an intersection type as a concrete type of a variable.

The roadmap ends with kotlin 2 and k2 stabilization which will help with other language updates but it is apparently expected to be released mid year so I was wondering if anyone knows when fixing this compatibility difference is expected to happen.