Skip to content

Encoding of quote HOLE in TASTy #17137

Closed
@nicolasstucki

Description

@nicolasstucki

Compiler version

3.0, 3.1, 3.2, 3.3

Problem

import scala.quoted.*
def test(using Quotes) = '{ def f[T](x: T) = ${ identity('{ val y: T = x; y }) } }

Compiling with -Xprint:splicing, we can see the variables defined in the outer quote and used in the inner one (T, x). In that phase we replace the splice with a quote hole {{{ 0 | T | T, x | ... }.

[[syntax trees at end of                  splicing]] // t/Test.scala
package <empty> {
  import scala.quoted.*
  final lazy module val Test$package: Test$package = new Test$package()
  @SourceFile("t/Test.scala") final module class Test$package() extends Object() { this: Test$package.type =>
    private def writeReplace(): AnyRef = new scala.runtime.ModuleSerializationProxy(classOf[Test$package.type])
    def test(using x$1: quoted.Quotes): quoted.Expr[Unit] =
      '{
        {
          def f[T >: Nothing <: Any](x: T): T =
            {{{ 0 | T | T, x | ... /* a lambda with the contents of the splice */ }}}
          ()
        }
      }.apply(x$1)
  }
}

We currently pickle this hole we have to pickle the captured variables T, x as trees.
https://github.com/lampepfl/dotty/blob/d36cd2d142f490e5ba7fcb29906b6b0a27cf8702/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala#L668-L673

The problem is that we do not know if the tree has to be unpickled as a type or a term. We unpickle all of them as terms
https://github.com/lampepfl/dotty/blob/d36cd2d142f490e5ba7fcb29906b6b0a27cf8702/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala#L1470-L1476

If a type contains a term reference, such as a TypeTree(tp: TermRef), the unpicker will unpickle it as an Ident or Select. This implies that the type is unpickled as a term, which causes trouble later when we wrap them in quoted.{Expr,Type}.

Solution 1

We have to pickle the hole with a format where we can unpickle types a types and terms as terms. For this we need to split the arguments into type and term arguments. We need to make sure that the order of arguments retains the order that is defined in the splicing phase. Therefore, we need to split the type arguments from term arguments during the splicing phase.

The tricky part is to find a way to encode this tree in tasty without braking TASTy binary compatibility.

Solution 2

Define a method and a type in the standard library to encode the holes.

This would make the pickled tasty slightly larger.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions