Enum + val + extension = init exception

This is probably a known thing, is it a bug?
Here is a Scastie

(If it looks too artificial, I do have a valid use case in today’s Advent of Code puzzle and I ran into this.)

lazy sorts it out. Maybe a clue to what the compiler is up to.

enum Spam:
  case Ham
  lazy val x = this match // lazy fixes the error
    case Ham => 0

extension (s: String)
  def toSpam = s match
    case "HAM" => Spam.Ham

"HAM".toSpam
2 Likes

Ah! The one time I didn’t use lazy val :woman_facepalming: :laughing:
I use it all the time normally.

1 Like

Use -Ysafe-init-global to see the warning.

per scastie

5 |    case Ham => 0
  |         ^^^
  |         Access uninitialized field value Ham. Calling trace:
  |         ├── enum Spam:      [ ham.scala:2 ]
  |         │   ^
  |         ├── case Ham        [ ham.scala:3 ]
  |         │   ^
  |         ├── enum Spam:      [ ham.scala:2 ]
  |         │   ^
  |         └── case Ham => 0   [ ham.scala:5 ]
  |                  ^^^
1 warning found

There is a suggestion to always warn at the ticket on this behavior.

There was a similar question in chat where the example matches this enum and throws; I assume it was some sort of init order problem, but difficult to guess from the snippet.

If it always warned for weird enums, pardon the expression, it would be a great help to everyone.

By “weird”, I mean the way it is desugared to the companion module.

Now that they’re fixing “for comprehension desugaring”, perhaps enum desugaring will next come under scrutiny.

1 Like