странная ошибка компиляции с экзистенциалами scala с ограниченным полиморфизмом f

Почему приведенный ниже код не компилируется?

  trait B[T <: B[T]]
  case class A[T <: B[T]](t: T)

  class C() extends B[C]
  val c: C = new C()

  val r2: A[_]         = A(c)     //compiles
  val r3: A[_]         = A(c)     //compiles fine
  val r4: A[_]         = r3       //compiles fine
  val r5: (A[_])       = (r3)     //compiles fine
  val r6: (A[_], A[_]) = (r3, r3) // does not compile, strange

Это дает:

Error:(68, 22) type arguments [_$7] do not conform to class A's type parameter bounds [T <: _experiment.akka_persistence.Test2.B[T]]
  val r6:(A[_],A[_])=(r3,r3)

РЕДАКТИРОВАТЬ:

Вот связанный автономный фрагмент кода:

  import scala.language.existentials


  trait B[T <: B[T]]
  case class A[T <: B[T]](t: T)

  class C() extends B[C]
  val c: C = new C()
  type SomeB = T forSome { type T <: B[T] }
  val r3: A[_<:SomeB]         = A(c)     //compiles fine
  val r4: A[C]         = A(c)     //compiles fine
  val r5: (A[_<:SomeB])       = (r3)     //compiles fine
  val r6:((_<:SomeB),((_<:SomeB))) = (c,c)  // compiles fine
  val r7:(A[_<:SomeB],((_<:SomeB))) = (A(c),c)  // compiles fine
  val r8:(A[_<:SomeB],(A[_<:SomeB])) = (A(c),A(c))  // compiles fine
  val r10:(A[_<:SomeB],(A[_<:SomeB])) = (A(c),r4)  // compiles fine
  val r9:(A[_<:SomeB],(A[_<:SomeB])) = (A(c),r3)  // does not compile
  • Кажется, что r4 должен иметь тип A[C], а затем компилируется r10.
  • Таким образом, это говорит о том, что A[_<:SomeB] вместо r3 недостаточно конкретно. Но почему нет ?
  • Кроме того, почему A[_<:SomeB] достаточно для val r5: (A[_<:SomeB]) = (r3), но не для r9?

person jhegedus    schedule 05.05.2017    source источник
comment
хммм, это кажется немного актуальным: stackoverflow.com/questions/28674486/   -  person jhegedus    schedule 05.05.2017
comment
Похоже очередной баг. Ваш первый фрагмент кода прекрасно компилируется с dotty/master.   -  person OlivierBlanvillain    schedule 05.05.2017
comment
Хм.... странно... мне начать использовать dotty ? :)   -  person jhegedus    schedule 05.05.2017
comment
Должен ли я отправить отчет об ошибке?   -  person jhegedus    schedule 05.05.2017
comment
Вы можете получить лучший ответ, сообщив о проблеме, чем здесь, на SO...   -  person OlivierBlanvillain    schedule 05.05.2017
comment
Да я так и не понял, баг это или что...   -  person jhegedus    schedule 05.05.2017


Ответы (1)


Прежде всего, ваши r4 и r5 на самом деле эквивалентны. Чтобы объявить val типа Tuple1, вам нужно явно указать:

val r5: Tuple1[A[_]] = Tuple1(r3)

И тогда вы обнаружите, что он также терпит неудачу с той же ошибкой.

В РЕПЛ:

scala> Tuple1(r3)
<console>:24: warning: inferred existential type (A[_$1],) forSome { type _$1 }, which cannot be expressed by wildcards,  should be enabled
by making the implicit value scala.language.existentials visible.
This can be achieved by adding the import clause 'import scala.language.existentials'
or by setting the compiler option -language:existentials.
See the Scaladoc for value scala.language.existentials for a discussion
why the feature should be explicitly enabled.
       Tuple1(r3)
             ^
<console>:24: error: type arguments [_$1] do not conform to class A's type parameter bounds [T <: B[T]]
       Tuple1(r3)
       ^

Вы видите, что с учетом экзистенциального типизированного r3 компилятор вывел кортеж как (A[_$1],) forSome { type _$1 }.

Этот случай действительно похож на случай из @jhegedus (Экзистенциальные типы для F-ограниченных полиморфных типов и необобщенных подтипов?), и применяется то же решение, т.е. дайте компилятору некоторую помощь, явно указав параметр типа Tuple1:

val r5 = Tuple1[A[_]](r3)

Или дайте r3 более конкретный тип:

val r3: A[C] = A(c)
val r5: Tuple1[A[_]] = Tuple1(r3)

И то же самое касается r6 / Tuple2

person PH88    schedule 05.05.2017