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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With