4

コンパイラーが抽象型パラメーターを持つクラスのマニフェストを解決する必要があるときに、コンパイラーの問題が発生しています。次のスニペットは問題を示しています

trait MyStuff

trait SecurityMutatorFactory[X]{
  def apply(x1:X,x2:X)
}

object Example{

  trait LEdge[N]
  {
    type L1
  }
  type MyEdge[X] = LEdge[X] { type L1 = SecurityMutatorFactory[X]}

  val a:Manifest[MyEdge[MyStuff]] = implicitly[Manifest[MyEdge[MyStuff]]]

}

その結果、コンパイラは次の型エラーをスローします。

type mismatch;
 found   : scala.reflect.Manifest[LEdge[MyStuff]]
 required: Manifest[MyEdge[MyStuff]]
Note: LEdge[MyStuff] >: MyEdge[MyStuff], but trait Manifest is invariant in type T.
You may wish to investigate a wildcard type such as `_ >: MyEdge[MyStuff]`. (SLS 3.2.10)
  val a:Manifest[MyEdge[MyStuff]] = implicitly[Manifest[MyEdge[MyStuff]]]

コンパイラレベルで何が起こっているのですか? ^

4

2 に答える 2

3

As others have suggested the problem comes from

type MyEdge[X] = LEdge[X] { type L1 = SecurityMutatorFactory[X] }

Declarations of the form type F[X] = ... introduce type synonyms, ie new names for existing types. They do not construct new traits or classes. However, LEdge[X] { type L1 = SecurityMutatorFactory[X] } is constructing a new anonymous class. So your example is approximatelly equivalent to

trait MyEdge[X] extends LEdge[X] { type L1 = SecurityMutatorFactory[X] }

(which is what you most probably want) but the original definition in the example is defining a synonym for an anonymous class instead of defining a new class MyEdge[X]. So in the example the new class is not actually called MyEdge. When constructing the implicit manifest, the compiler replaces the type synonym with the underlying type, but fails to construct a manifest for that because that type is anonymous.

Replacing the MyEdge declaration with either a normal extension definition:

trait MyEdge[X] extends LEdge[X] { type L1 = SecurityMutatorFactory[X] }

or with an ordinary type synonym:

type MyEdge[X] = LEdge[X]

both compile successfully.

EDIT

Here is the specific reason why generating implicit manifests for anonymous classes fails. In the language specification type expessions of the form BaseType { ... } are called refined types. According to the language specification, the manifest for a refined type is just the manifest of its base class. This however fails to typecheck, because you asked for a Manifest[LEdge[MyStuff]{ type L1 = SecurityMutatorFactory[X] }], but the algorithm is returning Manifest[LEdge[MyStuff]]. This means that you can only construct implicit manifests for types with refined types only in contravariant positions. For example using:

type MyEdge[X] = LEdge[X] { type L1 = SecurityMutatorFactory[X] } => AnyRef

in your example allows it to compile, though it is clearly not what you are after.

The full algorithm for constructing implicit manifests is given at the end of section 7.5 of the language specification. This question is covered by clause 6:

6) If T is a refined type T'{R}, a manifest is generated for T'. (That is, refinements are never reflected in manifests).

于 2013-09-15T01:47:07.383 に答える
3

まあ、私はそのようなパターンにあまり慣れていません:

type MyEdge[X] = LEdge[X] { type L1 = SecurityMutatorFactory[X]}

しかし、私は実装に関する保証ではなく、typeキーワードで定義された型をエイリアス(概念)と見なす傾向があります (編集より正確にはtype、プロトタイピング/指定に関して保証を提供すると思いますが、実際の型が存在するまで AST/コードは生成されませんエイリアスを、それが基づいている特性/クラスに置き換える必要があります)。そのため、コンパイラがエラー メッセージで次のように主張したとしても、

LEdge[MyStuff] >: MyEdge[MyStuff]

バイトコードレベルでは、MyEdgeインターフェース/メソッド/などを使用して、それに応じて実装されているかどうかはわかりません。したがって、最終的には LEdge と MyEdge の間の必要な関係を認識しない可能性があります。

found   : scala.reflect.Manifest[LEdge[MyStuff]]
required: Manifest[MyEdge[MyStuff]]

(そして、パッケージの不在はscala.reflect.ヒントですか? (1) )

あなたのコードについて、どのように使用しますaか? とにかく、以下があなたの意図であれば、

trait MyEdge[X] extends LEdge[X] {
   type L1 = SecurityMutatorFactory[X]
}

代わりに、コンパイルします(scala 2.10)...(dmitryがすでにそれを言っていることに気づきました)...それが実行時に何をするのか、私にはわかりません!

注意事項として、Manifestscala 2.9 以降では非推奨です。TypeTag[T]そのため、scaladoc で説明されているように使用することをお勧めします。

EDIT:
(1)次のことが起こると思われます:
-構文解析フェーズで、コンパイラは指定したものを文字通り登録します。つまり、implicitlyメソッドManifest[MyEdge[MyStuff]].
- コード生成フェーズまでに、エイリアスは最も近いクラスまたは特性に「調整」されます。implicitly結果の型Manifest[MyEdge[MyStuff]]が traitになる場合scala.reflect.Manifest[LEdge[MyStuff]]]
- 関与する型推論のいくつかの制限と、Manifest型パラメーター内の型「エイリアシング」が原因で、どういうわけか、指定された要件Manifest[MyEdge[MyStuff]]は生の形状のままになります。
- (私はこの回答の Scala コンパイラのソース コードを読んでいないので、これは純粋な推測です) コンパイラは一方で適切な AST/コードを持っていますが、メソッド プロトタイプ/仕様はまだ生/リテラル​​の下にあります。一方、形状。収まらないため、エラーが発生します。

それが役立つことを願って...

于 2013-09-09T17:33:24.953 に答える