Skip to content

Commit d86f44d

Browse files
authored
Fix for macro annotation that resolves macro-based implicit crashing the compiler (#20353)
When (1) macro-annotating a class or object nested in another class or object and (2) the annotation macro tries to summon an implicit value using `Implicits.search` and (3) the implicit search needs to expand a `given` macro, the compiler crashes with: ``` Failed to evaluate macro. Caused by class dotty.tools.dotc.CompilationUnit$SuspendException ``` I found that the reason for the crash is [`macroDependencies`](https://github.com/scala/scala3/blob/3.4.1/compiler/src/dotty/tools/dotc/inlines/Inliner.scala#L1067) returning locally defined variables, which, I believe, it should not. In particular it returns a list containing `$anonfun` for trees of the following shape that appear when resolving implicit macros: ``` { def $anonfun(using contextual$1: scala.quoted.Quotes): scala.quoted.Expr[<type for implicit search>] = <given macro for implicit value>(contextual$1) closure($anonfun) } ``` This PR skips over such `Closure` nodes, which should be the correct behavior. Not sure if there are other cases that `macroDependencies` handles incorrectly and that should be fixed ...
2 parents 23c5514 + 8743024 commit d86f44d

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

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

+2
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,8 @@ class Inliner(val call: tpd.Tree)(using Context):
11071107
new TreeAccumulator[List[Symbol]] {
11081108
override def apply(syms: List[Symbol], tree: tpd.Tree)(using Context): List[Symbol] =
11091109
tree match {
1110+
case Closure(env, meth, tpt) if meth.symbol.isAnonymousFunction =>
1111+
this(syms, tpt :: env)
11101112
case tree: RefTree if tree.isTerm && level == -1 && tree.symbol.isDefinedInCurrentRun && !tree.symbol.isLocal =>
11111113
foldOver(tree.symbol :: syms, tree)
11121114
case _: This if level == -1 && tree.symbol.isDefinedInCurrentRun =>

tests/pos-macros/i20353/Macro_1.scala

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//> using options -experimental
2+
3+
import scala.annotation.{experimental, MacroAnnotation}
4+
import scala.quoted.*
5+
6+
class ImplicitValue
7+
8+
object ImplicitValue:
9+
inline given ImplicitValue =
10+
${ makeImplicitValue }
11+
12+
def makeImplicitValue(using Quotes) =
13+
import quotes.reflect.*
14+
'{ ImplicitValue() }
15+
end ImplicitValue
16+
17+
@experimental
18+
class Test extends MacroAnnotation:
19+
def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]) =
20+
import quotes.reflect.*
21+
Implicits.search(TypeRepr.of[ImplicitValue])
22+
List(definition)

tests/pos-macros/i20353/Test_2.scala

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//> using options -experimental
2+
3+
class OuterClass:
4+
@Test
5+
class InnerClass
6+
7+
@Test
8+
object InnerObject
9+
end OuterClass
10+
11+
object OuterObject:
12+
@Test
13+
class InnerClass
14+
15+
@Test
16+
object InnerObject
17+
end OuterObject

0 commit comments

Comments
 (0)