@@ -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 * }
@@ -417,6 +420,8 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
417420 * val y$1 = args(1).asInstanceOf[Expr[Any]] // or .asInstanceOf[Type[Any]]
418421 * { ... '{ ... x$1.unary_~ ... y$1.unary_~ ... } ... }
419422 * }
423+ * or if the spliced subexpression has no captures it will be transformed to
424+ * { ... '{ ... x$1.unary_~ ... y$1.unary_~ ... } ... }
420425 *
421426 * See: `capture`
422427 *
@@ -429,6 +434,19 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
429434 * }
430435 */
431436 private def makeLambda (tree : Tree )(implicit ctx : Context ): Tree = {
437+ var treeWithoutCaptures : Tree = null
438+ def transformWithCapturer (tree : Tree )(capturer : mutable.Map [Symbol , Tree ] => Tree => Tree )(implicit ctx : Context ): Tree = {
439+ val captured = mutable.LinkedHashMap .empty[Symbol , Tree ]
440+ val captured2 = capturer(captured)
441+ outer.enteredSyms.foreach(s => capturers.put(s, captured2))
442+ if (ctx.owner.owner.is(Macro ))
443+ outer.enteredSyms.reverse.foreach(s => captured2(ref(s)))
444+ val tree2 = transform(tree)
445+ capturers --= outer.enteredSyms
446+ if (captured.isEmpty)
447+ treeWithoutCaptures = tree2
448+ seq(captured.result().valuesIterator.toList, tree2)
449+ }
432450 def body (arg : Tree )(implicit ctx : Context ): Tree = {
433451 var i = 0
434452 transformWithCapturer(tree)(
@@ -456,18 +474,10 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
456474 val lambdaOwner = ctx.owner.ownersIterator.find(o => levelOf.getOrElse(o, level) == level).get
457475 val tpe = MethodType (defn.SeqType .appliedTo(defn.AnyType ) :: Nil , tree.tpe.widen)
458476 val meth = ctx.newSymbol(lambdaOwner, UniqueName .fresh(nme.ANON_FUN ), Synthetic | Method , tpe)
459- Closure (meth, tss => body(tss.head.head)(ctx.withOwner(meth)).changeOwner(ctx.owner, meth))
460- }
477+ val closure = Closure (meth, tss => body(tss.head.head)(ctx.withOwner(meth)).changeOwner(ctx.owner, meth))
461478
462- private def transformWithCapturer (tree : Tree )(capturer : mutable.Map [Symbol , Tree ] => Tree => Tree )(implicit ctx : Context ): Tree = {
463- val captured = mutable.LinkedHashMap .empty[Symbol , Tree ]
464- val captured2 = capturer(captured)
465- outer.enteredSyms.foreach(s => capturers.put(s, captured2))
466- if (ctx.owner.owner.is(Macro ))
467- outer.enteredSyms.reverse.foreach(s => captured2(ref(s)))
468- val tree2 = transform(tree)
469- capturers --= outer.enteredSyms
470- seq(captured.result().valuesIterator.toList, tree2)
479+ if (treeWithoutCaptures == null || ctx.owner.is(Macro )) closure
480+ else treeWithoutCaptures
471481 }
472482
473483 /** Returns true if this tree will be captured by `makeLambda` */
0 commit comments