@@ -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