From 913c37452a341a7830d4ce7782bf014cf77f5906 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 26 Apr 2019 11:58:51 +0200 Subject: [PATCH] Inline idempotent singletons on quoted function beta-reduction --- .../tools/dotc/core/quoted/PickledQuotes.scala | 16 ++++++++++------ tests/run-with-compiler/i3876-b.check | 3 +-- tests/run-with-compiler/i3876-c.check | 3 +-- tests/run-with-compiler/i3876-d.check | 5 +---- tests/run-with-compiler/i3876-e.check | 9 +++++++++ tests/run-with-compiler/i3876-e.scala | 16 ++++++++++++++++ tests/run-with-compiler/i3876.check | 5 +---- tests/run-with-compiler/i5144b.check | 5 +---- 8 files changed, 40 insertions(+), 22 deletions(-) create mode 100644 tests/run-with-compiler/i3876-e.check create mode 100644 tests/run-with-compiler/i3876-e.scala diff --git a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala index a3e83220f91f..19e8f23e6ae0 100644 --- a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala +++ b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala @@ -10,7 +10,7 @@ import dotty.tools.dotc.core.StdNames._ import dotty.tools.dotc.core.NameKinds import dotty.tools.dotc.core.Mode import dotty.tools.dotc.core.Symbols._ -import dotty.tools.dotc.core.Types.Type +import dotty.tools.dotc.core.Types._ import dotty.tools.dotc.core.tasty.TreePickler.Hole import dotty.tools.dotc.core.tasty.{PositionPickler, TastyPickler, TastyPrinter, TastyString} import dotty.tools.dotc.core.tasty.TreeUnpickler.UnpickleMode @@ -128,15 +128,19 @@ object PickledQuotes { } private def functionAppliedTo(fn: Tree, args: List[Tree])(implicit ctx: Context): Tree = { - val argVals = args.map(arg => SyntheticValDef(NameKinds.UniqueName.fresh("x".toTermName), arg).withSpan(arg.span)) - def argRefs() = argVals.map(argVal => ref(argVal.symbol)) + val (argVals, argRefs) = args.map(arg => arg.tpe match { + case tpe: SingletonType if isIdempotentExpr(arg) => (Nil, arg) + case _ => + val argVal = SyntheticValDef(NameKinds.UniqueName.fresh("x".toTermName), arg).withSpan(arg.span) + (argVal :: Nil, ref(argVal.symbol)) + }).unzip def rec(fn: Tree): Tree = fn match { case Inlined(call, bindings, expansion) => // this case must go before closureDef to avoid dropping the inline node cpy.Inlined(fn)(call, bindings, rec(expansion)) case closureDef(ddef) => val paramSyms = ddef.vparamss.head.map(param => param.symbol) - val paramToVals = paramSyms.zip(argRefs()).toMap + val paramToVals = paramSyms.zip(argRefs).toMap new TreeTypeMap( oldOwners = ddef.symbol :: Nil, newOwners = ctx.owner :: Nil, @@ -145,9 +149,9 @@ object PickledQuotes { case Block(stats, expr) => seq(stats, rec(expr)).withSpan(fn.span) case _ => - fn.select(nme.apply).appliedToArgs(argRefs()).withSpan(fn.span) + fn.select(nme.apply).appliedToArgs(argRefs).withSpan(fn.span) } - Block(argVals, rec(fn)) + seq(argVals.flatten, rec(fn)) } private def classToType(clazz: Class[_])(implicit ctx: Context): Type = { diff --git a/tests/run-with-compiler/i3876-b.check b/tests/run-with-compiler/i3876-b.check index 7746fc33aaf4..fd12093e338e 100644 --- a/tests/run-with-compiler/i3876-b.check +++ b/tests/run-with-compiler/i3876-b.check @@ -1,6 +1,5 @@ 6 { - val x$1: scala.Int = 3 def f(x: scala.Int): scala.Int = x.+(x) - f(x$1) + f(3) } diff --git a/tests/run-with-compiler/i3876-c.check b/tests/run-with-compiler/i3876-c.check index bd419b41bf11..dca23bcfdf11 100644 --- a/tests/run-with-compiler/i3876-c.check +++ b/tests/run-with-compiler/i3876-c.check @@ -1,11 +1,10 @@ 6 { - val x$1: scala.Int = 3 val f: scala.Function1[scala.Int, scala.Int] { def apply(x: scala.Int): scala.Int } = ((x: scala.Int) => x.+(x)) (f: scala.Function1[scala.Int, scala.Int] { def apply(x: scala.Int): scala.Int - }).apply(x$1) + }).apply(3) } diff --git a/tests/run-with-compiler/i3876-d.check b/tests/run-with-compiler/i3876-d.check index 746b7f8778a7..43d6d4ec0aca 100644 --- a/tests/run-with-compiler/i3876-d.check +++ b/tests/run-with-compiler/i3876-d.check @@ -1,5 +1,2 @@ 6 -{ - val x$1: scala.Int = 3 - x$1.+(x$1) -} +3.+(3) diff --git a/tests/run-with-compiler/i3876-e.check b/tests/run-with-compiler/i3876-e.check new file mode 100644 index 000000000000..13627ce396d6 --- /dev/null +++ b/tests/run-with-compiler/i3876-e.check @@ -0,0 +1,9 @@ + +6 +{ + val x$1: scala.Int = { + scala.Predef.println() + 3 + } + x$1.+(x$1) +} diff --git a/tests/run-with-compiler/i3876-e.scala b/tests/run-with-compiler/i3876-e.scala new file mode 100644 index 000000000000..143b2d817963 --- /dev/null +++ b/tests/run-with-compiler/i3876-e.scala @@ -0,0 +1,16 @@ +import scala.quoted._ +object Test { + def main(args: Array[String]): Unit = { + implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader) + + val x: Expr[Int] = '{ println(); 3 } + + val f4: Expr[Int => Int] = '{ + inlineLambda + } + println(f4(x).run) + println(f4(x).show) + } + + inline def inlineLambda <: Int => Int = x => x + x +} \ No newline at end of file diff --git a/tests/run-with-compiler/i3876.check b/tests/run-with-compiler/i3876.check index 746b7f8778a7..43d6d4ec0aca 100644 --- a/tests/run-with-compiler/i3876.check +++ b/tests/run-with-compiler/i3876.check @@ -1,5 +1,2 @@ 6 -{ - val x$1: scala.Int = 3 - x$1.+(x$1) -} +3.+(3) diff --git a/tests/run-with-compiler/i5144b.check b/tests/run-with-compiler/i5144b.check index 5e736e0c2575..8b68228399c5 100644 --- a/tests/run-with-compiler/i5144b.check +++ b/tests/run-with-compiler/i5144b.check @@ -1,7 +1,4 @@ { - def f(x: scala.Int): scala.Int = { - val x$1: scala.Int = 42 - f(x$1) - } + def f(x: scala.Int): scala.Int = f(42) () }