#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 скомпилируется и запустится. Скасти