summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-03-22 17:18:09 +0000
committerMartin Odersky <odersky@gmail.com>2011-03-22 17:18:09 +0000
commitfda6c9517efc154c8516acaf139f4a547a9e4575 (patch)
tree70da007ca986b175b2a13d4181c88347740d6133 /src/compiler
parent87eb32c61a2bd5be1afaadad6ab7b367dc0c3848 (diff)
downloadscala-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.scala33
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala57
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) = {