Skip to content

Commit 83e7142

Browse files
committed
Fix references to class members defined in quotes
If an inner quote selects a symbol that is defined in an outer quote we need to transform it or reject it. The issue is that the inner quote cannot contain a reference to the type of the class defined in the outer quote. Any such reference is erased the parents of that class that are statically know outside those quotes. If the selected symbol is overriding a symbol in one of those statically known classes, we can use that overridden symbol instead. If not we have to reject the code.
1 parent 29e229b commit 83e7142

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,14 @@ class Splicing extends MacroTransform:
208208

209209
override def transform(tree: tpd.Tree)(using Context): tpd.Tree =
210210
tree match
211+
case tree: Select if tree.isTerm && isCaptured(tree.symbol) =>
212+
tree.symbol.allOverriddenSymbols.find(sym => !isCaptured(sym.owner)) match
213+
case Some(sym) =>
214+
// virtualize call on overridden symbol that is not defined in a non static class
215+
transform(tree.qualifier.select(sym))
216+
case _ =>
217+
report.error(em"Can not use reference to staged local ${tree.symbol} defined in an outer quote.\n\nThis can work if ${tree.symbol.owner} would extend a top level interface that defines ${tree.symbol}.", tree)
218+
tree
211219
case tree: RefTree =>
212220
if tree.isTerm then
213221
if isCaptured(tree.symbol) then

tests/pos-macros/i17103a.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import scala.quoted.*
2+
3+
trait C0:
4+
def d: Int
5+
6+
def test(using Quotes): Expr[Unit] =
7+
'{
8+
trait C1 extends C0:
9+
def d: Int
10+
trait C extends C1:
11+
def d: Int
12+
val c: C = ???
13+
${
14+
val expr = '{
15+
val cRef: C = ???
16+
cRef.d // calls C0.d
17+
()
18+
}
19+
expr
20+
}
21+
}

tests/pos-macros/i7405b.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import scala.quoted.*
33
class Foo {
44
def f(using Quotes): Expr[Any] = {
55
'{
6-
trait X {
6+
trait X extends A {
77
type Y
88
def y: Y = ???
99
}
@@ -17,3 +17,7 @@ class Foo {
1717
}
1818
}
1919
}
20+
21+
trait A:
22+
type Y
23+
def y: Y = ???

0 commit comments

Comments
 (0)