@@ -66,16 +66,19 @@ import dotty.tools.dotc.core.quoted._
66
66
* ```
67
67
* to
68
68
* ```
69
- * inline def foo[T1, ...](inline x1: X, ..., y1: Y, .... ): Seq[Any] => Object = { (args: Seq[Any]) => {
69
+ * inline def foo[T1, ...](inline x1: X, ..., y1: Y, ..., inline f1: X => Y ): Seq[Any] => Object = { (args: Seq[Any]) => {
70
70
* val T1$1 = args(0).asInstanceOf[Type[T1]]
71
71
* ...
72
72
* val x1$1 = args(0).asInstanceOf[X]
73
73
* ...
74
74
* val y1$1 = args(1).asInstanceOf[Expr[Y]]
75
75
* ...
76
- * { ... x1$1 .... '{ ... T1$1.unary_~ ... x1$1.toExpr.unary_~ ... y1$1.unary_~ ... } ... }
76
+ * { ... x1$1 .... '{ ... T1$1.unary_~ ... x1$1.toExpr.unary_~ ... y1$1.unary_~ ... f1$1.unary_~ ... } ... }
77
77
* }
78
78
* ```
79
+ * Where `inline` parameters with type Boolean, Byte, Short, Int, Long, Float, Double, Char and String are
80
+ * passed as their actual runtime value. See `isStage0Value`.
81
+ *
79
82
* Note: the parameters of `foo` are kept for simple overloading resolution but they are not used in the body of `foo`.
80
83
*
81
84
* At inline site we will call reflectively the static method `foo` with dummy parameters, which will return a
@@ -243,7 +246,7 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
243
246
def levelOK (sym : Symbol )(implicit ctx : Context ): Boolean = levelOf.get(sym) match {
244
247
case Some (l) =>
245
248
l == level ||
246
- sym.is( Inline ) && sym.owner.is( Macro ) && sym.info.isValueType && l - 1 == level
249
+ l == 1 && level == 0 && isStage0Value(sym)
247
250
case None =>
248
251
! sym.is(Param ) || levelOK(sym.owner)
249
252
}
@@ -374,8 +377,8 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
374
377
else ref(defn.QuotedExpr_apply ).appliedToType(body1.tpe.widen).appliedTo(body1)
375
378
}
376
379
else body match {
377
- case body : RefTree if isCaptured(body, level + 1 ) =>
378
- if (body.symbol.is( Inline )) {
380
+ case body : RefTree if isCaptured(body.symbol , level + 1 ) =>
381
+ if (isStage0Value( body.symbol)) {
379
382
// Optimization: avoid the full conversion when capturing inlined `x`
380
383
// in '{ x } to '{ x$1.toExpr.unary_~ } and go directly to `x$1.toExpr`
381
384
liftValue(capturers(body.symbol)(body))
@@ -476,7 +479,7 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
476
479
val tpw = tree.tpe.widen
477
480
val argTpe =
478
481
if (tree.isType) defn.QuotedTypeType .appliedTo(tpw)
479
- else if (tree.symbol.is( Inline )) tpw // inlined term
482
+ else if (isStage0Value( tree.symbol)) tpw
480
483
else defn.QuotedExprType .appliedTo(tpw)
481
484
val selectArg = arg.select(nme.apply).appliedTo(Literal (Constant (i))).asInstance(argTpe)
482
485
val capturedArg = SyntheticValDef (UniqueName .fresh(tree.symbol.name.toTermName).toTermName, selectArg)
@@ -509,11 +512,11 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
509
512
}
510
513
511
514
/** Returns true if this tree will be captured by `makeLambda` */
512
- private def isCaptured (tree : RefTree , level : Int )(implicit ctx : Context ): Boolean = {
515
+ private def isCaptured (sym : Symbol , level : Int )(implicit ctx : Context ): Boolean = {
513
516
// Check phase consistency and presence of capturer
514
- ( (level == 1 && levelOf.get(tree.symbol ).contains(1 )) ||
515
- (level == 0 && tree.symbol.is( Inline ))
516
- ) && capturers.contains(tree.symbol )
517
+ ( (level == 1 && levelOf.get(sym ).contains(1 )) ||
518
+ (level == 0 && isStage0Value(sym ))
519
+ ) && capturers.contains(sym )
517
520
}
518
521
519
522
/** Transform `tree` and return the resulting tree and all `embedded` quotes
@@ -550,13 +553,13 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
550
553
splice(ref(splicedType).select(tpnme.UNARY_~ ))
551
554
case tree : Select if tree.symbol.isSplice =>
552
555
splice(tree)
553
- case tree : RefTree if isCaptured(tree, level) =>
556
+ case tree : RefTree if isCaptured(tree.symbol , level) =>
554
557
val capturer = capturers(tree.symbol)
555
558
def captureAndSplice (t : Tree ) =
556
559
splice(t.select(if (tree.isTerm) nme.UNARY_~ else tpnme.UNARY_~ ))
557
- if (tree.symbol.is( Inline ) && level == 0 ) capturer(tree)
558
- else if (tree.symbol.is( Inline )) captureAndSplice(liftValue( capturer(tree)) )
559
- else captureAndSplice(capturer(tree))
560
+ if (! isStage0Value( tree.symbol)) captureAndSplice( capturer(tree) )
561
+ else if (level == 0 ) capturer(tree)
562
+ else captureAndSplice(liftValue( capturer(tree) ))
560
563
case Block (stats, _) =>
561
564
val last = enteredSyms
562
565
stats.foreach(markDef)
@@ -604,10 +607,6 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
604
607
""" .stripMargin, tree.rhs.pos)
605
608
EmptyTree
606
609
}
607
- case tree : ValDef if tree.symbol.is(Param | Inline ) && tree.symbol.owner.is(Macro ) &&
608
- defn.isFunctionClass(tree.tpe.widen.typeSymbol) =>
609
- ctx.error(" Macro parameters of function type cannot be `inline`" , tree.pos)
610
- EmptyTree
611
610
case _ =>
612
611
markDef(tree)
613
612
checkLevel(mapOverTree(enteredSyms))
@@ -629,6 +628,9 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
629
628
}
630
629
}
631
630
631
+ private def isStage0Value (sym : Symbol )(implicit ctx : Context ): Boolean =
632
+ sym.is(Inline ) && sym.owner.is(Macro ) && ! defn.isFunctionType(sym.info)
633
+
632
634
private def liftList (list : List [Tree ], tpe : Type )(implicit ctx : Context ): Tree = {
633
635
list.foldRight[Tree ](ref(defn.NilModule )) { (x, acc) =>
634
636
acc.select(" ::" .toTermName).appliedToType(tpe).appliedTo(x)
0 commit comments