Skip to content

Commit e871cb5

Browse files
authored
Merge pull request #4211 from dotty-staging/optimize-splices-without-captures
Optimize splices without captures
2 parents ce7246f + bf13d5b commit e871cb5

File tree

2 files changed

+31
-17
lines changed

2 files changed

+31
-17
lines changed

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,10 +1142,14 @@ class TreeUnpickler(reader: TastyReader,
11421142
val splice = splices(idx)
11431143
val reifiedArgs = args.map(arg => if (arg.isTerm) new TreeExpr(arg) else new TreeType(arg))
11441144
if (isType) {
1145-
val quotedType = splice.asInstanceOf[Seq[Any] => quoted.Type[_]](reifiedArgs)
1145+
val quotedType =
1146+
if (reifiedArgs.isEmpty) splice.asInstanceOf[quoted.Type[_]]
1147+
else splice.asInstanceOf[Seq[Any] => quoted.Type[_]](reifiedArgs)
11461148
PickledQuotes.quotedTypeToTree(quotedType)
11471149
} else {
1148-
val quotedExpr = splice.asInstanceOf[Seq[Any] => quoted.Expr[_]](reifiedArgs)
1150+
val quotedExpr =
1151+
if (reifiedArgs.isEmpty) splice.asInstanceOf[quoted.Expr[_]]
1152+
else splice.asInstanceOf[Seq[Any] => quoted.Expr[_]](reifiedArgs)
11491153
PickledQuotes.quotedExprToTree(quotedExpr)
11501154
}
11511155
}

compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import dotty.tools.dotc.core.quoted._
3232
* val x2 = ???
3333
* ...
3434
* ~{ ... '{ ... x1 ... x2 ...} ... }
35+
* ~{ ... /* no references to xi */ ... }
3536
* ...
3637
* }
3738
* ```
@@ -44,6 +45,7 @@ import dotty.tools.dotc.core.quoted._
4445
* val x2 = ???
4546
* ...
4647
* Hole(0 | x1, x2)
48+
* Hole(1 | )
4749
* ...
4850
* ]],
4951
* List(
@@ -52,7 +54,8 @@ import dotty.tools.dotc.core.quoted._
5254
* val x2$1 = args(1).asInstanceOf[Expr[T]] // can be asInstanceOf[Type[T]]
5355
* ...
5456
* { ... '{ ... x1$1.unary_~ ... x2$1.unary_~ ...} ... }
55-
* }
57+
* },
58+
* { ... /* no references to xi */ ... } // optimized to not create lambda
5659
* )
5760
* )
5861
* ```
@@ -66,12 +69,12 @@ import dotty.tools.dotc.core.quoted._
6669
* ```
6770
* to
6871
* ```
69-
* inline def foo[T1, ...](inline x1: X, ..., y1: Y, ....): Seq[Any] => Object = { (args: Seq[Any]) => {
72+
* inline def foo[T1, ...](inline x1: X, ..., y1: Y, ....): Object = { (args: Seq[Any]) => {
7073
* val T1$1 = args(0).asInstanceOf[Type[T1]]
7174
* ...
72-
* val x1$1 = args(0).asInstanceOf[X]
75+
* val x1$1 = args(..).asInstanceOf[X]
7376
* ...
74-
* val y1$1 = args(1).asInstanceOf[Expr[Y]]
77+
* val y1$1 = args(..).asInstanceOf[Expr[Y]]
7578
* ...
7679
* { ... T1$1.unary_~ ... x ... '(y1$1.unary_~) ... }
7780
* }
@@ -422,6 +425,8 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
422425
* val y$1 = args(1).asInstanceOf[Expr[Any]] // or .asInstanceOf[Type[Any]]
423426
* { ... '{ ... x$1.unary_~ ... y$1.unary_~ ... } ... }
424427
* }
428+
* or if the spliced subexpression has no captures it will be transformed to
429+
* { ... '{ ... x$1.unary_~ ... y$1.unary_~ ... } ... }
425430
*
426431
* See: `capture`
427432
*
@@ -434,6 +439,19 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
434439
* }
435440
*/
436441
private def makeLambda(tree: Tree)(implicit ctx: Context): Tree = {
442+
var treeWithoutCaptures: Tree = null
443+
def transformWithCapturer(tree: Tree)(capturer: mutable.Map[Symbol, Tree] => Tree => Tree)(implicit ctx: Context): Tree = {
444+
val captured = mutable.LinkedHashMap.empty[Symbol, Tree]
445+
val captured2 = capturer(captured)
446+
outer.enteredSyms.foreach(s => capturers.put(s, captured2))
447+
if (ctx.owner.owner.is(Macro))
448+
outer.enteredSyms.reverse.foreach(s => captured2(ref(s)))
449+
val tree2 = transform(tree)
450+
capturers --= outer.enteredSyms
451+
if (captured.isEmpty)
452+
treeWithoutCaptures = tree2
453+
seq(captured.result().valuesIterator.toList, tree2)
454+
}
437455
def body(arg: Tree)(implicit ctx: Context): Tree = {
438456
var i = 0
439457
transformWithCapturer(tree)(
@@ -461,18 +479,10 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
461479
val lambdaOwner = ctx.owner.ownersIterator.find(o => levelOf.getOrElse(o, level) == level).get
462480
val tpe = MethodType(defn.SeqType.appliedTo(defn.AnyType) :: Nil, tree.tpe.widen)
463481
val meth = ctx.newSymbol(lambdaOwner, UniqueName.fresh(nme.ANON_FUN), Synthetic | Method, tpe)
464-
Closure(meth, tss => body(tss.head.head)(ctx.withOwner(meth)).changeOwner(ctx.owner, meth))
465-
}
482+
val closure = Closure(meth, tss => body(tss.head.head)(ctx.withOwner(meth)).changeOwner(ctx.owner, meth))
466483

467-
private def transformWithCapturer(tree: Tree)(capturer: mutable.Map[Symbol, Tree] => Tree => Tree)(implicit ctx: Context): Tree = {
468-
val captured = mutable.LinkedHashMap.empty[Symbol, Tree]
469-
val captured2 = capturer(captured)
470-
outer.enteredSyms.foreach(s => capturers.put(s, captured2))
471-
if (ctx.owner.owner.is(Macro))
472-
outer.enteredSyms.reverse.foreach(s => captured2(ref(s)))
473-
val tree2 = transform(tree)
474-
capturers --= outer.enteredSyms
475-
seq(captured.result().valuesIterator.toList, tree2)
484+
if (treeWithoutCaptures == null || ctx.owner.is(Macro)) closure
485+
else treeWithoutCaptures
476486
}
477487

478488
/** Returns true if this tree will be captured by `makeLambda` */

0 commit comments

Comments
 (0)