Skip to content

Commit

Permalink
Fix references to class members defined in quotes
Browse files Browse the repository at this point in the history
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.

Fixes scala#17103
  • Loading branch information
nicolasstucki authored and Dedelweiss committed Apr 17, 2023
1 parent b92bddd commit f6a703d
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 1 deletion.
8 changes: 8 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/Splicing.scala
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,14 @@ class Splicing extends MacroTransform:

override def transform(tree: tpd.Tree)(using Context): tpd.Tree =
tree match
case tree: Select if tree.isTerm && isCaptured(tree.symbol) =>
tree.symbol.allOverriddenSymbols.find(sym => !isCaptured(sym.owner)) match
case Some(sym) =>
// virtualize call on overridden symbol that is not defined in a non static class
transform(tree.qualifier.select(sym))
case _ =>
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)
tree
case tree: RefTree =>
if tree.isTerm then
if isCaptured(tree.symbol) then
Expand Down
16 changes: 16 additions & 0 deletions tests/neg-macros/i17103.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import scala.quoted.*

def test(using Quotes): Expr[Unit] =
'{
trait C:
def d: Int
val c: C = ???
${
val expr = '{
val cRef: c.type = ???
cRef.d // error
()
}
expr
}
}
21 changes: 21 additions & 0 deletions tests/pos-macros/i17103a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import scala.quoted.*

trait C0:
def d: Int

def test(using Quotes): Expr[Unit] =
'{
trait C1 extends C0:
def d: Int
trait C extends C1:
def d: Int
val c: C = ???
${
val expr = '{
val cRef: C = ???
cRef.d // calls C0.d
()
}
expr
}
}
21 changes: 21 additions & 0 deletions tests/pos-macros/i17103b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import scala.quoted.*

trait C0:
def d: Int

def test(using Quotes): Expr[Unit] =
'{
trait C1 extends C0:
def d: Int
trait C extends C1:
def d: Int
val c: C = ???
${
val expr = '{
val cRef: c.type = ???
cRef.d // calls C0.d
()
}
expr
}
}
6 changes: 5 additions & 1 deletion tests/pos-macros/i7405b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import scala.quoted.*
class Foo {
def f(using Quotes): Expr[Any] = {
'{
trait X {
trait X extends A {
type Y
def y: Y = ???
}
Expand All @@ -17,3 +17,7 @@ class Foo {
}
}
}

trait A:
type Y
def y: Y = ???

0 comments on commit f6a703d

Please sign in to comment.