Dotty: Wildcard export ignores synthetic members generated from desugaring

Created on 18 Dec 2020  路  6Comments  路  Source: lampepfl/dotty

Minimized code

Up-to Scala 3.0.0-M2, a wildcard export worked as expected: ALL members were exported, both singleton members as class case members:

object T:
  enum Command:
    case ResetSudokuDetailState
    case Update(cellUpdates: Int)
    case GetSudokuDetailState(z:Int)
  export Command._

val update = T.Update(cellUpdates = 5)

In Scala 3.0.0-M3, the above code exports ResetSudokuDetailState, but not Update and GetSudokuDetailState.

The workaround is to export all members explicitly:

object T:
  enum Command:
    case ResetSudokuDetailState
    case Update(cellUpdates: Int)
    case GetSudokuDetailState(z:Int)
  export Command.{ResetSudokuDetailState, Update, GetSudokuDetailState}

val update = T.Update(cellUpdates = 5)

Output

scala> object T:
     |   enum Command:
     |     case ResetSudokuDetailState
     |     case Update(cellUpdates: Int)
     |     case GetSudokuDetailState(z:Int)
     |   export Command._
     |
     | val update = T.Update(cellUpdates = 5)
8 |val update = T.Update(cellUpdates = 5)
  |             ^^^^^^^^
  |             value Update is not a member of object T

Expectation

Doing a wildcard export on an enum should export _all_ members

bug

Most helpful comment

@bishabosha Yes, I think that could work. I.e. if one of a pair of type/term definitions with the same name is non-synthatic, the other is imported as well.

All 6 comments

I think this may have something to do with creator application changes, if you take a look suing -Xprint:typer cli option, the companion objects of enum cases were never exported, (I checked back to 0.25.0), just type aliases, so T.Update(cellUpdates = 5) was actually a creator application and not calling T.Update.apply.

more bad news, it seems you cant wildcard export definitions that are added after desugaring:

object T:
  object Command:
    case class Update(cellUpdates: Int)
  export Command._

in this example the synthetic companion object for Update is also not exported.

Will need to investigate if this is a fundamental issue with export desugaring at Namer or if there are just missing wildcard definitions being ignored

more bad news, it seems you cant wildcard export definitions that are added after desugaring

That's a pity... Using export to export all members of an enum makes it possible to take Scala 2 ADTs encoded with sealed traits; trivially encode them as Scala 3 enum's and leave any code that uses them unmodified.
Not having this work as it [accidentally] did prior to M3 means that code has to be changed at the use site.

It's a conscious decision not to export synthetic members. One positive aspect of this is that you can export all cases from an enum without also exporting the synthetic values etc machinery. I think we will stick to that.

@odersky would it be desirable to treat the non-(private/synthetic) symbols as names that can then be reinterpreted as an explicit selector, which would then pick up the companion object of case classes?

@bishabosha Yes, I think that could work. I.e. if one of a pair of type/term definitions with the same name is non-synthatic, the other is imported as well.

Was this page helpful?
0 / 5 - 0 ratings