Skip to content

Commit 4fdc844

Browse files
committed
Cleanup macro PCP checks
1 parent dd21107 commit 4fdc844

File tree

4 files changed

+55
-53
lines changed

4 files changed

+55
-53
lines changed

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

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ object Staging {
8888

8989
class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(ictx) {
9090
import tpd._
91-
import PCPCheckAndHeal._
9291

9392
override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
9493
case tree: DefDef if tree.symbol.is(Inline) && level > 0 => EmptyTree
@@ -273,22 +272,4 @@ object Staging {
273272
}
274273
}
275274

276-
277-
}
278-
279-
object PCPCheckAndHeal {
280-
import tpd._
281-
282-
/** InlineSplice is used to detect cases where the expansion
283-
* consists of a (possibly multiple & nested) block or a sole expression.
284-
*/
285-
object InlineSplice {
286-
def unapply(tree: Tree)(implicit ctx: Context): Option[Tree] = tree match {
287-
case Spliced(code) if Splicer.canBeSpliced(code) => Some(code)
288-
case Block(List(stat), Literal(Constant(()))) => unapply(stat)
289-
case Block(Nil, expr) => unapply(expr)
290-
case Typed(expr, _) => unapply(expr)
291-
case _ => None
292-
}
293-
}
294275
}

compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dotty.tools
22
package dotc
33
package typer
44

5-
import dotty.tools.dotc.ast.{Trees, untpd, tpd}
5+
import dotty.tools.dotc.ast.{Trees, tpd, untpd}
66
import Trees._
77
import core._
88
import Flags._
@@ -15,9 +15,11 @@ import Contexts.Context
1515
import Names.Name
1616
import NameKinds.{InlineAccessorName, UniqueInlineName}
1717
import Annotations._
18-
import transform.AccessProxies
18+
import transform.{AccessProxies, PCPCheckAndHeal, Splicer, TreeMapWithStages}
1919
import config.Printers.inlining
20-
import util.Property
20+
import util.{Property, SourcePosition}
21+
import dotty.tools.dotc.core.StagingContext._
22+
import dotty.tools.dotc.transform.TreeMapWithStages._
2123

2224
object PrepareInlineable {
2325
import tpd._
@@ -249,4 +251,52 @@ object PrepareInlineable {
249251
em"inline unapply method can be rewritten only if its right hand side is a tuple (e1, ..., eN)",
250252
body.sourcePos)
251253
}
254+
255+
def checkInlineMacro(sym: Symbol, rhs: Tree, pos: SourcePosition)(implicit ctx: Context) = {
256+
if (ctx.phase.isTyper) {
257+
258+
/** InlineSplice is used to detect cases where the expansion
259+
* consists of a (possibly multiple & nested) block or a sole expression.
260+
*/
261+
object InlineSplice {
262+
def unapply(tree: Tree)(implicit ctx: Context): Option[Tree] = tree match {
263+
case Spliced(code) if Splicer.canBeSpliced(code) => Some(code)
264+
case Block(List(stat), Literal(Constants.Constant(()))) => unapply(stat)
265+
case Block(Nil, expr) => unapply(expr)
266+
case Typed(expr, _) => unapply(expr)
267+
case _ => None
268+
}
269+
}
270+
271+
var isMacro = false
272+
new TreeMapWithStages(freshStagingContext) {
273+
override protected def transformSplice(splice: tpd.Select)(implicit ctx: Context): tpd.Tree = {
274+
isMacro = true
275+
splice
276+
}
277+
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree =
278+
if (isMacro) tree else super.transform(tree)
279+
}.transform(rhs)
280+
281+
if (isMacro) {
282+
sym.setFlag(Macro)
283+
if (level == 0)
284+
rhs match {
285+
case InlineSplice(_) =>
286+
new PCPCheckAndHeal(freshStagingContext).transform(rhs) // Ignore output, only check PCP
287+
case _ =>
288+
ctx.error(
289+
"""Malformed macro.
290+
|
291+
|Expected the ~ to be at the top of the RHS:
292+
| inline def foo(inline x: X, ..., y: Y): Int = ~impl(x, ... '(y))
293+
|
294+
| * The contents of the splice must call a static method
295+
| * All arguments must be quoted or inline
296+
""".stripMargin, pos)
297+
}
298+
}
299+
}
300+
}
301+
252302
}

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,36 +1556,7 @@ class Typer extends Namer
15561556
val rhs1 = typedExpr(ddef.rhs, tpt1.tpe.widenExpr)(rhsCtx)
15571557

15581558
if (sym.isInlineMethod) {
1559-
if (ctx.phase.isTyper) {
1560-
import PCPCheckAndHeal.InlineSplice
1561-
import TreeMapWithStages._
1562-
var isMacro = false
1563-
new TreeMapWithStages(freshStagingContext) {
1564-
override protected def transformSplice(splice: tpd.Select)(implicit ctx: Context): tpd.Tree = {
1565-
isMacro = true
1566-
splice
1567-
}
1568-
}.transform(rhs1)
1569-
1570-
if (isMacro) {
1571-
sym.setFlag(Macro)
1572-
if (level == 0)
1573-
rhs1 match {
1574-
case InlineSplice(_) =>
1575-
new PCPCheckAndHeal(freshStagingContext).transform(rhs1) // Ignore output, only check PCP
1576-
case _ =>
1577-
ctx.error(
1578-
"""Malformed macro.
1579-
|
1580-
|Expected the ~ to be at the top of the RHS:
1581-
| inline def foo(inline x: X, ..., y: Y): Int = ~impl(x, ... '(y))
1582-
|
1583-
| * The contents of the splice must call a static method
1584-
| * All arguments must be quoted or inline
1585-
""".stripMargin, ddef.sourcePos)
1586-
}
1587-
}
1588-
}
1559+
PrepareInlineable.checkInlineMacro(sym, rhs1, ddef.sourcePos)
15891560
PrepareInlineable.registerInlineInfo(sym, _ => rhs1)
15901561
}
15911562

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import scala.quoted._
22

33
object Foo {
4-
inline def foo(): Int = ${bar($x)} // error
4+
inline def foo(): Int = ${bar(${x})} // error
55
def x: Expr[Int] = '{1}
66
def bar(i: Int): Expr[Int] = i.toExpr
77
}

0 commit comments

Comments
 (0)