Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encoding of quote HOLE in TASTy #17137

Closed
nicolasstucki opened this issue Mar 22, 2023 · 0 comments · Fixed by #17298
Closed

Encoding of quote HOLE in TASTy #17137

nicolasstucki opened this issue Mar 22, 2023 · 0 comments · Fixed by #17298
Labels
area:metaprogramming:quotes Issues related to quotes and splices itype:bug

Comments

@nicolasstucki
Copy link
Contributor

nicolasstucki commented Mar 22, 2023

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.

@nicolasstucki nicolasstucki added itype:bug area:metaprogramming:quotes Issues related to quotes and splices labels Mar 22, 2023
@nicolasstucki nicolasstucki linked a pull request Mar 22, 2023 that will close this issue
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Mar 23, 2023
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Mar 23, 2023
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Mar 23, 2023
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Mar 23, 2023
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Mar 23, 2023
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Mar 23, 2023
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Mar 23, 2023
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Mar 23, 2023
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Mar 23, 2023
nicolasstucki added a commit that referenced this issue Aug 8, 2023
This is a new encoding of HOLE that differentiates between type and term
arguments of the hole.

```
-- pickled quote trees: These trees can only appear in pickled quotes. They will never be in a TASTy file.
  EXPLICITtpt tpt_Term
    -- Tag for a type tree that in a context where it is not explicitly known that this tree is a type.
  HOLE Length idx_Nat tpe_Type arg_Tree*
    -- Splice hole with index `idx`, the type of the hole `tpe`, type and term arguments of the hole `arg`s
```

We will pickle type trees in `arg_Tree` using the `EXPLICITtpt` tag.

We will only have hole captured types if there is a type defined in a
quote and used in a nested quote. Most of the time we do not have those
types and therefore no overhead in the encoding compared to before this
change.

Alternative to #17225
Fixes #17137
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:metaprogramming:quotes Issues related to quotes and splices itype:bug
Projects
None yet
1 participant