Skip to content

Commit ee403cd

Browse files
Merge pull request #8205 from dotty-staging/fix-#7142-2
Fix #7142: Detect escaped variables across macro expansion
2 parents 669423a + cadafc2 commit ee403cd

File tree

6 files changed

+29
-11
lines changed

6 files changed

+29
-11
lines changed

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ object Splicer {
4141
case Quoted(quotedTree) => quotedTree
4242
case _ =>
4343
val interpreter = new Interpreter(pos, classLoader)
44-
val macroOwner = ctx.newSymbol(ctx.owner, NameKinds.UniqueName.fresh(nme.MACROkw), Synthetic, defn.AnyType, coord = tree.span)
44+
val macroOwner = ctx.newSymbol(ctx.owner, nme.MACROkw, Macro | Synthetic, defn.AnyType, coord = tree.span)
4545
try {
4646
given Context = ctx.withOwner(macroOwner)
4747
// Some parts of the macro are evaluated during the unpickling performed in quotedExprToTree
@@ -100,7 +100,10 @@ object Splicer {
100100
traverseChildren(tree)
101101
private def isEscapedVariable(sym: Symbol)(given ctx: Context): Boolean =
102102
sym.exists && !sym.is(Package)
103-
&& sym.owner.ownersIterator.contains(expansionOwner) // symbol was generated within the macro expansion
103+
&& sym.owner.ownersIterator.exists(x =>
104+
x == expansionOwner || // symbol was generated within this macro expansion
105+
x.is(Macro, butNot = Method) && x.name == nme.MACROkw // symbol was generated within another macro expansion
106+
)
104107
&& !locals.contains(sym) // symbol is not in current scope
105108
}.traverse(tree)
106109
tree

tests/neg-macros/i7142h/Macro_1.scala

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package macros
2+
import scala.quoted._
3+
4+
var saved = Option.empty[Expr[Int]]
5+
6+
def oops(given QuoteContext) = {
7+
if (saved.isEmpty) '{ (x: Int) => ${ saved = Some('{x}); 'x } }
8+
else saved.get
9+
}
10+
11+
inline def test = ${oops}

tests/neg-macros/i7142h/Test_2.scala

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
object Test {
2+
macros.test
3+
macros.test // error
4+
}

tests/run-custom-args/Yretain-trees/tasty-extractors-owners.check

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
foo
2-
ValDef("macro$1", Inferred(), None)
2+
ValDef("macro", Inferred(), None)
33

44
bar
55
DefDef("foo", Nil, Nil, Inferred(), None)
@@ -8,7 +8,7 @@ bar2
88
DefDef("foo", Nil, Nil, Inferred(), None)
99

1010
foo2
11-
ValDef("macro$1", Inferred(), None)
11+
ValDef("macro", Inferred(), None)
1212

1313
baz
1414
ValDef("foo2", Inferred(), None)

tests/run-macros/tasty-location.check

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
foo Location(List(Test$, loc1, macro$1))
2-
foo Location(List(Test$, main, macro$2))
3-
foo Location(List(Test$, main, macro$3))
4-
foo Location(List(Test$, main, bar, macro$4))
5-
foo Location(List(Test$, main, bar, baz, macro$5))
6-
foo Location(List(Test$, main, f, $anonfun, macro$6))
1+
foo Location(List(Test$, loc1, macro))
2+
foo Location(List(Test$, main, macro))
3+
foo Location(List(Test$, main, macro))
4+
foo Location(List(Test$, main, bar, macro))
5+
foo Location(List(Test$, main, bar, baz, macro))
6+
foo Location(List(Test$, main, f, $anonfun, macro))

0 commit comments

Comments
 (0)