Scala Programming Language
  1. Scala Programming Language
  2. SI-6281

implicit params of macro defs don't play well with context bounds of macro impls

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Blocker Blocker
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: Scala 2.10.0-M7
    • Component/s: Macros
    • Labels:
      None

      Description

      import annotation.tailrec
      import scala.math.{min, max}
      import scala.{specialized => spec}
      
      import language.experimental.macros
      
      import scala.reflect.{ClassTag, TypeTag}
      import scala.reflect.macros.Context
      
      object Macros {
        def alloc[@spec A:ClassTag](src:Array[A], s1:Int, len:Int) = {
          val as = Array.ofDim[A](len)
          System.arraycopy(src, s1, as, 0, len)
          as
        }
      
        /**
         * Efficient alternative to Array.apply.
         *
         * "As seen on scala-internals!"
         */
        def array[A](as:A*)(implicit ct: ClassTag[A]) = macro arrayMacro[A]
      
        /**
         * Takes in something like:
         *   ArrayUtil.alloc[Int](11, 22, 33, 44)(ct)
         *
         * and builds a tree like:
         *   {
         *     val arr:Array[Int] = ct.newArray(4)
         *     arr.update(0, 11)
         *     arr.update(1, 22)
         *     arr.update(2, 33)
         *     arr.update(3, 44)
         *     arr
         *   }
         */
        def arrayMacro[A:c.AbsTypeTag](c:Context)(as:c.Expr[A]*)(ct: c.Expr[ClassTag[A]]): c.Expr[Array[A]] = {
          import c.mirror._
          import c.universe._
          def const(x:Int) = Literal(Constant(x))
      
          val n = as.length
          val arr = newTermName("arr")
      
          val create = Apply(Select(ct.tree, "newArray"), List(const(n)))
          val arrtpe = TypeTree(implicitly[c.AbsTypeTag[Array[A]]].tpe)
          val valdef = ValDef(Modifiers(), arr, arrtpe, create)
      
          val updates = (0 until n).map {
            i => Apply(Select(Ident(arr), "update"), List(const(i), as(i).tree))
          }
      
          val exprs = Seq(valdef) ++ updates ++ Seq(Ident(arr))
          val block = Block(exprs:_*)
      
          c.Expr[Array[A]](block)
        }
      }
      
      object Test extends App {
        import Macros._
        println(array(1, 2, 3))
      }
      
      C:\Projects\Kepler\sandbox @ 2.10.x>myke compile .
      Test_2.scala:3: error: exception during macro expansion:
      java.lang.IllegalArgumentException: argument type mismatch
      
        println(array(1, 2, 3))
                     ^
      one error found
      

        Activity

        Show
        Eugene Burmako added a comment - https://github.com/scala/scala/pull/1194
        Hide
        Eugene Burmako added a comment -

        Workaround: use context bounds, remove implicit parameters from a macro def and summon them manually in a macro impl using c.inferImplicitValue.

        Show
        Eugene Burmako added a comment - Workaround: use context bounds, remove implicit parameters from a macro def and summon them manually in a macro impl using c.inferImplicitValue.

          People

          • Assignee:
            Eugene Burmako
            Reporter:
            Eugene Burmako
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development