New desugaring behavior in Scala 2.10.1

2020-05-30 03:22发布

Suppose I have this monadic class:

case class Foo[A](xs: List[A]) {
  def map[B](f: A => B) = Foo(xs map f)
  def flatMap[B](f: A => Foo[B]) = Foo(xs flatMap f.andThen(_.xs))
  def withFilter(p: A => Boolean) = {
    println("Filtering!")
    Foo(xs filter p)
  }
}

The following is from a 2.10.0 REPL session:

scala> for { (a, b) <- Foo(List(1 -> "x")) } yield a
res0: Foo[Int] = Foo(List(1))

And here's the same thing in 2.10.1:

scala> for { (a, b) <- Foo(List(1 -> "x")) } yield a
Filtering!
res0: Foo[Int] = Foo(List(1))

This is completely unexpected (to me), and leads to particularly confusing errors in cases where filtering requires additional constraints (such as Scalaz's \/ or EitherT).

I wasn't able to find any discussion of this change in the 2.10.1 release notes. Can someone point out where and why this new desugaring behavior was introduced?

1条回答
一纸荒年 Trace。
2楼-- · 2020-05-30 04:05

The story is more complex than that, and it's in fact a 2.10.0 regression that was plugged there.

The "no-withFilter" behavior was introduced in c82ecab, and because of things like SI-6968, this was reverted partially #1893. Further adaptations followed (SI-6646, SI-7183)

The takeaway sentence you're looking for is :

The parser can't assume that a pattern (a, b) will match, as results of .isInstanceOf[Tuple2] can't be statically known until after the typer.

查看更多
登录 后发表回答