在此示例中,为什么 Scala 3 无法减少对 Either 的内联匹配?

Why does Scala 3 fail to reduce an inline match over Either in this example?

在试验 Scala 3 的元编程功能时,我发现了这个内联匹配问题,我无法解释清楚。

给定一个透明内联方法 eitherTest,它采用内联 Either[String, Int] 然后 returns StringInt 直接使用内联匹配表达式,如果将 eitherTest 的输入显式键入 LeftRight,则一切正常。但是,如果输入被显式键入 Either 的超类型,编译器似乎无法减少匹配表达式。更奇怪的是 eitherTest 的参数本身被键入为 Either.

这是编译器错误吗?这是预期的行为吗?我很难理解为什么编译器无法解决这个问题。

斯卡斯蒂 link: https://scastie.scala-lang.org/CThqajauRVeJvxvW0uYy4w

代码:

@main def hello: Unit =
  workingTest
  failingTest


def workingTest: Unit =
  val l: Left[String, Int] = Left("hello")
  val r: Right[String, Int] = Right(22)
  val tl: String = eitherTest(l)
  val tr: Int = eitherTest(r)
  println(s"$tl :: $tr")

def failingTest: Unit =
  val l: Either[String, Int] = Left("hello")
  val r: Either[String, Int] = Right(22)
  val tl: String = eitherTest(l)
  val tr: Int = eitherTest(r)
  println(s"$tl :: $tr")

transparent inline def eitherTest(inline v: Either[String, Int]): Any =
  inline v match
    case Right(a) => a
    case Left(b) => b

错误:

cannot reduce inline match with
 scrutinee:  l : (l : Either[String, Int])
 patterns :  case Right.unapply[String, Int](a @ _):Right[String, Int]
             case Left.unapply[String, Int](b @ _):Left[String, Int]
  val l: Either[String, Int] = Left("hello")
  val r: Either[String, Int] = Right(22)

这会显式丢弃类型信息,使编译器无法推断出它需要什么。我相信 transparent 依赖于传递参数的类型知识,而不是围绕静态定义值的“暗类型魔法”。如果你擦除传递参数的类型,那么失败是公平的吗?