scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.85k stars 1.06k forks source link

Explicit null error in macros: "java.lang.AssertionError: assertion failed: unresolved symbols" #8576

Open wookievx opened 4 years ago

wookievx commented 4 years ago

minimized code

type Opt[A] = A | Null
object Opt {
  given ops as AnyRef {
    inline def [A, B](inline lhs: Opt[A]) map (inline rhs: A => B): Opt[B] = ${ mapMacro('lhs, 'rhs) }
  }
  private def mapMacro[A: Type, B: Type](lhs: Expr[Opt[A]], rhs: Expr[A => B])(using QuoteContext): Expr[Opt[B]] =
    lhs match
      case '{ $v: Opt[A] } =>
        '{
          val result = $v
          if result != null
            ${Expr.betaReduce(rhs)('result)}
          else
            null
        }

}

Compilation output

java.lang.AssertionError: assertion failed: unresolved symbols: value result(line 34) when pickling /home/lukaszl/IdeaProjects/dott-macro-experiments/src/main/scala/options/Opt.scala while compiling /home/lukaszl/IdeaProjects/dott-macro-experiments/src/main/scala/Main.scala, /home/lukaszl/IdeaProjects/dott-macro-experiments/src/main/scala/options/Opt.scala
[error] ## Exception when compiling 4 sources to /home/lukaszl/IdeaProjects/dott-macro-experiments/target/scala-0.23/classes
[error] java.lang.AssertionError: assertion failed: unresolved symbols: value result(line 34) when pickling /home/lukaszl/IdeaProjects/dott-macro-experiments/src/main/scala/options/Opt.scala
[error] dotty.DottyPredef$.assertFail(DottyPredef.scala:17)
[error] dotty.tools.dotc.core.tasty.TreePickler.pickle(TreePickler.scala:722)
[error] dotty.tools.dotc.core.quoted.PickledQuotes$.pickle(PickledQuotes.scala:103)
[error] dotty.tools.dotc.core.quoted.PickledQuotes$.pickleQuote(PickledQuotes.scala:34)
[error] dotty.tools.dotc.transform.ReifyQuotes$QuoteReifier.pickleAsTasty$1(ReifyQuotes.scala:182)
[error] dotty.tools.dotc.transform.ReifyQuotes$QuoteReifier.pickledQuote(ReifyQuotes.scala:194)
[error] dotty.tools.dotc.transform.ReifyQuotes$QuoteReifier.transformQuotation(ReifyQuotes.scala:145)
[error] dotty.tools.dotc.transform.TreeMapWithStages.op$1(TreeMapWithStages.scala:97)
[error] dotty.tools.dotc.transform.TreeMapWithStages.transform(TreeMapWithStages.scala:123)
[error] dotty.tools.dotc.transform.ReifyQuotes$QuoteReifier.op$1(ReifyQuotes.scala:364)
[error] dotty.tools.dotc.transform.ReifyQuotes$QuoteReifier.transform(ReifyQuotes.scala:366)
[error] dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1252)

expectation

no exception (I am not sure what the correct behavior is in this case)

nicolasstucki commented 4 years ago

Minimized to

import scala.quoted._
type Opt[A] = A | Null
object Opt {
  def f[T](x: T): T = x
  private def mapMacro[A: Type](v: Expr[Opt[A]])(using QuoteContext): Expr[Unit] =
    '{
      val result: Opt[A] = $v
      if result != null then
        ${f('{result})}
    }
}

This requires -Yexplicit-nulls.

It looks like we are missing a hole for the result.type ((result : Opt[evidence$1$_$1])).

**** pickling quote of
{
  {
    @scala.internal.quoted.CompileTime.quoteTypeTag() type evidence$1$_$2
       >: [[[ 0 | Any | ]]] <: [[[ 1 | Any | ]]]
    {{{ 2 | Opt[Any] | }}}.$asInstanceOf$[
      (result : Opt[evidence$1$_$1]) & evidence$1$_$2
    ]
  }
}