Open smithjessk opened 8 years ago
This test generates this problematic rawlambda
:
raw = (() => {
val f: PartialFunction[Int,Int] = (({
class $anonfun extends scala.runtime.AbstractPartialFunction[Int,Int] with Serializable {
def <init>(): <$anon: Int => Int> = {
$anonfun.super.<init>();
()
};
final override def applyOrElse[A1 <: Int, B1 >: Int](x1: A1, default: A1 => B1): B1 = ((x1.asInstanceOf[Int]: Int): Int @unchecked) match {
case (x @ _) => x.+(1)
case (defaultCase$ @ _) => default.apply(x1)
};
final def isDefinedAt(x1: Int): Boolean = ((x1.asInstanceOf[Int]: Int): Int @unchecked) match {
case (x @ _) => true
case (defaultCase$ @ _) => false
}
};
new $anonfun()
}: PartialFunction[Int,Int]): PartialFunction[Int,Int]);
AsyncAwaitTest.await[Int].apply[(scala.concurrent.Future[Int], org.coroutines.AsyncAwaitTest.Cell[Int]), Int](scala.concurrent.Future.apply[Int](f.apply(2))(scala.concurrent.ExecutionContext.Implicits.global))(Predef.this.=:=.tpEquals[((scala.concurrent.Future[Int], org.coroutines.AsyncAwaitTest.Cell[Int]), Int)])
})
Canonicalization fails when going over default.apply(x1)
.
typer.typeOf(co) == null
because default
is never added to typer.treeMapping
and co.tpe == null
. default
is never added because this case does not cause traversal of the second cases inside the above partial functions.
Can you extend traverser to correctly cover the other cases?
Yes! I'm working on it in this branch.
It is not the second case that is dropped by the quasiquotes. Rather, it is the default case, e.g.:
case (defaultCase$ @ _) => default.apply(x1)
For instance, see that this partial function:
val f = {
case x: Int => x + 1
case x: String => x.length
}: PartialFunction[Any, Int]
has the following values for cs0
and cs1
, respectively:
List(case (x @ (_: scala.Int)) => x.+(1), case (x @ (_: scala.this.Predef.String)) => x.length())
List(case (x @ (_: Int)) => x.+(1), case (x @ (_: String)) => x.length())
Thus, we might want to stop canonicalization for the default cases. What do you think?
No, that's not the problem.
Add a println
statement to case _
in TraverserUtil
. The anonymous partial function class was not traversed by it for some reason. Find out why, fix TraverserUtil
, and this should work.
I think I'm misunderstanding your statement.
The partial function case matches on the anonymous partial function. This call to traverse is caused by the ascription case, in which e0
is the anonymous class that extends AbstractPartialFunction
.
println("t0 = " + t0)
inside the PF case prints the following output:
t0 = ({
final <synthetic> class $anonfun extends scala.runtime.AbstractPartialFunction[Int,Int] with Serializable {
def <init>() = {
super.<init>();
()
};
final override def applyOrElse[A1 <: Int, B1 >: Int](x1: A1, default: scala.this.Function1[A1, B1]) = ((x1.asInstanceOf[Int]: Int): (x1.asInstanceOf[Int]: Int): @scala.unchecked) match {
case (x @ _) => x.+(1)
case (defaultCase$ @ _) => default.apply(x1)
};
final def isDefinedAt(x1: Int): Boolean = ((x1.asInstanceOf[Int]: Int): (x1.asInstanceOf[Int]: Int): @scala.unchecked) match {
case (x @ _) => true
case (defaultCase$ @ _) => false
}
};
new $anonfun()
}: PartialFunction[Int,Int])
However, defaultCase
is not a part of cs0
.
Demo code: https://git.io/vrHmh
As recommended in #15, I'm porting some of the tests from Async into Coroutines. I translated this test and discovered a
NullPointerException
during compilation. A truncated SBT dump is at the bottom of this issue. I believe this may be related to @retronym's comment in #15. I will investigate this more soon; just wanted to go ahead and bring the issue up.