Skip to content

Symbol.asQuotes doesn't work as advertised #20471

Closed
@joroKr21

Description

@joroKr21

Compiler version

3.4.2

Minimized code

Diff: https://github.com/typelevel/cats-tagless/pull/547/files?w=1#diff-19baba9f9fc14acd2200e21ad491f2871a69edbae3de81d0d3e7eec2c88899c5

CI: https://github.com/typelevel/cats-tagless/actions/runs/9236004309/job/25411405213?pr=547

Here is my change:

       body = {
         case (method, tpe, body) if tpe =:= B =>
+          given Quotes = method.asQuotes
           '{
             @tailrec def step(x: A): B =
               ${ body.replace(a, '{ x }).asExprOf[Either[A, B]] } match
                 case Left(a) => step(a)
                 case Right(b) => b
             step($a)
-          }.asTerm.changeOwner(method)
+          }.asTerm

The test which fails to compile:

  trait TestAlgebra[T] derives FlatMap:
    def abstractEffect(a: String): T
    def concreteEffect(a: String): T = abstractEffect(a + " concreteEffect")
    def abstractOther(a: String): String
    def concreteOther(a: String): String = a + " concreteOther"
    def withoutParams: T

Output

[error] -- Error: /home/runner/work/cats-tagless/cats-tagless/tests/src/test/scala-3/cats/tagless/tests/autoFlatMapTests.scala:39:31 
[error] 39 |  trait TestAlgebra[T] derives FlatMap:
[error]    |                               ^
[error]    |Exception occurred while executing macro expansion.
[error]    |java.lang.AssertionError: assertion failed: Tree had an unexpected owner for method step
[error]    |Expected: method withoutParams (cats.tagless.tests.autoFlatMapTests$.TestAlgebra$._$_$$anon._$$anon$macro$3.withoutParams)
[error]    |But was: method concreteEffect (cats.tagless.tests.autoFlatMapTests$.TestAlgebra$._$_$$anon._$$anon$macro$3.concreteEffect)
[error]    |
[error]    |The code of the definition of method step is
[error]    |@scala.annotation.tailrec def step(x: A): B = f.apply(x).withoutParams match {
[error]    |  case scala.Left(a) =>
[error]    |    step(a)
[error]    |  case scala.Right(b) =>
[error]    |    (b: B)
[error]    |}
[error]    |
[error]    |which was found in the code
[error]    |{
[error]    |  @scala.annotation.tailrec def step(x: A): B = f.apply(x).withoutParams match {
[error]    |    case scala.Left(a) =>
[error]    |      step(a)
[error]    |    case scala.Right(b) =>
[error]    |      (b: B)
[error]    |  }
[error]    |  step(`a₂`)
[error]    |}
[error]    |
[error]    |which has the AST representation
[error]    |Inlined(Some(TypeIdent("MacroFlatMap$")), Nil, Block(List(DefDef("step", List(TermParamClause(List(ValDef("x", Inferred(), None)))), Inferred(), Some(Match(Inlined(None, Nil, Select(Inlined(Some(TypeIdent("MacroFlatMap$")), Nil, Apply(Select(Inlined(None, Nil, Ident("f")), "apply"), List(Inlined(None, Nil, Ident("x"))))), "withoutParams")), List(CaseDef(TypedOrTest(Unapply(TypeApply(Select(Ident("Left"), "unapply"), List(Inferred(), Inferred())), Nil, List(Bind("a", Wildcard()))), Inferred()), None, Block(Nil, Apply(Ident("step"), List(Ident("a"))))), CaseDef(TypedOrTest(Unapply(TypeApply(Select(Ident("Right"), "unapply"), List(Inferred(), Inferred())), Nil, List(Bind("b", Wildcard()))), Inferred()), None, Block(Nil, Typed(Ident("b"), Inferred())))))))), Apply(Ident("step"), List(Inlined(None, Nil, Ident("a"))))))
[error]    |
[error]    |
[error]    |
[error]    |Tip: The owner of a tree can be changed using method `Tree.changeOwner`.
[error]    |Tip: The default owner of definitions created in quotes can be changed using method `Symbol.asQuotes`.

Expectation

I expect it to compile the same way it does if I use changeOwner. It's even one of the tips:

Tip: The default owner of definitions created in quotes can be changed using method Symbol.asQuotes

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions