Skip to content

Commit c030b30

Browse files
committed
Detect macro dependencies within the current run
1 parent 7423d31 commit c030b30

File tree

14 files changed

+133
-8
lines changed

14 files changed

+133
-8
lines changed

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

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,17 +1239,48 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
12391239
assert(level == 0)
12401240
val inlinedFrom = enclosingInlineds.last
12411241
val ctx1 = tastyreflect.MacroExpansion.context(inlinedFrom)
1242-
val evaluatedSplice = Splicer.splice(body, inlinedFrom.sourcePos, MacroClassLoader.fromContext)(ctx1)
12431242

1244-
val inlinedNormailizer = new TreeMap {
1245-
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match {
1246-
case Inlined(EmptyTree, Nil, expr) if enclosingInlineds.isEmpty => transform(expr)
1247-
case _ => super.transform(tree)
1243+
val dependencies = macroDependencies(body)
1244+
1245+
if (dependencies.nonEmpty) {
1246+
var location = inlinedFrom.symbol
1247+
if (location.isLocalDummy) location = location.owner
1248+
1249+
val msg =
1250+
em"""Failed to expand macro. This macro depends on an implementation that is defined in the same project and not yet compiled.
1251+
|In particular ${inlinedFrom.symbol} depends on ${dependencies.map(_.show).mkString(", ")}.
1252+
|
1253+
|Moving ${dependencies.map(_.show).mkString(", ")} to a different project would fix this.
1254+
|""".stripMargin
1255+
ctx.error(msg, inlinedFrom.sourcePos)
1256+
EmptyTree
1257+
} else {
1258+
val evaluatedSplice = Splicer.splice(body, inlinedFrom.sourcePos, MacroClassLoader.fromContext)(ctx1)
1259+
1260+
val inlinedNormailizer = new TreeMap {
1261+
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match {
1262+
case Inlined(EmptyTree, Nil, expr) if enclosingInlineds.isEmpty => transform(expr)
1263+
case _ => super.transform(tree)
1264+
}
12481265
}
1266+
val normalizedSplice = inlinedNormailizer.transform(evaluatedSplice)
1267+
if (normalizedSplice.isEmpty) normalizedSplice
1268+
else normalizedSplice.withSpan(span)
12491269
}
1250-
val normalizedSplice = inlinedNormailizer.transform(evaluatedSplice)
1251-
if (normalizedSplice.isEmpty) normalizedSplice
1252-
else normalizedSplice.withSpan(span)
1270+
}
1271+
1272+
/** Return the set of symbols that are refered by the tree and defined in the current run */
1273+
private def macroDependencies(tree: Tree)(implicit ctx: Context) = {
1274+
new TreeAccumulator[Set[Symbol]] {
1275+
override def apply(syms: Set[Symbol], tree: tpd.Tree)(implicit ctx: Context): Set[Symbol] = {
1276+
val newSyms = tree match {
1277+
case tree: RefTree if tree.symbol.isDefinedInCurrentRun && tree.symbol.owner != ctx.owner =>
1278+
syms + tree.symbol
1279+
case _ => syms
1280+
}
1281+
foldOver(newSyms, tree)
1282+
}
1283+
}.apply(Set.empty, tree)
12531284
}
12541285
}
12551286

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-- Error: tests/neg-macros/macros-in-same-project-1/Bar.scala:2:13 -----------------------------------------------------
2+
2 | Foo.myMacro() // error
3+
| ^^^^^^^^^^^^^
4+
|Failed to expand macro. This macro depends on an implementation that is defined in the same project and not yet compiled.
5+
|In particular method myMacro depends on method aMacroImplementation.
6+
|
7+
|Moving method aMacroImplementation to a different project would fix this.
8+
| This location is in code that was inlined at Bar.scala:2
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object Bar {
2+
Foo.myMacro() // error
3+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import scala.quoted._
2+
3+
object Foo {
4+
5+
inline def myMacro(): Unit = ${ aMacroImplementation }
6+
7+
def aMacroImplementation given QuoteContext: Expr[Unit] = '{ println("Hello") }
8+
9+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-- Error: tests/neg-macros/macros-in-same-project-2/Bar.scala:5:9 ------------------------------------------------------
2+
5 | myMacro() // error
3+
| ^^^^^^^^^
4+
|Failed to expand macro. This macro depends on an implementation that is defined in the same project and not yet compiled.
5+
|In particular method myMacro depends on method aMacroImplementation, object Foo.
6+
|
7+
|Moving method aMacroImplementation, object Foo to a different project would fix this.
8+
| This location is in code that was inlined at Bar.scala:5
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
object Bar {
2+
3+
inline def myMacro(): Unit = ${ Foo.aMacroImplementation }
4+
5+
myMacro() // error
6+
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import scala.quoted._
2+
3+
object Foo {
4+
5+
def aMacroImplementation given QuoteContext: Expr[Unit] = '{ println("Hello") }
6+
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-- Error: tests/neg-macros/macros-in-same-project-3/Baz.scala:2:13 -----------------------------------------------------
2+
2 | Bar.myMacro() // error
3+
| ^^^^^^^^^^^^^
4+
|Failed to expand macro. This macro depends on an implementation that is defined in the same project and not yet compiled.
5+
|In particular method myMacro depends on method aMacroImplementation.
6+
|
7+
|Moving method aMacroImplementation to a different project would fix this.
8+
| This location is in code that was inlined at Baz.scala:2
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import scala.quoted._
2+
3+
object Bar {
4+
5+
inline def myMacro(): Unit = ${ aMacroImplementation }
6+
7+
def aMacroImplementation given QuoteContext: Expr[Unit] = Foo.hello()
8+
9+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object Baz {
2+
Bar.myMacro() // error
3+
}

0 commit comments

Comments
 (0)