2016-05-02 9 views
1

これは、スカラーでは何となく予期しない(または私の期待が間違っています)。したがって、次のいくつかのサンプルコードです:Scalaでの自己入力時の自動ミックスAPI

trait A 
trait B 

trait HasA { def foo: A } 
trait HasB { def foo: B } 

これまでのところは良い、私は

scala> trait HasBoth extends HasA with HasB 
<console>:11: error: overriding method foo in trait HasA of type => A; 
method foo in trait HasB of type => B has incompatible type 
     trait HasBoth extends HasA with HasB 

がさてさて、私はエラーを参照しています。それは理にかなっている。

が、混乱は、次の来る:

trait Wrapper[T] { def get: T } 
trait HasBoth2 { self: Wrapper[HasA with HasB] => def bar = get.foo } 

この私はそれは非常識だ見つけました。 barのタイプを確認すると、Bとなります。制約がHasB with HasAであるように注文を裏返すと、barAになります。

ここでは矛盾があります。自動的

  1. HasA with HasB収量{ def foo: A with B }、または
  2. HasBoth2は、型の非互換性のエラーを生成する:私は、のいずれかを期待します。

この不一致を親切に説明してください。それは型のシステムバグです。

更新HasBoth2の制約を満たしますラップ

trait HasBoth3 extends HasA with HasB { def foo: A with B } 
type Wrapped = Wrapper[HasBoth3] 

+0

ここでは、型vsクラスの混乱のようです。型HasA with HasBは型制約に過ぎず、型trait HasBothはクラスを作成しようとしています。 – dmitry

+0

@ドミトリーまだ自己タイピングを説明していません。型が制約に矛盾する – HuStmpHrrr

+0

実際に型制約を満たすことができるのは「HasA with HasB」にキャストされた 'null 'だけなので、それは重要ではありません。 –

答えて

3

これは予期された動作です。これは、スカウガの不健全さの中核ポイントの1つです。

SI-7278: Unsoundess in many guises

私は下の部分で再現SI-7255でいくつかの説明を提供します。

これは、タイプシステムのかなり基本的な失敗であり、おそらくドットのモチベーションの一部であるようです。

抽象型のメンバは、通常は次のように統語されません。彼らは洗練されるだけです。この文脈で意味することは、BとAの自己タイプとの交差点であるタイプが作成されたことです。すなわち、AとBが交差するタイプは、線形化で最後の 'C'を使用できると仮定して作成されます。最後の 'C'が以前の 'C'の改良でない限り、コンパイルはrefcheckで失敗します。

このクラスは、クラスが宣言されたクラスと宣言された自己型の共通部分を持つものと見なすため、自己型によって分解されます。 XがYまたはYがXのいずれかが有効なインスタンス化である可能性があります。 "最後の"メンバーであることを先験的に知る方法はありません。

さらに多くの色については、私の最後のコメントSI-7472を参照してください。