scala/scala — pull request #4122 by retronym (2014-11-09 14:10:33+00:00)
Title: SI-7459 Handle pattern binders used as prefixes in TypeTrees.

Match translation was incorrect for:

case t => new t.C
case D(t) => new d.C

We would end up with Types in TypeTrees referring to the wrong
symbols, e.g:

// t7459a.scala
((x0$1: this.LM) => {
case val x1: this.LM = x0$1;
case4(){
matchEnd3(new tttt.Node[Any]())
};
matchEnd3(x: Any){
x
}

Or:
// t7459b.scala
((x0$1: CC) => {
case val x1: CC = x0$1;
case4(){
if (x1.ne(null))
matchEnd3(new tttt.Node[Any]())
else
case5()
};

This commit:

- Changes `bindSubPats` to traverse types, as well as terms,
in search of references to bound symbols
- Changes `Substitution` to reuse `Tree#substituteSymbols` rather
than the home-brew substitution from `Tree`s to `Tree`s, if the
`to` trees are all `Ident`s

I had to dance around the awkward handling of "swatches" (exception
handlers that can be implemented with JVM native type switches) by
duplicating trees to avoid seeing the results of `substituteSymbols`
in `caseDefs` after we abandon that approach if we detect the
patterns are too complex late in the game.

I also had to add an escape hatch for the "type selection from
volatile type" check in the type checker. Without this, the
translation of `pos/t7459c.scala`:

case val x1: _$1 = (null: Test.Mirror[_]).universe;
case5(){
if (x1.isInstanceOf[Test.JavaUniverse])
{
val x2: _$1 with Test.JavaUniverse = (x1.asInstanceOf[_$1 with Test.JavaUniverse]: _$1 with Test.JavaUniverse);
matchEnd4({
val ju1: Test.JavaUniverse = x2;
val f: () => x2.Type = (() => (null: x2.TypeTag[Nothing]).tpe);

.. triggers that error at `x2.TypeTag`.

Review by @adriaanm. I think we can do better for 2.12 as we discussed in #3490.
But we should consider booking this progress.