diff options
author | Lukas Rytz <lukas.rytz@gmail.com> | 2015-10-26 15:47:54 +0100 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2015-10-26 17:16:07 +0100 |
commit | 4a5a800d4606d917289dc14c35f2035e83f58953 (patch) | |
tree | 1ed0ae3e948fc6de0f3bd451ae85e5dbdaacc7d5 /src/compiler | |
parent | 462dc9af886391c9c31cb6949b15e69b0cab55ef (diff) | |
download | scala-4a5a800d4606d917289dc14c35f2035e83f58953.tar.gz scala-4a5a800d4606d917289dc14c35f2035e83f58953.tar.bz2 scala-4a5a800d4606d917289dc14c35f2035e83f58953.zip |
SI-9535 correct bytecode and generic signatures for @throws[TypeParam]
For @throws[E] where E is not a class type, GenASM incorrectly writes
the non-class type to the classfile. GenBCode used to crash before
this commit. Now GenBCode correctly emits the erased type (like
javac) and adds a generic signature.
Diffstat (limited to 'src/compiler')
4 files changed, 32 insertions, 15 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index bc3bdfc6ba..3cdc37ad21 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -542,11 +542,15 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { * must-single-thread */ def addRemoteExceptionAnnot(isRemoteClass: Boolean, isJMethodPublic: Boolean, meth: Symbol) { - val needsAnnotation = ( - ( isRemoteClass || - isRemote(meth) && isJMethodPublic - ) && !(meth.throwsAnnotations contains definitions.RemoteExceptionClass) - ) + def hasThrowsRemoteException = meth.annotations.exists { + case ThrownException(exc) => exc.typeSymbol == definitions.RemoteExceptionClass + case _ => false + } + val needsAnnotation = { + (isRemoteClass || + isRemote(meth) && isJMethodPublic + ) && !hasThrowsRemoteException + } if (needsAnnotation) { val c = Constant(definitions.RemoteExceptionClass.tpe) val arg = Literal(c) setType c.tpe @@ -655,8 +659,11 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { * must-single-thread */ def getExceptions(excs: List[AnnotationInfo]): List[String] = { - for (ThrownException(exc) <- excs.distinct) - yield internalName(exc) + for (ThrownException(tp) <- excs.distinct) + yield { + val erased = enteringErasure(erasure.erasure(tp.typeSymbol)(tp)) + internalName(erased.typeSymbol) + } } } // end of trait BCForwardersGen diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 61abc55501..4424a3796b 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -891,8 +891,11 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self => * This method returns such list of internal names. */ def getExceptions(excs: List[AnnotationInfo]): List[String] = - for (ThrownException(exc) <- excs.distinct) - yield javaName(exc) + for (ThrownException(tp) <- excs.distinct) + yield { + val erased = enteringErasure(erasure.erasure(tp.typeSymbol)(tp)) + javaName(erased.typeSymbol) + } def getCurrentCUnit(): CompilationUnit @@ -995,10 +998,14 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self => * Invoked from genMethod() and addForwarder(). */ def addRemoteExceptionAnnot(isRemoteClass: Boolean, isJMethodPublic: Boolean, meth: Symbol) { + def hasThrowsRemoteException = meth.annotations.exists { + case ThrownException(exc) => exc.typeSymbol == definitions.RemoteExceptionClass + case _ => false + } val needsAnnotation = ( ( isRemoteClass || isRemote(meth) && isJMethodPublic - ) && !(meth.throwsAnnotations contains RemoteExceptionClass) + ) && !hasThrowsRemoteException ) if (needsAnnotation) { val c = Constant(RemoteExceptionClass.tpe) diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 833f25537c..747d20a441 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -71,7 +71,9 @@ abstract class Erasure extends AddInterfaces } override protected def verifyJavaErasure = settings.Xverify || settings.debug - def needsJavaSig(tp: Type) = !settings.Ynogenericsig && NeedsSigCollector.collect(tp) + def needsJavaSig(tp: Type, throwsArgs: List[Type]) = !settings.Ynogenericsig && { + NeedsSigCollector.collect(tp) || throwsArgs.exists(NeedsSigCollector.collect) + } // only refer to type params that will actually make it into the sig, this excludes: // * higher-order type parameters @@ -277,7 +279,7 @@ abstract class Erasure extends AddInterfaces val preRebound = pre.baseType(sym.owner) // #2585 dotCleanup( ( - if (needsJavaSig(preRebound)) { + if (needsJavaSig(preRebound, Nil)) { val s = jsig(preRebound, existentiallyBound) if (s.charAt(0) == 'L') s.substring(0, s.length - 1) + "." + sym.javaSimpleName else fullNameInSig(sym) @@ -356,8 +358,9 @@ abstract class Erasure extends AddInterfaces else jsig(etp) } } - if (needsJavaSig(info)) { - try Some(jsig(info, toplevel = true)) + val throwsArgs = sym0.annotations flatMap ThrownException.unapply + if (needsJavaSig(info, throwsArgs)) { + try Some(jsig(info, toplevel = true) + throwsArgs.map("^" + jsig(_, toplevel = true)).mkString("")) catch { case ex: UnknownSig => None } } else None diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 45ebbd532d..510c83eb88 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3653,7 +3653,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val annType = annTpt.tpe finish( - if (typedFun.isErroneous) + if (typedFun.isErroneous || annType == null) ErroneousAnnotation else if (annType.typeSymbol isNonBottomSubClass ClassfileAnnotationClass) { // annotation to be saved as java classfile annotation |