scala/scala — pull request #4164 by retronym (2014-11-26 05:41:06+00:00)
Title: SI-9003 Eagerly capture more potentially mutable binders

This is a re-run of SI-5158 in two different contexts.

As reported, the result of `unapply[Seq]` under name based pattern
matching might not guarantee stability of results of calls to
`_1`, `apply(i)`, etc, so we call these eagerly, and call them
once only.

I also found a case in regular pattern matching that we hadn't
accounted for: extracting elements of sequences (either from
a case class or from an `unapplySeq`) may also be unstable.

This commit changes `ExtractorTreeMaker` to force storage
of such binders, even under `-optimize`. This parallels the change
to `ProductExtractorTreeMaker` in 8ebe8e3e8.

I have added a special case for traditional `unapply` methods
returning `Option`. This avoids a change for:

```
% cat test/files/run/t9003b.scala
object Single {
def unapply(a: Any) = Some("")
}

object Test {
def main(args: Array[String]): Unit = {
"" match {
case Single(x) =>
(x, x)
}
}
}
% qscalac -optimize -Xprint:patmat test/files/run/t9003b.scala 2>&1 | grep --context=5 get
case val x1: Any = "";
case5(){
val o7: Some[String] = Single.unapply(x1);
if (o7.isEmpty.unary_!)
matchEnd4({
scala.Tuple2.apply[String, String](o7.get, o7.get);
()
})
else
case6()
};
% scalac-hash v2.11.4 -optimize -Xprint:patmat test/files/run/t9003b.scala 2>&1 | grep --context=5 get
case val x1: Any = "";
case5(){
val o7: Some[String] = Single.unapply(x1);
if (o7.isEmpty.unary_!)
matchEnd4({
scala.Tuple2.apply[String, String](o7.get, o7.get);
()
})
else
case6()
};
```

Review by @adriaanm