From 8aae61180c3edab97c653dbc7096a439f5c3da12 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sat, 15 Dec 2012 16:38:10 -0800 Subject: Deskolemize type skolems before pickling. Lex Spoon noticed what appeared to be duplicate symbols in methods read from classfiles. The duplicates turned out to be type skolems, which because they're not supposed to be pickled in the first place (right?) are unpickled without turning back into skolems. Now pickler is careful to deskolemize before writing anything down. The effort implied by test case is more than can possibly be justified for this obscure compiler corner, but I'll chalk it up to reflection exploration. --- test/files/run/no-pickle-skolems.check | 1 + test/files/run/no-pickle-skolems/Source_1.scala | 5 ++++ test/files/run/no-pickle-skolems/Test_2.scala | 37 +++++++++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 test/files/run/no-pickle-skolems.check create mode 100644 test/files/run/no-pickle-skolems/Source_1.scala create mode 100644 test/files/run/no-pickle-skolems/Test_2.scala (limited to 'test/files') diff --git a/test/files/run/no-pickle-skolems.check b/test/files/run/no-pickle-skolems.check new file mode 100644 index 0000000000..d64066171a --- /dev/null +++ b/test/files/run/no-pickle-skolems.check @@ -0,0 +1 @@ +OK! diff --git a/test/files/run/no-pickle-skolems/Source_1.scala b/test/files/run/no-pickle-skolems/Source_1.scala new file mode 100644 index 0000000000..1b4cbfa788 --- /dev/null +++ b/test/files/run/no-pickle-skolems/Source_1.scala @@ -0,0 +1,5 @@ +package s + +trait Foo { def to[CC[X]](implicit cc: CC[Int]): Unit } + +class Bar extends Foo { def to[CC[X]](implicit cc: CC[Int]): Unit = ??? } diff --git a/test/files/run/no-pickle-skolems/Test_2.scala b/test/files/run/no-pickle-skolems/Test_2.scala new file mode 100644 index 0000000000..90bb4c4f88 --- /dev/null +++ b/test/files/run/no-pickle-skolems/Test_2.scala @@ -0,0 +1,37 @@ +import scala.reflect.runtime.universe._ + +object Test { + /** Collects symbols by the given name, even if they're not + * named CC. + */ + def collectSymbols[T: TypeTag](inMethod: TermName, name: String): List[String] = { + val m = typeOf[T] member inMethod typeSignatureIn typeOf[T] + var buf: List[Symbol] = Nil + var seen: Set[Symbol] = Set() + def id(s: Symbol): Int = s.asInstanceOf[{ def id: Int }].id + + def check(s: Symbol) { + if (!seen(s)) { + seen += s + if (s.name.toString == name) buf ::= s + } + } + def loop(t: Type) { + t match { + case TypeRef(pre, sym, args) => loop(pre) ; check(sym) ; args foreach loop + case PolyType(tparams, restpe) => tparams foreach { tp => check(tp) ; check(tp.owner) ; loop(tp.typeSignature) } ; loop(restpe) + case MethodType(params, restpe) => params foreach { p => check(p) ; loop(p.typeSignature) } ; loop(restpe) + case _ => + } + } + loop(m) + + buf.reverse.distinct map (s => s.name + "#" + id(s)) + } + + def main(args: Array[String]): Unit = { + val syms = collectSymbols[s.Bar]("to", "CC") + assert(syms.size == 1, syms) + println("OK!") + } +} -- cgit v1.2.3