@@ -32,6 +32,7 @@ import dotty.tools.dotc.core.quoted._
32
32
* val x2 = ???
33
33
* ...
34
34
* ~{ ... '{ ... x1 ... x2 ...} ... }
35
+ * ~{ ... /* no references to xi */ ... }
35
36
* ...
36
37
* }
37
38
* ```
@@ -44,6 +45,7 @@ import dotty.tools.dotc.core.quoted._
44
45
* val x2 = ???
45
46
* ...
46
47
* Hole(0 | x1, x2)
48
+ * Hole(1 | )
47
49
* ...
48
50
* ]],
49
51
* List(
@@ -52,7 +54,8 @@ import dotty.tools.dotc.core.quoted._
52
54
* val x2$1 = args(1).asInstanceOf[Expr[T]] // can be asInstanceOf[Type[T]]
53
55
* ...
54
56
* { ... '{ ... x1$1.unary_~ ... x2$1.unary_~ ...} ... }
55
- * }
57
+ * },
58
+ * { ... /* no references to xi */ ... } // optimized to not create lambda
56
59
* )
57
60
* )
58
61
* ```
@@ -66,12 +69,12 @@ import dotty.tools.dotc.core.quoted._
66
69
* ```
67
70
* to
68
71
* ```
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]) => {
70
73
* val T1$1 = args(0).asInstanceOf[Type[T1]]
71
74
* ...
72
- * val x1$1 = args(0 ).asInstanceOf[X]
75
+ * val x1$1 = args(.. ).asInstanceOf[X]
73
76
* ...
74
- * val y1$1 = args(1 ).asInstanceOf[Expr[Y]]
77
+ * val y1$1 = args(.. ).asInstanceOf[Expr[Y]]
75
78
* ...
76
79
* { ... T1$1.unary_~ ... x ... '(y1$1.unary_~) ... }
77
80
* }
@@ -422,6 +425,8 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
422
425
* val y$1 = args(1).asInstanceOf[Expr[Any]] // or .asInstanceOf[Type[Any]]
423
426
* { ... '{ ... x$1.unary_~ ... y$1.unary_~ ... } ... }
424
427
* }
428
+ * or if the spliced subexpression has no captures it will be transformed to
429
+ * { ... '{ ... x$1.unary_~ ... y$1.unary_~ ... } ... }
425
430
*
426
431
* See: `capture`
427
432
*
@@ -434,6 +439,19 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
434
439
* }
435
440
*/
436
441
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
+ }
437
455
def body (arg : Tree )(implicit ctx : Context ): Tree = {
438
456
var i = 0
439
457
transformWithCapturer(tree)(
@@ -461,18 +479,10 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
461
479
val lambdaOwner = ctx.owner.ownersIterator.find(o => levelOf.getOrElse(o, level) == level).get
462
480
val tpe = MethodType (defn.SeqType .appliedTo(defn.AnyType ) :: Nil , tree.tpe.widen)
463
481
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))
466
483
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
476
486
}
477
487
478
488
/** Returns true if this tree will be captured by `makeLambda` */
0 commit comments