2017-05-04 4 views
15

は、この問題を示し、最小限のデモコードです:私はそれをコンパイルしようとするとKotlinの型パラメータは、別の型パラメータで囲まれていると他の境界を持てないのはなぜですか?ここ

interface A 

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

、コンパイラが文句を言うだろう:

Error:(81, 25) Kotlin: Type parameter cannot have any other bounds if it's bounded by another type parameter

を私はKotlin Language Specificationを読んで、唯一以下のバウンド制限を見つけます:

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.

私が満たしている制限については説明しません。

私はKotlinの問題トラッカーを調べて、この制限に関する問題を見つけました:Allow to inherit a type parameter from another type parameter and a class : KT-13768。そこで質問がある

I don't think we can compile the code correctly to JVM if we remove this restriction.

By Andrey Breslav

:なぜ私たちは正しくコードをコンパイルすることはできませんしかし、この問題は、次のような理由(:この問題は、スタニスラフErokhinでリニューアルオープンされた5月6日、2017年に更新)によって拒否されましたこの制限を解除するとJVMに

同じデモをScalaで動作します。

trait A 

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

それはScalaはJVMに正しくコードをコンパイルできることを示しています。なぜコトリンはできないの? Kotlinでの決定可能なサブタイプ化を保証するのは制限されているのでしょうか(ScalaはTuring完全型システムを持っています)Cotlinのような決定的なサブタイプが必要かもしれません。後@erokhins(https://stackoverflow.com/a/43807444/7964561)によって答え

更新:

何かのJavaで禁じられたが、特にJavaの相互運用性に、JVMによって許可さをサポートする場合、いくつかの微妙な問題があります。私はscalacによって生成されたバイトコードを掘り下げる際に興味深い問題を発見します。私は次のようにデモで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は、次のシグネチャを生成します:Scalaでtest(new AB, new AB)

// 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をScalasが署名(LB;LB;)Vを起動するので、成功します。 Javaはという署名を呼び出し、実行時にjava.lang.NoSuchMethodErrorが発生するため、test(new AB(), new AB());(Javaで起動)は失敗します。これは、この制限を緩和した後、スカラがJavaで呼び出せないものを生成することを意味します。コトリンは、それをリラックスした後、同じ問題に会うかもしれません。

答えて

7

の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.私が知る限り、Kotlinには決定的なサブタイプがあり、決定性には影響しません。

関連する問題