I'm exploring the possibilities of scala3's inlining. I've made up a simple example where I want a validation method constructing a sealed class to be applied at compile time:
import scala.compiletime.{ error, codeOf }
sealed abstract class OneOrTwo(val code: String)
object OneOrTwo {
case object One extends OneOrTwo("one")
case object Two extends OneOrTwo("two")
def from(s: String): Option[OneOrTwo] =
s match {
case One.code => Some(One)
case Two.code => Some(Two)
case _ => None
}
inline def inlinedFrom1(s: String): OneOrTwo = {
inline s match {
case "one" => One
case "two" => Two
case _ => error("can't make a OneOrTwo out of " + codeOf(s))
}
}
val test1 = OneOrTwo.inlinedFrom1("one") // compiles
val test12 = OneOrTwo.inlinedFrom1("three") // doesn't compile as expected -> can't make a OneOrTwo out of "three"
}
So far, so good. But what I really want is to be able to re-use the from function within the inlined one. Here's me trying:
// this goes in the OneOrTwo companion object as well
inline def inlinedFrom2(s: String): OneOrTwo = {
from(s).getOrElse(error("can't make a OneOrTwo out of " + codeOf(s)))
}
inline def inlinedFrom3(s: String): OneOrTwo = {
s match {
case One.code => One
case Two.code => Two
case _ => error("can't make a OneOrTwo out of " + codeOf(s))
}
}
val test2 = OneOrTwo.inlinedFrom2("one") // doesn't compile -> can't make a OneOrTwo out of "one"
val test3 = OneOrTwo.inlinedFrom3("one") // doesn't compile -> can't make a OneOrTwo out of "one"
inlinedFrom3 is a generalisation to show that if I match on the objects' code directly, the compiler doesn't see that they are the same as the input string and takes the wrong branch.
What I'd like to understand is why inlinedFrom3 doesn't work and whether there is a way to make it work.
Note: I'm using scala 3.0.0-RC2