Почему инициализация объекта вызывает » java.lang.Ошибка проверки: Плохой тип в стеке операндов’?

#scala

Вопрос:

Воспроизводимый Пример:

 object Main extends App {
  val bar = new Bar(None)
  println(bar)
  val foo = Foo.newFoo
  println(foo)
}

trait Foo {
  type A <: Option[String]
}

class Bar[AA <: Option[String]](val a: AA) extends Foo {
  override type A = AA

  override def toString: String = s"Bar(${a})"
}

object Foo {
  def newFoo: Foo = new Bar(None)

  type FullA = Foo { type A = Some[String] }
  def safeGetA[U <: FullA](u: U): String = u match {
    case foo: Bar[_] => foo.a.get
  }
}
 

Результат:

 Bar(None)
Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    Foo$.safeGetA(LFoo;)Ljava/lang/String; @17: invokevirtual
  Reason:
    Type 'scala/runtime/Nothing

Исключение возникает при инициализации объекта Foo  -для появления исключения  safeGetA  необходимо определить метод, но его не нужно вызывать или ссылаться на него. Обратите внимание, что построение a  Bar  завершается успешно, когда его конструктор вызывается напрямую; исключение запускается при первой ссылке на сопутствующий объект  Foo  .

Мой вопрос не только "что здесь происходит", но и "какой синтаксический шаблон вызывает это", чтобы я мог избежать этого в (более сложной) реальной программной среде, где это впервые появилось. (В этом упрощенном примере изменение соответствия подстановочных знаков на конкретный

 case foo: Bar[Some[String]] => foo.a.get
 

не вызывает ошибку, но оставляет String экзистенциальный

 case foo: Bar[Some[_]] => foo.a.get
 

делает. Я понятия не имею, в чем заключается существенная разница.) В частности, каково значение типа scala.runtime.Nothing$ , которое среда выполнения пытается принудить к a Bar , и почему предпринимается попытка такого принуждения?

Существует ряд вопросов SO, содержащих аналогичные ошибки, но ни один из вопросов с принятыми ответами, по-видимому, не воспроизводит проблему здесь.

Комментарии:

1. Какую версию Scala вы используете? Как/где вы запускаете свой код?

2. Воспроизведено на Scala 2.12.11 и 2.13.5, на нескольких JRE (например, 1.8.0_191, 1.8.0_292 и OpenJDK 11.0.9.1 1-после Debian-1deb10u2).

3. Предоставленный вами код не компилируется. Исправьте это, пожалуйста.

4. Ага, ходил туда-сюда между версиями, где Bar был класс case против класса vanilla.

5. Другая точка данных: любая ссылка на Foo запускает инициализацию объекта и ошибку времени выполнения. Scala3 не будет компилировать этот код. Удалите : String как safeGetA() тип возвращаемого значения, и Scala3 скомпилируется и запустится. Скасти

(current frame, stack[0]) is not assignable to 'Bar'
Current Frame:
bci: @17
flags: { }
locals: { 'FooИсключение возникает при инициализации объекта Foo -для появления исключения safeGetA необходимо определить метод, но его не нужно вызывать или ссылаться на него. Обратите внимание, что построение a Bar завершается успешно, когда его конструктор вызывается напрямую; исключение запускается при первой ссылке на сопутствующий объект Foo .

Мой вопрос не только "что здесь происходит", но и "какой синтаксический шаблон вызывает это", чтобы я мог избежать этого в (более сложной) реальной программной среде, где это впервые появилось. (В этом упрощенном примере изменение соответствия подстановочных знаков на конкретный


не вызывает ошибку, но оставляет String экзистенциальный


делает. Я понятия не имею, в чем заключается существенная разница.) В частности, каково значение типа scala.runtime.Nothing$ , которое среда выполнения пытается принудить к a Bar , и почему предпринимается попытка такого принуждения?

Существует ряд вопросов SO, содержащих аналогичные ошибки, но ни один из вопросов с принятыми ответами, по-видимому, не воспроизводит проблему здесь.

Комментарии:

1. Какую версию Scala вы используете? Как/где вы запускаете свой код?

2. Воспроизведено на Scala 2.12.11 и 2.13.5, на нескольких JRE (например, 1.8.0_191, 1.8.0_292 и OpenJDK 11.0.9.1 1-после Debian-1deb10u2).

3. Предоставленный вами код не компилируется. Исправьте это, пожалуйста.

4. Ага, ходил туда-сюда между версиями, где Bar был класс case против класса vanilla.

5. Другая точка данных: любая ссылка на Foo запускает инициализацию объекта и ошибку времени выполнения. Scala3 не будет компилировать этот код. Удалите : String как safeGetA() тип возвращаемого значения, и Scala3 скомпилируется и запустится. Скасти

, 'Foo', top, 'Foo', 'scala/runtime/NothingИсключение возникает при инициализации объекта Foo -для появления исключения safeGetA необходимо определить метод, но его не нужно вызывать или ссылаться на него. Обратите внимание, что построение a Bar завершается успешно, когда его конструктор вызывается напрямую; исключение запускается при первой ссылке на сопутствующий объект Foo .

Мой вопрос не только "что здесь происходит", но и "какой синтаксический шаблон вызывает это", чтобы я мог избежать этого в (более сложной) реальной программной среде, где это впервые появилось. (В этом упрощенном примере изменение соответствия подстановочных знаков на конкретный


не вызывает ошибку, но оставляет String экзистенциальный


делает. Я понятия не имею, в чем заключается существенная разница.) В частности, каково значение типа scala.runtime.Nothing$ , которое среда выполнения пытается принудить к a Bar , и почему предпринимается попытка такого принуждения?

Существует ряд вопросов SO, содержащих аналогичные ошибки, но ни один из вопросов с принятыми ответами, по-видимому, не воспроизводит проблему здесь.

Комментарии:

1. Какую версию Scala вы используете? Как/где вы запускаете свой код?

2. Воспроизведено на Scala 2.12.11 и 2.13.5, на нескольких JRE (например, 1.8.0_191, 1.8.0_292 и OpenJDK 11.0.9.1 1-после Debian-1deb10u2).

3. Предоставленный вами код не компилируется. Исправьте это, пожалуйста.

4. Ага, ходил туда-сюда между версиями, где Bar был класс case против класса vanilla.

5. Другая точка данных: любая ссылка на Foo запускает инициализацию объекта и ошибку времени выполнения. Scala3 не будет компилировать этот код. Удалите : String как safeGetA() тип возвращаемого значения, и Scala3 скомпилируется и запустится. Скасти

}
stack: { 'scala/runtime/NothingИсключение возникает при инициализации объекта Foo -для появления исключения safeGetA необходимо определить метод, но его не нужно вызывать или ссылаться на него. Обратите внимание, что построение a Bar завершается успешно, когда его конструктор вызывается напрямую; исключение запускается при первой ссылке на сопутствующий объект Foo .

Мой вопрос не только "что здесь происходит", но и "какой синтаксический шаблон вызывает это", чтобы я мог избежать этого в (более сложной) реальной программной среде, где это впервые появилось. (В этом упрощенном примере изменение соответствия подстановочных знаков на конкретный


не вызывает ошибку, но оставляет String экзистенциальный


делает. Я понятия не имею, в чем заключается существенная разница.) В частности, каково значение типа scala.runtime.Nothing$ , которое среда выполнения пытается принудить к a Bar , и почему предпринимается попытка такого принуждения?

Существует ряд вопросов SO, содержащих аналогичные ошибки, но ни один из вопросов с принятыми ответами, по-видимому, не воспроизводит проблему здесь.

Комментарии:

1. Какую версию Scala вы используете? Как/где вы запускаете свой код?

2. Воспроизведено на Scala 2.12.11 и 2.13.5, на нескольких JRE (например, 1.8.0_191, 1.8.0_292 и OpenJDK 11.0.9.1 1-после Debian-1deb10u2).

3. Предоставленный вами код не компилируется. Исправьте это, пожалуйста.

4. Ага, ходил туда-сюда между версиями, где Bar был класс case против класса vanilla.

5. Другая точка данных: любая ссылка на Foo запускает инициализацию объекта и ошибку времени выполнения. Scala3 не будет компилировать этот код. Удалите : String как safeGetA() тип возвращаемого значения, и Scala3 скомпилируется и запустится. Скасти

}
Bytecode:
0x0000000: 2b4e 2dc1 0012 9900 1b2d c000 213a 0419
0x0000010: 04b6 0025 c000 27b6 002b c000 2d4d a700
0x0000020: 0fa7 0003 bb00 2f59 2db7 0032 bf2c b0
Stackmap Table:
append_frame(@33,Top,Object[#53])
same_frame(@36)
full_frame(@45,{Object[#2],Object[#53],Object[#45],Object[#53],Object[#33]},{})

at Main$.delayedEndpoint$Main$1(Main.scala:4)
at Main$delayedInit$body.apply(Main.scala:1)
at scala.Function0.apply$mcV$sp(Function0.scala:39)
at scala.Function0.apply$mcV$sp$(Function0.scala:39)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
at scala.App.$anonfun$main$1(App.scala:76)
at scala.App.$anonfun$main$1$adapted(App.scala:76)
at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:563)
at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:561)
at scala.collection.AbstractIterable.foreach(Iterable.scala:919)
at scala.App.main(App.scala:76)
at scala.App.main$(App.scala:74)
at Main$.main(Main.scala:1)
at Main.main(Main.scala)
Исключение возникает при инициализации объекта Foo -для появления исключения safeGetA необходимо определить метод, но его не нужно вызывать или ссылаться на него. Обратите внимание, что построение a Bar завершается успешно, когда его конструктор вызывается напрямую; исключение запускается при первой ссылке на сопутствующий объект Foo .

Мой вопрос не только «что здесь происходит», но и «какой синтаксический шаблон вызывает это», чтобы я мог избежать этого в (более сложной) реальной программной среде, где это впервые появилось. (В этом упрощенном примере изменение соответствия подстановочных знаков на конкретный


не вызывает ошибку, но оставляет String экзистенциальный


делает. Я понятия не имею, в чем заключается существенная разница.) В частности, каково значение типа scala.runtime.Nothing$ , которое среда выполнения пытается принудить к a Bar , и почему предпринимается попытка такого принуждения?

Существует ряд вопросов SO, содержащих аналогичные ошибки, но ни один из вопросов с принятыми ответами, по-видимому, не воспроизводит проблему здесь.

Комментарии:

1. Какую версию Scala вы используете? Как/где вы запускаете свой код?

2. Воспроизведено на Scala 2.12.11 и 2.13.5, на нескольких JRE (например, 1.8.0_191, 1.8.0_292 и OpenJDK 11.0.9.1 1-после Debian-1deb10u2).

3. Предоставленный вами код не компилируется. Исправьте это, пожалуйста.

4. Ага, ходил туда-сюда между версиями, где Bar был класс case против класса vanilla.

5. Другая точка данных: любая ссылка на Foo запускает инициализацию объекта и ошибку времени выполнения. Scala3 не будет компилировать этот код. Удалите : String как safeGetA() тип возвращаемого значения, и Scala3 скомпилируется и запустится. Скасти