Почему нельзя вводить параметр в Kotlin какие-либо другие границы, если он ограничен другим параметром типа?

Вот минимальный демонстрационный код, который показывает эту проблему:

interface A

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

Когда я пытаюсь скомпилировать его, компилятор будет жаловаться:

Ошибка: (81, 25) Kotlin: параметр Type не может иметь никаких других границ, если он ограничен другим параметром типа

Я прочитал Специфика языка Kotlin, но вы найдете только следующее ограничение:

Параметр type не может указывать себя как свою собственную привязку, и несколько параметров типа не могут указывать друг друга как ограничение циклическим образом.

Он не объясняет, какое ограничение я встречаю.

Я изучаю трекер Kotlin, и я нахожу проблему об этом ограничении: Разрешить наследование параметра типа из другого параметра типа и класса: KT-13768. Однако этот вопрос был отклонен по следующей причине (обновление от 6 мая 2017 года: этот вопрос был вновь открыт Станиславом Ерохиным):

Я не думаю, что мы сможем правильно скомпилировать код JVM, если удалим это ограничение.

Андрей Бреслав

Итак, возникает вопрос: почему мы не можем правильно скомпилировать код JVM, если мы удалим это ограничение?

Эта же демонстрация работает в Scala:

trait A

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

Это означает, что Scala может скомпилировать код для JVM. Почему Котлин не может? Является ли это ограничением для обеспечения разрешимого подтипирования в Kotlin (я думаю, что подтипирование невозможно для Scala (Scala имеет систему Turing-complete type). Kotlin может хотеть разрешимый подтипирование, как С#.)?

Обновление после ответа от @erokhins (qaru.site/info/387165/...):

Есть некоторые тонкие проблемы при поддержке чего-то, запрещенного Java, но разрешенного JVM, особенно в Java-совместимости. Я нахожу интересную проблему при перекодировании в байт-код, созданный с помощью скаляса. Я изменяю код Scala в демо, как показано ниже:

trait A

trait B

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

class AB extends A with B

Scalac сгенерирует следующую подпись:

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

Вызов test с test(new AB, new AB) в Scala будет успешным, так как Scalas вызывает подпись (LB;LB;)V; но вызывать с помощью test(new AB(), new AB()); в Java не удастся, так как Java вызывает подпись (LB;Ljava/lang/Object;)V, вызывая java.lang.NoSuchMethodError во время выполнения. Это означает, что генерируется скаляр, что-то не может быть вызвано на Java после ослабления этого ограничения. Котлин может встретить ту же проблему после расслабления.

Ответ 1

Эти ограничения были сделаны потому, что у него есть java (язык):

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

И мы полагаем, что это запрещено также и на уровне байт-кода. Я вникаю в него и кажется, что он разрешен, а scalac генерирует следующую подпись:

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

Итак, мы, вероятно, можем поддерживать такие случаи в будущих версиях kotlin.

P.S. Насколько я знаю, у Котлина есть разрешимый подтипирование, и это не влияет на разрешимость.