Skip to content

Commit 844f662

Browse files
committed
Fix scala#4801: WIP
1 parent c9b2a0f commit 844f662

File tree

5 files changed

+62
-41
lines changed

5 files changed

+62
-41
lines changed

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

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@ package dotty.tools.dotc
22
package transform
33

44
import core._
5-
import Decorators._, Flags._, Types._, Contexts._, Symbols._, Constants._
5+
import Decorators._
6+
import Flags._
7+
import Types._
8+
import Contexts._
9+
import Symbols._
10+
import Constants._
611
import Flags._
712
import ast.Trees._
8-
import ast.{TreeTypeMap, untpd}
13+
import ast.{TreeTypeMap, tpd, untpd}
914
import util.Positions._
1015
import tasty.TreePickler.Hole
1116
import SymUtils._
@@ -120,12 +125,19 @@ class ReifyQuotes extends MacroTransformWithImplicits {
120125
new Reifier(isQuote, this, if (isQuote) level + 1 else level - 1, levels, nestedEmbedded)
121126
}
122127

128+
def inlined: Reifier = {
129+
assert(level == 0)
130+
new Reifier(true, this, 0, levels, embedded)
131+
}
132+
123133
/** We are in a `~(...)` context that is not shadowed by a nested `'(...)` */
124134
def inSplice: Boolean = outer != null && !inQuote
125135

126136
/** We are not in a `~(...)` or a `'(...)` */
127137
def isRoot: Boolean = outer == null
128138

139+
def isInlined: Boolean = inQuote && level == 0
140+
129141
/** A map from type ref T to expressions of type `quoted.Type[T]`".
130142
* These will be turned into splices using `addTags` and represent type variables
131143
* that can be possibly healed.
@@ -422,10 +434,27 @@ class ReifyQuotes extends MacroTransformWithImplicits {
422434
spliceOutsideQuotes(splice.pos)
423435
splice
424436
}
425-
else {
437+
else if (level > 0) {
426438
val (body1, quotes) = nested(isQuote = false).split(splice.qualifier)
427439
makeHole(body1, quotes, splice.tpe).withPos(splice.pos)
428440
}
441+
else if (isInlined) {
442+
// FIXME
443+
val evaluatedSplice = Splicer.splice(splice.qualifier, splice.qualifier.pos, macroClassLoader).withPos(splice.qualifier.pos)
444+
if (ctx.reporter.hasErrors) EmptyTree
445+
else transform(evaluatedSplice)
446+
} else {
447+
if (!Splicer.canBeSpliced(splice.qualifier))
448+
ctx.error( // TODO adapt error message
449+
"""Malformed inline macro.
450+
|
451+
|Expected the ~ to be at the top of the RHS:
452+
| inline def foo(x: X, ..., y: Y): Int = ~impl(x, ... '(y))
453+
|
454+
|The contents of the splice must call a static method. Arguments must be quoted or inlined.
455+
""".stripMargin, splice.pos)
456+
splice
457+
}
429458
}
430459

431460
/** Transforms the contents of a nested splice
@@ -550,37 +579,10 @@ class ReifyQuotes extends MacroTransformWithImplicits {
550579
val last = enteredSyms
551580
stats.foreach(markDef)
552581
mapOverTree(last)
553-
case Inlined(call, bindings, InlineSplice(spliced)) =>
554-
val tree2 =
555-
if (level == 0) {
556-
val evaluatedSplice = Splicer.splice(spliced, tree.pos, macroClassLoader).withPos(tree.pos)
557-
if (ctx.reporter.hasErrors) EmptyTree
558-
else transform(cpy.Inlined(tree)(call, bindings, evaluatedSplice))
559-
}
560-
else super.transform(tree)
561-
562-
// due to value-discarding which converts an { e } into { e; () })
563-
if (tree.tpe =:= defn.UnitType) Block(tree2 :: Nil, Literal(Constant(())))
564-
else tree2
582+
case tree: Inlined if !isInlined && level == 0 =>
583+
inlined.transform(tree)
565584
case _: Import =>
566585
tree
567-
case tree: DefDef if tree.symbol.is(Macro) && level == 0 =>
568-
markDef(tree)
569-
tree.rhs match {
570-
case InlineSplice(_) =>
571-
mapOverTree(enteredSyms) // Ignore output, only check PCP
572-
cpy.DefDef(tree)(rhs = defaultValue(tree.rhs.tpe))
573-
case _ =>
574-
ctx.error(
575-
"""Malformed inline macro.
576-
|
577-
|Expected the ~ to be at the top of the RHS:
578-
| inline def foo(x: X, ..., y: Y): Int = ~impl(x, ... '(y))
579-
|
580-
|The contents of the splice must call a static method. Arguments must be quoted or inlined.
581-
""".stripMargin, tree.rhs.pos)
582-
EmptyTree
583-
}
584586
case _ =>
585587
markDef(tree)
586588
checkLevel(mapOverTree(enteredSyms))

tests/neg/i4433.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
object Foo {
3-
inline def g(inline p: Int => Boolean): Boolean = ~{ // error
4-
if(p(5)) '(true)
3+
inline def g(inline p: Int => Boolean): Boolean = ~{
4+
if(p(5)) '(true) // error
55
else '(false)
66
}
77
}

tests/neg/quote-macro-splice.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@ import scala.quoted._
22

33
object Test {
44

5-
inline def foo1: Int = { // error
5+
inline def foo1: Int = {
66
println()
7-
~impl(1.toExpr)
7+
~impl(1.toExpr) // error
88
}
99

10-
inline def foo2: Int = { // error
11-
~impl(1.toExpr)
12-
~impl(2.toExpr)
10+
inline def foo2: Int = {
11+
~impl(1.toExpr) // error
12+
~impl(2.toExpr) // error
1313
}
1414

15-
inline def foo3: Int = { // error
15+
inline def foo3: Int = {
1616
val a = 1
1717
~impl('(a))
1818
}
1919

20-
inline def foo4: Int = { // error
20+
inline def foo4: Int = {
2121
~impl('(1))
2222
1
2323
}

tests/run/i4801/Macros_1.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.quoted._
2+
3+
object Macro {
4+
5+
inline def foo(b: Boolean): Int = {
6+
if (b) ~bar(true)
7+
else ~bar(false)
8+
}
9+
10+
def bar(b: Boolean): Expr[Int] = if (b) '(1) else '(0)
11+
}

tests/run/i4801/Test_2.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
// println(Macro.foo(true))
4+
// println(Macro.foo(false))
5+
val x: Boolean = true
6+
println(Macro.foo(x))
7+
}
8+
}

0 commit comments

Comments
 (0)