Skip to content

Commit 861cc5c

Browse files
committed
Do not Ycheck inlined positions for macro annotated definitions
In macro annotation definitions, as part of the macro expansion, users can mess with `Inlined` nodes, which can break YCheckPositions checks. Similarly to how it is done for macro methods, we now skip checking definitions with a macro annotation.
1 parent 1be790c commit 861cc5c

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class YCheckPositions extends Phase {
3838
// Recursivlely check children while keeping track of current source
3939
reporting.trace(i"check pos ${tree.getClass} ${tree.source} ${sources.head} $tree") {
4040
tree match {
41+
case _ if isMacroAnnotatedDefinition(tree) =>
42+
() // FIXME macro annotated definitions can drop Inlined nodes. As with macro defs, they should be reinserted after macro expansion
4143
case tree @ Inlined(_, bindings, expansion) if tree.inlinedFromOuterScope =>
4244
assert(bindings.isEmpty)
4345
val old = sources
@@ -59,6 +61,12 @@ class YCheckPositions extends Phase {
5961
case _ =>
6062
}
6163

64+
private def isMacroAnnotatedDefinition(tree: tpd.Tree)(using Context) =
65+
tree match
66+
case tree: TypeDef => tree.isClassDef && MacroAnnotations.hasMacroAnnotation(tree.symbol)
67+
case tree: ValOrDefDef => MacroAnnotations.hasMacroAnnotation(tree.symbol)
68+
case _ => false
69+
6270
private def isMacro(call: Tree)(using Context) =
6371
call.symbol.is(Macro) ||
6472
(call.symbol.isClass && call.tpe.derivesFrom(defn.MacroAnnotationClass)) ||

tests/pos-macros/i17007/Macro_1.scala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//> using option "-Ycheck:all"
2+
import scala.annotation.MacroAnnotation
3+
import scala.quoted.*
4+
5+
class annotation extends MacroAnnotation:
6+
def transform(using Quotes)(tree: quotes.reflect.Definition) =
7+
import quotes.reflect.*
8+
9+
tree match
10+
case tree: ClassDef =>
11+
val List(DefDef(name, paramss, tpt, Some(body))) = tree.body: @unchecked
12+
val rhs = body match
13+
case Inlined(_, _, Block(List(Apply(_ /* `locally` */, List(rhs))), _)) => rhs
14+
val method = DefDef.copy(tree.body.head)(name, paramss, tpt, Some(rhs.changeOwner(tree.body.head.symbol)))
15+
List(ClassDef.copy(tree)(tree.name, tree.constructor, tree.parents, tree.self, List(method)))
16+
case tree: DefDef =>
17+
val DefDef(name, paramss, tpt, Some(body)) = tree: @unchecked
18+
val rhs = body match
19+
case Inlined(_, _, Block(List(Apply(_ /* `locally` */, List(rhs))), _)) => rhs
20+
val defdef = DefDef.copy(tree)(name, paramss, tpt, Some(rhs.changeOwner(tree.symbol)))
21+
List(defdef)
22+
case tree: ValDef =>
23+
val ValDef(name, tpt, Some(body)) = tree: @unchecked
24+
val rhs = body match
25+
case Inlined(_, _, Block(List(Apply(_ /* `locally` */, List(rhs))), _)) => rhs
26+
val valdef = ValDef.copy(tree)(name, tpt, Some(rhs.changeOwner(tree.symbol)))
27+
List(valdef)
28+

tests/pos-macros/i17007/Test_2.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//> using option "-Ycheck:all"
2+
transparent inline def inlineMethod(v: Int) =
3+
locally(v)
4+
0
5+
6+
@annotation
7+
class Test1:
8+
def method = inlineMethod(42)
9+
10+
object Test2:
11+
@annotation val valdef = inlineMethod(42)
12+
@annotation def defdef = inlineMethod(42)

0 commit comments

Comments
 (0)