diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-09-23 10:35:43 +0200 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-09-23 10:42:48 +0200 |
commit | 16d963bcb032deb669247e4a95c6391971cafd75 (patch) | |
tree | f2dd541f9345d2624069c097d18ae1e8509c87a2 | |
parent | 65817bd2b71f5ea0e39af1b1c2b085562cd8e925 (diff) | |
download | scala-16d963bcb032deb669247e4a95c6391971cafd75.tar.gz scala-16d963bcb032deb669247e4a95c6391971cafd75.tar.bz2 scala-16d963bcb032deb669247e4a95c6391971cafd75.zip |
SI-7868 Account for numeric widening in match translation
Pattern match translation was unprepared for trees of the shape:
(0: Short) match {
case A.unapply(<unapply-selector>.toInt) <unapply> (_) => ()
case _ => ()
}
While a scrutinee is inelibigle for implicit views in order to
conform to the type of the extractor call, it is allowed to
weakly conform. In this case, the typechecker will add the
numeric widening with a `toInt` call.
This commit:
- Changes treeInfo.Unapplied to recognize this tree shape
- Changes spliceApply to recognize and preserve the widening
when substituting the unapply selector with the binder
- Tests reification of such pattern matches, which also depends
on treeInfo.Unapplied.
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala | 8 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/TreeInfo.scala | 9 | ||||
-rw-r--r-- | test/files/run/t7868.scala | 13 | ||||
-rw-r--r-- | test/files/run/t7868b.check | 6 | ||||
-rw-r--r-- | test/files/run/t7868b.scala | 11 |
5 files changed, 43 insertions, 4 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala index 75335f7920..ab19660da5 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala @@ -600,9 +600,15 @@ trait MatchTranslation { protected def spliceApply(binder: Symbol): Tree = { object splice extends Transformer { + def binderRef(pos: Position): Tree = + REF(binder) setPos pos override def transform(t: Tree) = t match { + // duplicated with the extractor Unapplied case Apply(x, List(i @ Ident(nme.SELECTOR_DUMMY))) => - treeCopy.Apply(t, x, (REF(binder) setPos i.pos) :: Nil) + treeCopy.Apply(t, x, binderRef(i.pos) :: Nil) + // SI-7868 Account for numeric widening, e.g. <unappplySelector>.toInt + case Apply(x, List(i @ (sel @ Select(Ident(nme.SELECTOR_DUMMY), name)))) => + treeCopy.Apply(t, x, treeCopy.Select(sel, binderRef(i.pos), name) :: Nil) case _ => super.transform(t) } diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index 1b763b8632..ab7506e657 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -784,10 +784,13 @@ abstract class TreeInfo { * unapply (unwrapping nested Applies) and returns the fun part of that Apply. */ object Unapplied { + // Duplicated with `spliceApply` def unapply(tree: Tree): Option[Tree] = tree match { - case Apply(fun, Ident(nme.SELECTOR_DUMMY) :: Nil) => Some(fun) - case Apply(fun, _) => unapply(fun) - case _ => None + // SI-7868 Admit Select() to account for numeric widening, e.g. <unappplySelector>.toInt + case Apply(fun, (Ident(nme.SELECTOR_DUMMY)| Select(Ident(nme.SELECTOR_DUMMY), _)) :: Nil) + => Some(fun) + case Apply(fun, _) => unapply(fun) + case _ => None } } diff --git a/test/files/run/t7868.scala b/test/files/run/t7868.scala new file mode 100644 index 0000000000..1f938adf31 --- /dev/null +++ b/test/files/run/t7868.scala @@ -0,0 +1,13 @@ +object A { + def unapply(n: Int): Option[Int] = Some(n) + + def run = (0: Short) match { + case A(_) => + case _ => + } +} + + +object Test extends App { + A.run +} diff --git a/test/files/run/t7868b.check b/test/files/run/t7868b.check new file mode 100644 index 0000000000..6577c4bc4e --- /dev/null +++ b/test/files/run/t7868b.check @@ -0,0 +1,6 @@ +Expr[Int]({ + val x = (0: Short): @unchecked match { + case A((x @ _)) => x + }; + x +}) diff --git a/test/files/run/t7868b.scala b/test/files/run/t7868b.scala new file mode 100644 index 0000000000..759eeaf862 --- /dev/null +++ b/test/files/run/t7868b.scala @@ -0,0 +1,11 @@ +object A { + def unapply(n: Int): Option[Int] = Some(1) +} + +object Test extends App { + import reflect.runtime.universe._ + println(reify { + val A(x) = (0: Short) + x + }) +} |