diff options
author | Lukas Rytz <lukas.rytz@typesafe.com> | 2015-10-27 09:03:15 +0100 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@typesafe.com> | 2015-10-27 09:03:15 +0100 |
commit | 4321ea458ad1258f273ee22a4c6a7606ab054501 (patch) | |
tree | fe68843b632bda3eed3066a83f66b5249dbb86dd /src | |
parent | b194a4e7230334e441cd31b617fdce8e329dfa3a (diff) | |
parent | 4a5a800d4606d917289dc14c35f2035e83f58953 (diff) | |
download | scala-4321ea458ad1258f273ee22a4c6a7606ab054501.tar.gz scala-4321ea458ad1258f273ee22a4c6a7606ab054501.tar.bz2 scala-4321ea458ad1258f273ee22a4c6a7606ab054501.zip |
Merge pull request #4820 from lrytz/t9535
SI-9535 correct bytecode and generic signatures for @throws[TypeParam]
Diffstat (limited to 'src')
6 files changed, 38 insertions, 27 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index a48a437ed7..d501d4239b 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -490,11 +490,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 @@ -603,8 +607,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 diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala index b923541b56..207a66e360 100644 --- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala +++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala @@ -30,12 +30,6 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => def staticAnnotations = annotations filter (_.isStatic) - /** Symbols of any @throws annotations on this symbol. - */ - def throwsAnnotations(): List[Symbol] = annotations collect { - case ThrownException(exc) => exc - } - def addThrowsAnnotation(throwableSym: Symbol): Self = { val throwableTpe = if (throwableSym.isMonomorphicType) throwableSym.tpe else { debuglog(s"Encountered polymorphic exception `${throwableSym.fullName}` while parsing class file.") @@ -406,24 +400,24 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => class ErroneousAnnotation() extends CompleteAnnotationInfo(ErrorType, Nil, Nil) - /** Extracts symbol of thrown exception from AnnotationInfo. + /** Extracts the type of the thrown exception from an AnnotationInfo. * * Supports both “old-style” `@throws(classOf[Exception])` * as well as “new-stye” `@throws[Exception]("cause")` annotations. */ object ThrownException { - def unapply(ann: AnnotationInfo): Option[Symbol] = { + def unapply(ann: AnnotationInfo): Option[Type] = { ann match { case AnnotationInfo(tpe, _, _) if tpe.typeSymbol != ThrowsClass => None // old-style: @throws(classOf[Exception]) (which is throws[T](classOf[Exception])) case AnnotationInfo(_, List(Literal(Constant(tpe: Type))), _) => - Some(tpe.typeSymbol) + Some(tpe) // new-style: @throws[Exception], @throws[Exception]("cause") case AnnotationInfo(TypeRef(_, _, arg :: _), _, _) => - Some(arg.typeSymbol) + Some(arg) case AnnotationInfo(TypeRef(_, _, Nil), _, _) => - Some(ThrowableClass) + Some(ThrowableTpe) } } } diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index c3b2a8da08..ce93841567 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -2964,7 +2964,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => loop(info) } - override def exceptions = annotations flatMap ThrownException.unapply + override def exceptions = for (ThrownException(tp) <- annotations) yield tp.typeSymbol } implicit val MethodSymbolTag = ClassTag[MethodSymbol](classOf[MethodSymbol]) |