Symbol visibility in Scala 3 constructors

Why does this code compile in Scala 3?

object Settings {
  def x = 0
}

class Settings(value: Double = x)

Why is the symbol x visible in the constructor parameter list? I guess it must be somehow related to the fact class constructors are closely related to companion objects, but it surprised me. (See 3.6.4 regression - false positive warnings: unused imports · Issue #22690 · scala/scala3 · GitHub)

I’d say this is a bug given:

object Settings {
  def x = 0
}

class Settings{
  val value: Double = x // error: Not found: x
}

But maybe it was done this way since you can’t put an import before the primary constructor ?

Surprising either way !

I believe it’s because of the way default arguments are handled currently. They are translated to default getters in the companion object. I would argue this is a bug. The best way to fix this and many other problems is to change the way we translate default arguments. It’s planned but it’s a challenge to do it in a binary backwards compatibe way.

1 Like

I am not sure how should I write my code to compile without warnings now in 3.6.4 yet stay future proof. If this bug is ever fixed, my code will contain about 30 errors in different classes, as it is quite common in my code the only use of the import like Settings.* is in the constructor to defined default values. I can avoid the warning by being explicit and always using Settings.x, but in constructors with multiple parameters this looks quite ugly.

I have no idea about other projects out in the wild, but given this behavior is common to all Scala 3 versions, I would not be surprised if at lease some projects written in Scala 3 rely upon this behaviour, perhaps unintentionally.