aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-11-13 22:24:09 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-11-14 11:46:08 +0100
commitdf2ebee249f94bbba273ce70a9a3331d07131230 (patch)
tree19c6e6cee5a84a22c42df6e981f94d131b2e5664
parent9500b044e05c3f676f29f1395f2036f145f84765 (diff)
downloadscala-async-df2ebee249f94bbba273ce70a9a3331d07131230.tar.gz
scala-async-df2ebee249f94bbba273ce70a9a3331d07131230.tar.bz2
scala-async-df2ebee249f94bbba273ce70a9a3331d07131230.zip
Fix crasher in icode due to symbol mismatches in lifted methods
These stem from the handling of the internal/external view or method type parameters by `thisMethodType` in `Namers`. I've now preseversed the orginal ValDefs favoured the latter when constructing the new DefDef, and made construction of all liftables consistent in this regard.
-rw-r--r--src/main/scala/scala/async/internal/Lifter.scala81
-rw-r--r--src/test/scala/scala/async/run/toughtype/ToughType.scala50
2 files changed, 94 insertions, 37 deletions
diff --git a/src/main/scala/scala/async/internal/Lifter.scala b/src/main/scala/scala/async/internal/Lifter.scala
index f49dcbb..295eb3f 100644
--- a/src/main/scala/scala/async/internal/Lifter.scala
+++ b/src/main/scala/scala/async/internal/Lifter.scala
@@ -105,45 +105,52 @@ trait Lifter {
}
val lifted = liftableSyms.map(symToTree).toList.map {
- case vd@ValDef(_, _, tpt, rhs) =>
- import reflect.internal.Flags._
- val sym = vd.symbol
- sym.setFlag(MUTABLE | STABLE | PRIVATE | LOCAL)
- sym.name = name.fresh(sym.name.toTermName)
- sym.modifyInfo(_.deconst)
- ValDef(vd.symbol, gen.mkZero(vd.symbol.info)).setPos(vd.pos)
- case dd@DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
- import reflect.internal.Flags._
- val sym = dd.symbol
- sym.name = this.name.fresh(sym.name.toTermName)
- sym.setFlag(PRIVATE | LOCAL)
- DefDef(dd.symbol, rhs).setPos(dd.pos)
- case cd@ClassDef(_, _, _, impl) =>
- import reflect.internal.Flags._
- val sym = cd.symbol
- sym.name = newTypeName(name.fresh(sym.name.toString).toString)
- companionship.companionOf(cd.symbol) match {
- case NoSymbol =>
- case moduleSymbol =>
- moduleSymbol.name = sym.name.toTermName
- moduleSymbol.moduleClass.name = moduleSymbol.name.toTypeName
- }
- ClassDef(cd.symbol, impl).setPos(cd.pos)
- case md@ModuleDef(_, _, impl) =>
- import reflect.internal.Flags._
- val sym = md.symbol
- companionship.companionOf(md.symbol) match {
- case NoSymbol =>
+ t =>
+ val treeLifted = t match {
+ case vd@ValDef(_, _, tpt, rhs) =>
+ import reflect.internal.Flags._
+ val sym = vd.symbol
+ sym.setFlag(MUTABLE | STABLE | PRIVATE | LOCAL)
sym.name = name.fresh(sym.name.toTermName)
- sym.moduleClass.name = sym.name.toTypeName
- case classSymbol => // will be renamed by `case ClassDef` above.
+ sym.modifyInfo(_.deconst)
+ val zeroRhs = atPos(t.pos)(gen.mkZero(vd.symbol.info))
+ treeCopy.ValDef(vd, Modifiers(sym.flags), sym.name, TypeTree(sym.tpe).setPos(t.pos), zeroRhs)
+ case dd@DefDef(_, _, tparams, vparamss, tpt, rhs) =>
+ import reflect.internal.Flags._
+ val sym = dd.symbol
+ sym.name = this.name.fresh(sym.name.toTermName)
+ sym.setFlag(PRIVATE | LOCAL)
+ // Was `DefDef(sym, rhs)`, but this ran afoul of `ToughTypeSpec.nestedMethodWithInconsistencyTreeAndInfoParamSymbols`
+ // due to the handling of type parameter skolems in `thisMethodType` in `Namers`
+ treeCopy.DefDef(dd, Modifiers(sym.flags), sym.name, tparams, vparamss, tpt, rhs)
+ case cd@ClassDef(_, _, tparams, impl) =>
+ import reflect.internal.Flags._
+ val sym = cd.symbol
+ sym.name = newTypeName(name.fresh(sym.name.toString).toString)
+ companionship.companionOf(cd.symbol) match {
+ case NoSymbol =>
+ case moduleSymbol =>
+ moduleSymbol.name = sym.name.toTermName
+ moduleSymbol.moduleClass.name = moduleSymbol.name.toTypeName
+ }
+ treeCopy.ClassDef(cd, Modifiers(sym.flags), sym.name, tparams, impl)
+ case md@ModuleDef(_, _, impl) =>
+ import reflect.internal.Flags._
+ val sym = md.symbol
+ companionship.companionOf(md.symbol) match {
+ case NoSymbol =>
+ sym.name = name.fresh(sym.name.toTermName)
+ sym.moduleClass.name = sym.name.toTypeName
+ case classSymbol => // will be renamed by `case ClassDef` above.
+ }
+ treeCopy.ModuleDef(md, Modifiers(sym.flags), sym.name, impl)
+ case td@TypeDef(_, _, tparams, rhs) =>
+ import reflect.internal.Flags._
+ val sym = td.symbol
+ sym.name = newTypeName(name.fresh(sym.name.toString).toString)
+ treeCopy.TypeDef(td, Modifiers(sym.flags), sym.name, tparams, rhs)
}
- ModuleDef(md.symbol, impl).setPos(md.pos)
- case td@TypeDef(_, _, _, rhs) =>
- import reflect.internal.Flags._
- val sym = td.symbol
- sym.name = newTypeName(name.fresh(sym.name.toString).toString)
- TypeDef(td.symbol, rhs).setPos(td.pos)
+ atPos(t.pos)(treeLifted)
}
lifted
}
diff --git a/src/test/scala/scala/async/run/toughtype/ToughType.scala b/src/test/scala/scala/async/run/toughtype/ToughType.scala
index b342a00..1551856 100644
--- a/src/test/scala/scala/async/run/toughtype/ToughType.scala
+++ b/src/test/scala/scala/async/run/toughtype/ToughType.scala
@@ -135,9 +135,59 @@ class ToughTypeSpec {
}
foo
}
+
+ // This test was failing when lifting `def r` with:
+ // symbol value m#10864 does not exist in r$1
+ //
+ // We generated:
+ //
+ // private[this] def r$1#5727[A#5728 >: Nothing#157 <: Any#156](m#5731: Foo#2349[A#5728]): Unit#208 = Bippy#2352.this.bar#5532({
+ // m#5730;
+ // ()
+ // });
+ //
+ // Notice the incorrect reference to `m`.
+ //
+ // We compensated in `Lifter` by copying `ValDef` parameter symbols directly across.
+ //
+ // Turns out the behaviour stems from `thisMethodType` in `Namers`, which treats type parameter skolem symbols.
+ @Test def nestedMethodWithInconsistencyTreeAndInfoParamSymbols() {
+ import language.{reflectiveCalls, postfixOps}
+ import scala.concurrent.{Future, ExecutionContext, future, Await}
+ import scala.concurrent.duration._
+ import scala.async.Async.{async, await}
+ import scala.async.internal.AsyncId
+
+ class Foo[A]
+
+ object Bippy {
+
+ import ExecutionContext.Implicits.global
+
+ def bar(f: => Unit): Unit = f
+
+ def quux: Future[String] = ???
+
+ def foo = async {
+ def r[A](m: Foo[A])(n: A) = {
+ bar {
+ locally(m)
+ locally(n)
+ identity[A] _
+ }
+ }
+
+ await(quux)
+
+ r(new Foo[String])("")
+ }
+ }
+ Bippy
+ }
}
trait A
+
trait B
trait L[A2, B2 <: A2] {