diff options
author | Martin Odersky <odersky@gmail.com> | 2011-03-22 17:18:09 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2011-03-22 17:18:09 +0000 |
commit | fda6c9517efc154c8516acaf139f4a547a9e4575 (patch) | |
tree | 70da007ca986b175b2a13d4181c88347740d6133 /src/compiler | |
parent | 87eb32c61a2bd5be1afaadad6ab7b367dc0c3848 (diff) | |
download | scala-fda6c9517efc154c8516acaf139f4a547a9e4575.tar.gz scala-fda6c9517efc154c8516acaf139f4a547a9e4575.tar.bz2 scala-fda6c9517efc154c8516acaf139f4a547a9e4575.zip |
Added test that signatures conform to their era...
Added test that signatures conform to their erasures. Work in progress.
Review by extempore.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala | 33 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 57 |
2 files changed, 76 insertions, 14 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 9a1bafa27f..fb253d1ddc 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -572,22 +572,29 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid { * in which case we treat every signature as valid. Medium term we * should certainly write independent signature validation. */ - if (!SigParser.isParserAvailable || isValidSignature(sym, sig)) { - val index = jmember.getConstantPool.addUtf8(sig).toShort - if (opt.verboseDebug) - atPhase(currentRun.erasurePhase) { - println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index) - } - val buf = ByteBuffer.allocate(2) - buf putShort index - addAttribute(jmember, tpnme.SignatureATTR, buf) - } - else clasz.cunit.warning(sym.pos, + if (SigParser.isParserAvailable && isValidSignature(sym, sig)) { + val normalizedTpe = erasure.prepareSigMap(memberTpe) + val bytecodeTpe = owner.thisType.memberInfo(sym) + if (erasure.erasure(normalizedTpe) =:= bytecodeTpe) { + val index = jmember.getConstantPool.addUtf8(sig).toShort + if (opt.verboseDebug) + atPhase(currentRun.erasurePhase) { + println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index) + } + val buf = ByteBuffer.allocate(2) + buf putShort index + addAttribute(jmember, tpnme.SignatureATTR, buf) + } else clasz.cunit.warning(sym.pos, + """|compiler bug: created generic signature for %s in %s that does not conform to its erasure + |signature: %s + |erasure type: %s + |if this is reproducible, please report bug at http://lampsvn.epfl.ch/trac/scala + """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig, bytecodeTpe)) + } else clasz.cunit.warning(sym.pos, """|compiler bug: created invalid generic signature for %s in %s |signature: %s |if this is reproducible, please report bug at http://lampsvn.epfl.ch/trac/scala - """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig) - ) + """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig)) } } } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 3f94e165a1..00ef2279d6 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -231,11 +231,66 @@ abstract class Erasure extends AddInterfaces // for debugging signatures: traces logic given system property private val traceSig = util.Tracer(sys.props contains "scalac.sigs.trace") + val prepareSigMap = new TypeMap { + def squashBoxed(tp: Type): Type = tp.normalize match { + case t @ RefinedType(parents, decls) => + val parents1 = parents mapConserve squashBoxed + if (parents1 eq parents) tp + else RefinedType(parents1, decls) + case t => + if (boxedClass contains t.typeSymbol) ObjectClass.tpe + else tp + } + def apply(tp: Type): Type = tp.normalize match { + case tp1 @ TypeBounds(lo, hi) => + val lo1 = squashBoxed(apply(lo)) + val hi1 = squashBoxed(apply(hi)) + if ((lo1 eq lo) && (hi1 eq hi)) tp1 + else TypeBounds(lo1, hi1) + case tp1 @ TypeRef(pre, sym, args) => + def argApply(tp: Type) = { + val tp1 = apply(tp) + if (tp1.typeSymbol == UnitClass) ObjectClass.tpe + else squashBoxed(tp1) + } + if (sym == ArrayClass && args.nonEmpty) + if (unboundedGenericArrayLevel(tp) == 1) ObjectClass.tpe + else mapOver(tp1) + else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass) + ObjectClass.tpe + else if (sym == UnitClass) + BoxedUnitClass.tpe + else if (sym == NothingClass) + RuntimeNothingClass.tpe + else if (sym == NullClass) + RuntimeNullClass.tpe + else { + val pre1 = apply(pre) + val args1 = args mapConserve argApply + if ((pre1 eq pre) && (args1 eq args)) tp1 + else TypeRef(pre1, sym, args1) + } + case tp1 @ MethodType(params, restpe) => + val params1 = mapOver(params) + val restpe1 = if (restpe.normalize.typeSymbol == UnitClass) UnitClass.tpe else apply(restpe) + if ((params1 eq params) && (restpe1 eq restpe)) tp1 + else MethodType(params1, restpe1) + case tp1 @ RefinedType(parents, decls) => + val parents1 = parents mapConserve apply + if (parents1 eq parents) tp1 + else RefinedType(parents1, decls) + case tp1: ClassInfoType => + tp1 + case tp1 => + mapOver(tp1) + } + } + /** The Java signature of type 'info', for symbol sym. The symbol is used to give the right return * type for constructors. */ def javaSig(sym0: Symbol, info: Type): Option[String] = atPhase(currentRun.erasurePhase) { - def jsig(tp: Type): String = jsig2(false, Nil, tp) + def jsig(tp: Type): String = jsig2(toplevel = false, Nil, tp) // Unit in return position is 'V', but that cannot appear elsewhere. def unboxedSig(tpe: Type, isReturnPosition: Boolean) = { |