Why can't type parameter in Kotlin have any other bounds if it's bounded by another type parameter?
kotlin, types
Solution
This restrictions was made because java(language) has it:
interface A {}
// Error:(7, 26) java: a type variable may not be followed by other bounds
<T1, T2 extends T1 & A> void test() {}
And we suppose that this forbidden also in bytecode level. I dig into it and seems like it is allowed, and scalac generate the following signature:
// access flags 0x1
// signature <T1:Ljava/lang/Object;T2:TT1;:LA;>()V
// declaration: void test<T1, T2T1 extends A>()
public test()V
So, we probably can support such cases it in the future versions of kotlin.
P.S. As far as I know Kotlin has decidable subtyping, and decidability isn't affected by this.
Problem
Here is the minimal demo code that shows this problem: ``` interface A fun <T1, T2> test() where T2 : T1, T2 : A {} ``` When I try to compile it, compiler will complain: Error:(81, 25) Kotlin: Type parameter cannot have any other bounds if it's bounded by another type parameter I read Kotlin Language Specification, but only find the following bound restriction: A type-parameter cannot specify itself as its own bound, and several type-parameters cannot specify each other as a bound in a cyclic manner. It doesn't explain the restriction I meet. I explore Kotlin's issue tracker, and I find an issue about this restriction: Allow to inherit a type parameter from another type parameter and a class : KT-13768. However, this issue has been rejected by the following reason (update on May 6th, 2017: this issue has been reopened by Stanislav Erokhin): I don't think we can compile the code correctly to JVM if we remove this restriction. By Andrey Breslav So the question is: why can't we compile the code correctly to JVM if we remove this restriction? The same demo works in Scala: ``` trait A def test[T1, T2 <: T1 with A](): Unit = {} ``` It indicates that Scala can compile the code correctly to JVM. Why can't Kotlin? Is it a restriction to guarantee a decidable subtyping in Kotlin (I guess. Subtyping is undecidable for Scala (Scala has a Turing-complete type system). Kotlin may want decidable subtyping like C#.)? Update after answered by @erokhins (https://stackoverflow.com/a/43807444/7964561): There are some subtle issues when supporting something forbidden by Java but allowed by JVM, especially in Java interoperability. I find an interesting issue when digging into bytecode generated by scalac. I modify Scala code in demo as follow: ``` trait A trait B def test[T1 <: B, T2 <: T1 with A](t1: T1, t2: T2): Unit = {} class AB extends A with B ``` Scalac will generate the following signature: ``` // signature <T1::LB;T2:TT1;:LA;>(TT1;TT2;)V // descriptor: (LB;LB;)V public <T1 extends B, T2 extends T1 & A> void test(T1, T2); ``` Invoke `test` with `test(new AB, new AB)` in Scala will succeed, since Scalas invoke signature `(LB;LB;)V`; but invoke with `test(new AB(), new AB());` in Java will fail, since Java invokes signature `(LB;Ljava/lang/Object;)V`, causing `java.lang.NoSuchMethodError` in runtime. It means scalac generates something cannot be invoked in Java after relaxing this restriction. Kotlin may meet the same issue after relaxing it.