summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-03-02 02:34:54 +0000
committerPaul Phillips <paulp@improving.org>2011-03-02 02:34:54 +0000
commite42733e9fe1f3af591976fbb48b66035253d85b9 (patch)
treef91c3aef289cb7e58347484d1375437b2230e729 /src/compiler
parent2021f393627c8a853248a5d6178b86f3d5d7f763 (diff)
downloadscala-e42733e9fe1f3af591976fbb48b66035253d85b9.tar.gz
scala-e42733e9fe1f3af591976fbb48b66035253d85b9.tar.bz2
scala-e42733e9fe1f3af591976fbb48b66035253d85b9.zip
Another lap around the track with generic signa...
Another lap around the track with generic signatures. At the root of the issue reported in #4214 is our old friend (fondly remembered from the days of primitive equality) boxed/primitive unification. // scala trait T[A] { def f(): A } // the generic signature spec doesn't allow for parameterizing // on primitive types, so this cannot remain Char. However // translating it to Character, as was done, also has issues. class C extends T[Char] { def f(): Char = 'a' } // Note that neither of the signatures for f, the implementation // or the bridge method, matches the type parameter. Generic interfaces in class: T<java.lang.Character> Generic signatures: public char C.f() public java.lang.Object C.f() After this commit, primitive type parameters are translated into Object instead of the boxed type. It was martin's idea, so no review. Closes #4214.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala81
1 files changed, 39 insertions, 42 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index a9a9180495..015481b97a 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -226,38 +226,39 @@ abstract class Erasure extends AddInterfaces
* type for constructors.
*/
def javaSig(sym0: Symbol, info: Type): Option[String] = atPhase(currentRun.erasurePhase) {
- def jsig(tp: Type, mustBox: Boolean) = {
- (boxedClass get tp.typeSymbol) match {
- case Some(boxed) if mustBox => jsig2(false, true, Nil, boxed.tpe)
- case _ => jsig2(false, mustBox, Nil, tp)
- }
- }
- def hiBounds(bounds: TypeBounds): List[Type] = bounds.hi.normalize match {
+ def jsig(tp: Type): String = jsig2(false, Nil, tp)
+
+ def boxedSig(tp: Type) = jsig(squashBoxed(tp))
+ def squashBoxed(tp: Type) =
+ if (boxedClass contains tp.typeSymbol) ObjectClass.tpe
+ else tp
+
+ def hiBounds(bounds: TypeBounds): List[Type] = (bounds.hi.normalize match {
case RefinedType(parents, _) => parents map normalize
- case tp => List(tp)
- }
+ case tp => tp :: Nil
+ }) map squashBoxed
- def jsig2(toplevel: Boolean, mustBox: Boolean, tparams: List[Symbol], tp0: Type): String = {
+ def jsig2(toplevel: Boolean, tparams: List[Symbol], tp0: Type): String = {
val tp = tp0.dealias
tp match {
case st: SubType =>
- jsig2(toplevel, mustBox, tparams, st.supertype)
+ jsig2(toplevel, tparams, st.supertype)
case ExistentialType(tparams, tpe) =>
- jsig2(toplevel, true, tparams, tpe)
+ jsig2(toplevel, tparams, tpe)
case TypeRef(pre, sym, args) =>
def argSig(tp: Type) =
if (tparams contains tp.typeSymbol) {
val bounds = tp.typeSymbol.info.bounds
if (AnyRefClass.tpe <:< bounds.hi) {
if (bounds.lo <:< NullClass.tpe) "*"
- else "-" + jsig(bounds.lo, true)
+ else "-" + boxedSig(bounds.lo)
}
- else "+" + jsig(bounds.hi, true)
+ else "+" + boxedSig(bounds.hi)
}
else if (tp.typeSymbol == UnitClass) {
- jsig(ObjectClass.tpe, true)
+ jsig(ObjectClass.tpe)
} else {
- jsig(tp, true)
+ boxedSig(tp)
}
def classSig = (
"L"+atPhase(currentRun.icodePhase)(sym.fullName + global.genJVM.moduleSuffix(sym)).replace('.', '/')
@@ -266,27 +267,27 @@ abstract class Erasure extends AddInterfaces
// If args isEmpty, Array is being used as a higher-kinded type
if (sym == ArrayClass && args.nonEmpty) {
- if (unboundedGenericArrayLevel(tp) == 1) jsig(ObjectClass.tpe, true)
- else ARRAY_TAG.toString+(args map (x => jsig(x, false))).mkString
+ if (unboundedGenericArrayLevel(tp) == 1) jsig(ObjectClass.tpe)
+ else ARRAY_TAG.toString+(args map jsig).mkString
}
else if (isTypeParameterInSig(sym))
TVAR_TAG.toString+sym.name+";"
else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass)
- jsig(ObjectClass.tpe, mustBox)
+ jsig(ObjectClass.tpe)
else if (sym == UnitClass)
- jsig(BoxedUnitClass.tpe, mustBox)
+ jsig(BoxedUnitClass.tpe)
else if (sym == NothingClass)
- jsig(RuntimeNothingClass.tpe, mustBox)
+ jsig(RuntimeNothingClass.tpe)
else if (sym == NullClass)
- jsig(RuntimeNullClass.tpe, mustBox)
+ jsig(RuntimeNullClass.tpe)
else if (isValueClass(sym))
- abbrvTag(sym).toString
+ jsig(ObjectClass.tpe)
else if (sym.isClass) {
val preRebound = pre.baseType(sym.owner) // #2585
dotCleanup(
(
if (needsJavaSig(preRebound)) {
- val s = jsig(preRebound, mustBox)
+ val s = jsig(preRebound)
if (s.charAt(0) == 'L') s.substring(0, s.length - 1) + classSigSuffix
else classSig
}
@@ -299,47 +300,43 @@ abstract class Erasure extends AddInterfaces
)
)
}
- else jsig(erasure(tp), mustBox)
+ else jsig(erasure(tp))
case PolyType(tparams, restpe) =>
assert(tparams.nonEmpty)
def boundSig(bounds: List[Type]) = {
val (isTrait, isClass) = bounds partition (_.typeSymbol.isTrait)
":" + (
- if (isClass.isEmpty) "" else jsig(isClass.head, true)
+ if (isClass.isEmpty) "" else boxedSig(isClass.head)
) + (
- isTrait map (x => ":" + jsig(x, true)) mkString
+ isTrait map (x => ":" + boxedSig(x)) mkString
)
}
def paramSig(tsym: Symbol) = tsym.name + boundSig(hiBounds(tsym.info.bounds))
val paramString = if (toplevel) tparams map paramSig mkString ("<", "", ">") else ""
- paramString + jsig(restpe, false)
+ paramString + jsig(restpe)
case MethodType(params, restpe) =>
- "("+(params map (_.tpe) map (x => jsig(x, false))).mkString+")"+
- (if (restpe.typeSymbol == UnitClass || sym0.isConstructor) VOID_TAG.toString else jsig(restpe, false))
- case RefinedType(parents, decls) if (!parents.isEmpty) =>
- jsig(parents.head, mustBox)
+ "("+(params map (_.tpe) map jsig).mkString+")"+
+ (if (restpe.typeSymbol == UnitClass || sym0.isConstructor) VOID_TAG.toString else jsig(restpe))
+ case RefinedType(parent :: _, decls) =>
+ jsig(parent)
case ClassInfoType(parents, _, _) =>
- (parents map (x => jsig(x, true))).mkString
+ (parents map jsig).mkString
case AnnotatedType(_, atp, _) =>
- jsig(atp, mustBox)
+ jsig(atp)
case BoundedWildcardType(bounds) =>
println("something's wrong: "+sym0+":"+sym0.tpe+" has a bounded wildcard type")
- jsig(bounds.hi, true)
+ jsig(bounds.hi)
case _ =>
val etp = erasure(tp)
if (etp eq tp) throw new UnknownSig
- else jsig(etp, mustBox)
+ else jsig(etp)
}
}
if (needsJavaSig(info)) {
- try {
- //println("Java sig of "+sym0+" is "+jsig2(true, List(), sym0.info))//DEBUG
- Some(jsig2(true, false, Nil, info))
- } catch {
- case ex: UnknownSig => None
- }
+ try Some(jsig2(true, Nil, info))
+ catch { case ex: UnknownSig => None }
}
else None
}