I have an identity macro named `macroId` and an expression `expr` such
that type inference breaks on `macroId expr` compared to `expr`: while
the latter succeeds, the former gives a compile-time error because
type inference gives _a different result_.
Of course, that's a problem when trying to write more interesting
macros. I checked this on -M7 and on 2.10.x HEAD.
This bothers me — read on if that bothers you, too: a minimized bug
report follows. I plan to raise a ticket if this is accepted as valid,
and I can provide additional data on request.
## Identity macro [*1]:
def macroId(arg: Any) = macro macroId_impl
def macroId_impl(c: Context)(arg: c.Expr[Any]): c.Expr[Any] = arg
This is supposed to be an identity macro; I think you'll agree.
## Test expressions:
val coll: Exp[List[Int]] = ...
val f15_noMacro = {
coll map (i => i) /*Type inference makes this map[Int, List[Int]]*/
}
val f15 = macroId { //macroId is used here!
coll map (i => i) /*Type inference makes this map[Int, Any] which
causes a compile error.*/
}
where map is a pimped^H enriched method with signature:
def map[U, That <: Traversable[U] with TraversableLike[U, That]](f:
Exp[T] => Exp[U])(implicit c: CanBuildFrom[Repr, U, That]): Exp[That]
= ???
(For details see [*2]).
## Error text:
src/test/scala/ivm/expressiontree/MacroFailureMinimal.scala:27: error:
type arguments [Int,Any] do not conform to method map's type parameter
bounds [U,That <: Traversable[U] with
scala.collection.TraversableLike[U,That]]
coll map (i => i)
^
src/test/scala/ivm/expressiontree/MacroFailureMinimal.scala:31: error:
type arguments [Int,Any] do not conform to method map's type parameter
bounds [U,That <: Traversable[U] with
scala.collection.TraversableLike[U,That]]
coll map (i => i)
^
two errors found
## Additional experiments:
If inside macroId, I also call showRaw:
println("Stringify: " + arg.tree.toString)
println("showRaw: " + showRaw(arg.tree, printTypes = true, printIds = true))
I can verify that type inference is already complete (with Any instead
of the right result) at the time of this call.
Stringify: MacroFailureMinimalHelper.TraversableLikeOps[Int,
List[Int]](MacroFailureMinimalHelper.coll).map[Int, Any](((i: iv
m.expressiontree.MacroFailureMinimalHelper.Exp[Int]) =>
i))(immutable.this.List.canBuildFrom[Int])
showRaw: Apply[1](Apply[2](TypeApply[3](Select[4](Apply[5](TypeApply[6](Select[7](Ident[8](ivm.expressiontree.MacroFailureMin
imalHelper#11488), newTermName("TraversableLikeOps")#11524),
List(TypeTree[9](), TypeTree[10]())), List(Select[11](Ident[8](i
vm.expressiontree.MacroFailureMinimalHelper#11488),
newTermName("coll")#11529))), newTermName("map")#11536),
List(TypeTree[9]
(), TypeTree[12]())),
List(Function[13](List(ValDefNoType(Modifiers(PARAM),
newTermName("i"), TypeTree[14](), EmptyTree)), Id
ent[14](newTermName("i")#28098)))),
List(TypeApply[15](Select[16](Select[17](This[18](newTypeName("immutable")),
scala.collec
tion.immutable.List#15618), newTermName("canBuildFrom")#15876),
List(TypeTree[9]()))))
[...]
[12] TypeRef(ThisType(scala#19), scala.Any#3870, List()) //The culprit
type is here, it seems to me a normal scala.Any without surprises.
Furthermore, the problem only happens when the "problematic call" (to
map) is at the outer layer (close to the macro call). The following
works instead:
val f15_show_2 = macroId { //macroId is used here!
coll map (i => i) filter (_ => false) /*Calling filter here seems
to protect the call to map from this bug. filter's signature is simple
enough for this bug not to hit it.*/
}
*1
https://github.com/ps-mr/LinqOnSteroids/blob/topic/macro-bugreport/src/main/scala/ivm/expressiontree/MacroFrontend.scala#L44
*2
https://github.com/ps-mr/LinqOnSteroids/blob/topic/macro-bugreport/src/test/scala/ivm/expressiontree/MacroFailureMinimal.scala#L12
--
Paolo Giarrusso - Ph.D. Student, Philipps-University Marburg
http://www.informatik.uni-marburg.de/~pgiarrusso/