Skip to content

Commit f709ac4

Browse files
committed
Handle lifted arguments in splices correctly
1 parent 1cbb2d1 commit f709ac4

File tree

6 files changed

+48
-19
lines changed

6 files changed

+48
-19
lines changed

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
228228
!sym.is(Param) || levelOK(sym.owner)
229229
}
230230

231-
/** Issue a "splice outside quote" error unless we ar in the body of an inline method */
231+
/** Issue a "splice outside quote" error unless we are in the body of an inline method */
232232
def spliceOutsideQuotes(pos: Position)(implicit ctx: Context): Unit =
233233
ctx.error(i"splice outside quotes", pos)
234234

@@ -584,6 +584,8 @@ class ReifyQuotes extends MacroTransformWithImplicits {
584584
|
585585
|Expected the ~ to be at the top of the RHS:
586586
| inline def foo(x: X, ..., y: Y): Int = ~impl(x, ... '(y))
587+
|
588+
|The contents of the splice must call a static method. Arguments must be quoted or inlined.
587589
""".stripMargin, tree.rhs.pos)
588590
EmptyTree
589591
}
@@ -625,13 +627,11 @@ class ReifyQuotes extends MacroTransformWithImplicits {
625627
* consists of a (possibly multiple & nested) block or a sole expression.
626628
*/
627629
object InlineSplice {
628-
def unapply(tree: Tree)(implicit ctx: Context): Option[Tree] = {
629-
tree match {
630-
case Select(qual, _) if tree.symbol.isSplice && Splicer.canBeSpliced(qual) => Some(qual)
631-
case Block(List(stat), Literal(Constant(()))) => unapply(stat)
632-
case Block(Nil, expr) => unapply(expr)
633-
case _ => None
634-
}
630+
def unapply(tree: Tree)(implicit ctx: Context): Option[Tree] = tree match {
631+
case Select(qual, _) if tree.symbol.isSplice && Splicer.canBeSpliced(qual) => Some(qual)
632+
case Block(List(stat), Literal(Constant(()))) => unapply(stat)
633+
case Block(Nil, expr) => unapply(expr)
634+
case _ => None
635635
}
636636
}
637637
}

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ object Splicer {
105105
protected def interpretTastyContext()(implicit env: Env): Object =
106106
new TastyImpl(ctx)
107107

108-
protected def interpretStaticMethodCall(fn: Tree, args: List[Object])(implicit env: Env): Object = {
108+
protected def interpretStaticMethodCall(fn: Tree, args: => List[Object])(implicit env: Env): Object = {
109109
val (clazz, instance) = loadModule(fn.symbol.owner)
110110
val method = getMethod(clazz, fn.symbol.name, paramsSig(fn.symbol))
111111
stopIfRuntimeException(method.invoke(instance, args: _*))
@@ -225,7 +225,7 @@ object Splicer {
225225
def interpretTypeQuote(tree: tpd.Tree)(implicit env: Env): Boolean = true
226226
def interpretLiteral(value: Any)(implicit env: Env): Boolean = true
227227
def interpretTastyContext()(implicit env: Env): Boolean = true
228-
def interpretStaticMethodCall(fn: tpd.Tree, args: List[Boolean])(implicit env: Env): Boolean = args.forall(identity)
228+
def interpretStaticMethodCall(fn: tpd.Tree, args: => List[Boolean])(implicit env: Env): Boolean = args.forall(identity)
229229

230230
def unexpectedTree(tree: tpd.Tree)(implicit env: Env): Boolean = {
231231
// Assuming that top-level splices can only be in inline methods
@@ -244,7 +244,7 @@ object Splicer {
244244
protected def interpretTypeQuote(tree: Tree)(implicit env: Env): Res
245245
protected def interpretLiteral(value: Any)(implicit env: Env): Res
246246
protected def interpretTastyContext()(implicit env: Env): Res
247-
protected def interpretStaticMethodCall(fn: Tree, args: List[Res])(implicit env: Env): Res
247+
protected def interpretStaticMethodCall(fn: Tree, args: => List[Res])(implicit env: Env): Res
248248
protected def unexpectedTree(tree: Tree)(implicit env: Env): Res
249249

250250
protected final def interpretTree(tree: Tree)(implicit env: Env): Res = tree match {
@@ -261,18 +261,18 @@ object Splicer {
261261
interpretTastyContext()
262262

263263
case StaticMethodCall(fn, args) =>
264-
val interpretedArgs = args.map(arg => interpretTree(arg))
265-
interpretStaticMethodCall(fn, interpretedArgs)
264+
interpretStaticMethodCall(fn, args.map(arg => interpretTree(arg)))
266265

266+
// Interpret `foo(j = x, i = y)` which it is expanded to
267+
// `val j$1 = x; val i$1 = y; foo(i = y, j = x)`
267268
case Block(stats, expr) =>
268269
val newEnv = stats.foldLeft(env)((accEnv, stat) => stat match {
269-
case stat: ValDef => accEnv.updated(stat.name, interpretTree(stat.rhs)(accEnv))
270+
case stat: ValDef if stat.symbol.is(Synthetic) =>
271+
accEnv.updated(stat.name, interpretTree(stat.rhs)(accEnv))
270272
case stat => return unexpectedTree(stat)
271273
})
272274
interpretTree(expr)(newEnv)
273-
274275
case NamedArg(_, arg) => interpretTree(arg)
275-
276276
case Ident(name) if env.contains(name) => env(name)
277277

278278
case _ => unexpectedTree(tree)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ abstract class Lifter {
4949
// don't instantiate here, as the type params could be further constrained, see tests/pos/pickleinf.scala
5050
var liftedType = expr.tpe.widen
5151
if (liftedFlags.is(Method)) liftedType = ExprType(liftedType)
52-
val lifted = ctx.newSymbol(ctx.owner, name, liftedFlags, liftedType, coord = positionCoord(expr.pos))
52+
val lifted = ctx.newSymbol(ctx.owner, name, liftedFlags | Synthetic, liftedType, coord = positionCoord(expr.pos))
5353
defs += liftedDef(lifted, expr).withPos(expr.pos)
5454
ref(lifted.termRef).withPos(expr.pos.focus)
5555
}

tests/pos/i4493-b.scala renamed to tests/neg/i4493-b.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
class Index[K]
22
object Index {
3-
inline def succ[K](x: K): Unit = ~{
3+
inline def succ[K](x: K): Unit = ~{ // error
44
implicit val t: quoted.Type[K] = '[K]
55
'(new Index[K])
66
}

tests/pos/i4493.scala renamed to tests/neg/i4493.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
class Index[K]
22
object Index {
3-
inline def succ[K]: Unit = ~{
3+
inline def succ[K]: Unit = ~{ // error
44
implicit val t: quoted.Type[K] = '[K]
55
'(new Index[K])
66
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import Test.impl
2+
3+
import scala.quoted._
4+
5+
object Test {
6+
7+
inline def foo1: Unit = ~{ // error
8+
val x = 1
9+
impl(x)
10+
}
11+
12+
inline def foo2: Unit = ~impl({ // error
13+
val x = 1
14+
x
15+
})
16+
17+
inline def foo3: Unit = ~impl({ // error
18+
println("foo3")
19+
3
20+
})
21+
22+
inline def foo4: Unit = ~{ // error
23+
println("foo4")
24+
impl(1)
25+
}
26+
27+
def impl(i: Int): Expr[Unit] = '()
28+
29+
}

0 commit comments

Comments
 (0)