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

Time:03-25

Experimenting with Scala 3's metaprogramming capabilities, I found this issue with inline matching that I'm not able to satisfy myself with an explanation for.

Given a transparent inline method eitherTest which takes an inlined Either[String, Int] and then returns either the String or the Int directly using an inline match expression, things work perfectly fine if the input to eitherTest is explicitly typed to a Left or a Right. However, the compiler appears to be unable to reduce the match expression if the input is explicitly typed to the supertype of Either. What makes this more curious is that the argument to eitherTest is itself typed as Either.

Is this a compiler bug? Is this expected behavior? I'm struggling to understand why the compiler would not be able to resolve this.

Scastie link: https://scastie.scala-lang.org/CThqajauRVeJvxvW0uYy4w

Code:

@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

Error:

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]

CodePudding user response:

  val l: Either[String, Int] = Left("hello")
  val r: Either[String, Int] = Right(22)

This explicitly discards type information, leaving the compiler unable to infer what it needs. I believe the transparent relies on type knowledge of passed arguments, rather than "dark type magic" around statically defined values. If you erase the type of the passed arguments, then it is fair to fail right?

  • Related