scala3 のインライン化の可能性を探っています。シールされたクラスを構築する検証メソッドをコンパイル時に適用する簡単な例を作成しました。
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"
}
ここまでは順調ですね。しかし、私が本当に望んでいるのはfrom
、インライン化された関数内で関数を再利用できるようにすることです。これが私が試していることです:
// 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
オブジェクトのコードを直接照合すると、コンパイラはそれらが入力文字列と同じであることを認識せず、間違った分岐を取ることを示す一般化です。
私が理解したいのは、なぜinlinedFrom3
機能しないのか、機能させる方法があるのか ということです。
注:私はscala 3.0.0-RC2を使用しています