Skip to content

Commit 648b8a4

Browse files
committed
Change macro labelling
- Mark a method with a toplevel splice as a macro already when we register the inline info. This is needed so that such methods are recognized as erased the first time someone wants to inline them. - Improve error message for splice outside quote.
1 parent efd5310 commit 648b8a4

File tree

7 files changed

+34
-28
lines changed

7 files changed

+34
-28
lines changed

compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ public enum ErrorMessageID {
131131
MatchCaseOnlyNullWarningID,
132132
ImportRenamedTwiceID,
133133
TypeTestAlwaysSucceedsID,
134+
SpliceOutsideQuotesID,
134135
;
135136

136137
public int errorNumber() {

compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala

+8
Original file line numberDiff line numberDiff line change
@@ -2105,4 +2105,12 @@ object messages {
21052105
}
21062106
val explanation = ""
21072107
}
2108+
2109+
case class SpliceOutsideQuotes() extends Message(SpliceOutsideQuotesID) {
2110+
val kind = "Syntax"
2111+
val msg = "splice outside quotes"
2112+
val explanation =
2113+
"""A splice may only appear inside quotes '{ ... },
2114+
|or else it must be the whole right hand side of a transparent method.""".stripMargin
2115+
}
21082116
}

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

+3-16
Original file line numberDiff line numberDiff line change
@@ -156,23 +156,10 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
156156
}
157157
}
158158

159-
/** 1. If we are in a transparent method but not in a nested quote, mark the transparent method
160-
* as a macro.
161-
*
162-
* 2. If selection is a quote or splice node, record that fact in the current compilation unit.
159+
/** If selection is a quote or splice node, record that fact in the current compilation unit.
163160
*/
164-
private def handleMeta(sym: Symbol)(implicit ctx: Context): Unit = {
165-
166-
def markAsMacro(c: Context): Unit =
167-
if (c.owner eq c.outer.owner) markAsMacro(c.outer)
168-
else if (c.owner.isTransparentMethod) c.owner.setFlag(Macro | Erased)
169-
else if (!c.outer.owner.is(Package)) markAsMacro(c.outer)
170-
171-
if (sym.isSplice || sym.isQuote) {
172-
markAsMacro(ctx)
173-
ctx.compilationUnit.containsQuotesOrSplices = true
174-
}
175-
}
161+
private def handleMeta(sym: Symbol)(implicit ctx: Context): Unit =
162+
if (sym.isSplice || sym.isQuote) ctx.compilationUnit.containsQuotesOrSplices = true
176163

177164
private object dropInlines extends TreeMap {
178165
override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import SymUtils._
1212
import NameKinds._
1313
import dotty.tools.dotc.ast.tpd.Tree
1414
import typer.Implicits.SearchFailureType
15-
15+
import reporting.diagnostic.messages._
1616
import scala.collection.mutable
1717
import dotty.tools.dotc.core.StdNames._
1818
import dotty.tools.dotc.core.quoted._
@@ -230,7 +230,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
230230

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

235235
/** Try to heal phase-inconsistent reference to type `T` using a local type definition.
236236
* @return None if successful

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

+10
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import ProtoTypes.selectionProto
2020
import SymDenotations.SymDenotation
2121
import Annotations._
2222
import transform.{ExplicitOuter, AccessProxies}
23+
import transform.SymUtils._
2324
import Inferencing.fullyDefinedType
2425
import config.Printers.inlining
2526
import ErrorReporting.errorTree
@@ -250,6 +251,15 @@ object PrepareTransparent {
250251
inlined.updateAnnotation(LazyBodyAnnotation { _ =>
251252
implicit val ctx = inlineCtx
252253
val rawBody = treeExpr(ctx)
254+
255+
def markAsMacro(body: Tree): Unit = body match {
256+
case _: Select if body.symbol.isSplice => inlined.setFlag(Erased | Macro)
257+
case Block(Nil, expr) => markAsMacro(expr)
258+
case Block(expr :: Nil, Literal(Constant(()))) => markAsMacro(expr)
259+
case _ =>
260+
}
261+
markAsMacro(rawBody)
262+
253263
val typedBody =
254264
if (ctx.reporter.hasErrors) rawBody
255265
else ctx.compilationUnit.inlineAccessors.makeInlineable(rawBody)

tests/neg/quote-macro-splice.scala

+9-9
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,23 @@ import scala.quoted._
22

33
object Test {
44

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

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

15-
transparent def foo3: Int = { // error
15+
transparent def foo3: Int = {
1616
val a = 1
17-
~impl('(a))
17+
~impl('(a)) // error: splice outside quotes
1818
}
1919

20-
transparent def foo4: Int = { // error
21-
~impl('(1))
20+
transparent def foo4: Int = {
21+
~impl('(1)) // error: splice outside quotes
2222
1
2323
}
2424

tests/pos/i4773.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ import scala.quoted._
33
object Foo {
44
transparent def foo2(): Unit = ~foo2Impl()
55
def foo2Impl(): Expr[Unit] = '()
6-
erased transparent def foo(): Unit = foo2()
6+
transparent def foo(): Unit = foo2()
77
}

0 commit comments

Comments
 (0)