Skip to content

Macro inside inline fails Ycheck #4735

Closed
@nicolasstucki

Description

@nicolasstucki
import scala.annotation.tailrec
import scala.quoted._

object Macro {

  inline def unrolledForeach(inline unrollSize: Int, seq: Array[Int], f: => Int => Unit): Unit = // or f: Int => Unit
    ~unrolledForeachImpl(unrollSize, '(seq), '(f))

  private def unrolledForeachImpl(unrollSize: Int, seq: Expr[Array[Int]], f: Expr[Int => Unit]): Expr[Unit] = '{
    val size = (~seq).length
    assert(size % (~unrollSize.toExpr) == 0) // for simplicity of the implementation
    var i = 0
    while (i < size) {
      println("<log> start loop")
      ~{
        for (j <- new UnrolledRange(0, unrollSize)) '{
          val element = (~seq)(i + ~j.toExpr)
          ~f('(element)) // or `(~f)(element)` if `f` should not be inlined
        }
      }
      i += ~unrollSize.toExpr
    }

  }

  private class UnrolledRange(start: Int, end: Int) {
    def foreach(f: Int => Expr[Unit]): Expr[Unit] = {
      @tailrec def loop(i: Int, acc: Expr[Unit]): Expr[Unit] =
        if (i >= 0) loop(i - 1, '{ ~f(i); ~acc })
        else acc
      loop(end - 1, '())
    }
  }
}
import scala.quoted._

object Test {
  def main(args: Array[String]): Unit = {
    val arr = Array.tabulate[Int](21)(x => x)
    for (x <- new Unrolled(arr)) {
      System.out.println(2*x)
    }
  }


}
class Unrolled(arr: Array[Int]) extends AnyVal {
  inline def foreach(f: => Int => Unit): Unit = Macro.unrolledForeach(3, arr, f)
}

Fails Ycheck with

exception while typing inline def foreach(f: => Function1[Int, Unit]): Unit = Macro.unrolledForeach(3, this.inline$arr, f) of class class dotty.tools.dotc.ast.Trees$DefDef # 4391
exception while typing @scala.annotation.internal.SourceFile(
  "/Users/nicolasstucki/GitHub/dotty/tests/run/quote-unrolled-foreach/quoted_2.scala"
) final class Unrolled(arr: Array[Int]) extends AnyVal() { 
  private[this] val arr: Array[Int]
  inline def foreach(f: => Function1[Int, Unit]): Unit = Macro.unrolledForeach(3, this.inline$arr, f)
  def inline$arr: Array[Int] = Unrolled.this.arr
  override def hashCode(): Int = Unrolled.this.arr.hashCode()
  override def equals(x$0: Any): Boolean = 
    x$0 match 
      {
        case x$0 @ _: Unrolled @unchecked => this.arr.==(x$0.arr)
        case _ => false
      }
} of class class dotty.tools.dotc.ast.Trees$TypeDef # 4520
exception while typing package <empty> {
  import scala.quoted._
  final lazy module val Test: Test = new Test()
  @scala.annotation.internal.SourceFile(
    "/Users/nicolasstucki/GitHub/dotty/tests/run/quote-unrolled-foreach/quoted_2.scala"
  ) final module class Test() extends Object() { this: Test.type => 
    def main(args: Array[String]): Unit = 
      {
        val arr: Array[Int] = 
          Array.tabulate[Int](21)(
            {
              def $anonfun(x: Int): Int = x
              closure($anonfun)
            }
          )(scala.reflect.ClassTag.apply[Int](Integer.TYPE))
        /* inlined from Unrolled*/ 
          {
            val Unrolled_this: Unrolled = new Unrolled(arr)
            /* inlined from Macro*/ 
              {
                val seq: Array[Int] = Unrolled_this.inline$arr
                {
                  val size: Int = seq.length
                  assert(size.%(3).==(0))
                  var i: Int = 0
                  {
                    <label> def while$(): Unit = 
                      if i.<(size) then 
                        {
                          {
                            println("<log> start loop")
                            {
                              {
                                val element: Int = seq.apply(i.+(0))
                                {
                                  val x$1: Int = element
                                  {
                                    System.out.println(2.*(x$1))
                                  }
                                }
                              }
                              {
                                {
                                  val element: Int = seq.apply(i.+(1))
                                  {
                                    val x$2: Int = element
                                    {
                                      System.out.println(2.*(x$2))
                                    }
                                  }
                                }
                                {
                                  {
                                    val element: Int = seq.apply(i.+(2))
                                    {
                                      val x$3: Int = element
                                      {
                                        System.out.println(2.*(x$3))
                                      }
                                    }
                                  }
                                  ()
                                }
                              }
                            }
                            i = i.+(3)
                          }
                          while$()
                        }
                       else ()
                    while$()
                  }
                }
              }
          }
      }
  }
  @scala.annotation.internal.SourceFile(
    "/Users/nicolasstucki/GitHub/dotty/tests/run/quote-unrolled-foreach/quoted_2.scala"
  ) final class Unrolled(arr: Array[Int]) extends AnyVal() { 
    private[this] val arr: Array[Int]
    inline def foreach(f: => Function1[Int, Unit]): Unit = Macro.unrolledForeach(3, this.inline$arr, f)
    def inline$arr: Array[Int] = Unrolled.this.arr
    override def hashCode(): Int = Unrolled.this.arr.hashCode()
    override def equals(x$0: Any): Boolean = 
      x$0 match 
        {
          case x$0 @ _: Unrolled @unchecked => this.arr.==(x$0.arr)
          case _ => false
        }
  }
  final lazy module val Unrolled: Unrolled = new Unrolled()
  @scala.annotation.internal.SourceFile(
    "/Users/nicolasstucki/GitHub/dotty/tests/run/quote-unrolled-foreach/quoted_2.scala"
  ) final module class Unrolled() extends Object() { this: Unrolled.type =>}
} of class class dotty.tools.dotc.ast.Trees$PackageDef # 4733
*** error while checking /Users/nicolasstucki/GitHub/dotty/tests/run/quote-unrolled-foreach/quoted_2.scala after phase reifyQuotes ***

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions