¿Por qué no se puede escribir un parámetro en Kotlin que tenga otros límites si está limitado por otro parámetro de tipo?

Aquí está el código de demostración mínimo que muestra este problema:

interface A fun <T1, T2> test() where T2 : T1, T2 : A {} 

Cuando bash comstackrlo, el comstackdor se queja:

Error: (81, 25) Kotlin: parámetro de tipo no puede tener ningún otro límite si está delimitado por otro parámetro de tipo

Leí la Especificación de idioma de Kotlin , pero solo encuentro la siguiente restricción restringida:

Un parámetro de tipo no puede especificarse a sí mismo como su propio límite, y varios parameters de tipo no pueden especificarse entre sí como un límite cíclico.

No explica la restricción que encuentro.

Exploro el rastreador de problemas de Kotlin y encuentro un problema sobre esta restricción: Permitir henetworkingar un parámetro de tipo de otro parámetro de tipo y una class: KT-13768 . Sin embargo, este problema ha sido rechazado por el siguiente motivo (actualización del 6 de mayo de 2017: Stanislav Erokhin volvió a abrir este tema):

No creo que podamos comstackr el código correctamente en JVM si eliminamos esta restricción.

Por Andrey Breslav

Entonces la pregunta es: ¿por qué no podemos comstackr el código correctamente en JVM si eliminamos esta restricción?

La misma demostración funciona en Scala:

 trait A def test[T1, T2 <: T1 with A](): Unit = {} 

Indica que Scala puede comstackr el código correctamente en JVM. ¿Por qué no puede Kotlin? ¿Es una restricción garantizar una subtipificación decidible en Kotlin? (Supongo que la subtipificación es indecidible para Scala (Scala tiene un sistema de tipo Turing completo). ¿Kotlin puede querer un subtipado decidible como C #.?

Actualización después de respondida por @erokhins ( https://stackoverflow.com/a/43807444/7964561 ):

Hay algunos problemas sutiles al admitir algo prohibido por Java pero permitido por JVM, especialmente en la interoperabilidad de Java. Encuentro un problema interesante cuando profundizo en bytecode generado por scalac. Modifico el código de Scala en la demo de la siguiente manera:

 trait A trait B def test[T1 <: B, T2 <: T1 with A](t1: T1, t2: T2): Unit = {} class AB extends A with B 

Scalac generará la siguiente firma:

 // 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); 

La test invocación con test(new AB, new AB) en Scala tendrá éxito, ya que Scalas invocará la firma (LB;LB;)V ; pero invocar con test(new AB(), new AB()); en Java fallará, ya que Java invoca la firma (LB;Ljava/lang/Object;)V , causando java.lang.NoSuchMethodError en time de ejecución. Significa que scalac genera algo que no se puede invocar en Java después de relajar esta restricción. Kotlin puede enfrentar el mismo problema después de relajarlo.

Estas restricciones se hicieron porque java (idioma) lo tiene:

  interface A {} // Error:(7, 26) java: a type variable may not be followed by other bounds <T1, T2 extends T1 & A> void test() {} 

Y suponemos que esto también está prohibido en el nivel de bytecode. Indago en ello y parece que está permitido, y scalac genera la siguiente firma:

  // access flags 0x1 // signature <T1:Ljava/lang/Object;T2:TT1;:LA;>()V // declaration: void test<T1, T2T1 extends A>() public test()V 

Por lo tanto, probablemente podamos apoyar tales casos en las versiones futuras de kotlin.

PD: Hasta donde sé, Kotlin tiene un subtipado decidible, y la decibilidad no se ve afectada por esto.