summaryrefslogtreecommitdiff
path: root/src/compiler/scala
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2015-03-11 11:34:08 -0700
committerLukas Rytz <lukas.rytz@gmail.com>2015-03-11 12:53:36 -0700
commit027e97981d9b6a3783e9ab247cc898017b3de821 (patch)
tree209a0d646f54c14b119924ba55773c382f50a701 /src/compiler/scala
parent4e982451decdc3821febfe975e1b8e406a3741e8 (diff)
downloadscala-027e97981d9b6a3783e9ab247cc898017b3de821.tar.gz
scala-027e97981d9b6a3783e9ab247cc898017b3de821.tar.bz2
scala-027e97981d9b6a3783e9ab247cc898017b3de821.zip
Workaround for SI-9111
The inliner forces some method symbols to complete that would not be completed otherwise. This triggers SI-9111, in which the completer of a valid Java method definition reports an error in mixed compilation. The workaround disables error reporting while completing lazy method and class symbols in the backend.
Diffstat (limited to 'src/compiler/scala')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala69
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/OptimizerReporting.scala1
3 files changed, 60 insertions, 16 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
index e617c86b23..81d8adb7de 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
@@ -12,7 +12,7 @@ import asm.Opcodes
import scala.tools.asm.tree.{InnerClassNode, ClassNode}
import scala.tools.nsc.backend.jvm.BTypes.{MethodInlineInfo, InlineInfo}
import scala.tools.nsc.backend.jvm.opt.{CallGraph, ByteCodeRepository, Inliner}
-import OptimizerReporting._
+import opt.OptimizerReporting._
import scala.collection.convert.decorateAsScala._
/**
@@ -736,8 +736,10 @@ abstract class BTypes {
/**
* A ClassBType represents a class or interface type. The necessary information to build a
* ClassBType is extracted from compiler symbols and types, see BTypesFromSymbols.
+ *
+ * Currently non-final due to SI-9111
*/
- final case class ClassBType(internalName: InternalName) extends RefBType {
+ /*final*/ case class ClassBType(internalName: InternalName) extends RefBType {
/**
* Write-once variable allows initializing a cyclic graph of infos. This is required for
* nested classes. Example: for the definition `class A { class B }` we have
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
index d94bd77851..9fdb92b47c 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
@@ -146,14 +146,49 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
else {
val internalName = classSym.javaBinaryName.toString
classBTypeFromInternalName.getOrElse(internalName, {
- // The new ClassBType is added to the map in its constructor, before we set its info. This
- // allows initializing cyclic dependencies, see the comment on variable ClassBType._info.
- setClassInfo(classSym, ClassBType(internalName))
+ if (completeSilentlyAndCheckErroneous(classSym)) {
+ new ErroneousClassBType(internalName)
+ } else {
+ // The new ClassBType is added to the map in its constructor, before we set its info. This
+ // allows initializing cyclic dependencies, see the comment on variable ClassBType._info.
+ setClassInfo(classSym, ClassBType(internalName))
+ }
})
}
}
/**
+ * Part of the workaround for SI-9111. Makes sure that the compiler only fails if the ClassInfo
+ * of the symbol that could not be completed is actually required.
+ */
+ private class ErroneousClassBType(internalName: InternalName) extends ClassBType(internalName) {
+ def msg = s"The class info for $internalName could not be completed due to SI-9111."
+ override def info: ClassInfo = opt.OptimizerReporting.assertionError(msg)
+ override def info_=(i: ClassInfo): Unit = opt.OptimizerReporting.assertionError(msg)
+ }
+
+ /**
+ * This is a hack to work around SI-9111. The completer of `methodSym` may report type errors. We
+ * cannot change the typer context of the completer at this point and make it silent: the context
+ * captured when creating the completer in the namer. However, we can temporarily replace
+ * global.reporter (it's a var) to store errors.
+ */
+ def completeSilentlyAndCheckErroneous(sym: Symbol): Boolean = {
+ if (sym.rawInfo.isComplete) false
+ else {
+ val originalReporter = global.reporter
+ val storeReporter = new reporters.StoreReporter()
+ try {
+ global.reporter = storeReporter
+ sym.info
+ } finally {
+ global.reporter = originalReporter
+ }
+ storeReporter.infos.exists(_.severity == storeReporter.ERROR)
+ }
+ }
+
+ /**
* Builds a [[MethodBType]] for a method symbol.
*/
final def methodBTypeFromSymbol(methodSymbol: Symbol): MethodBType = {
@@ -428,18 +463,24 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
else {
// Primitve methods cannot be inlined, so there's no point in building an InlineInfo. Also, some
// primitive methods (e.g., `isInstanceOf`) have non-erased types, which confuses [[typeToBType]].
- classSym.info.decls.iterator.filter(m => m.isMethod && !scalaPrimitives.isPrimitive(m)).map({
+ classSym.info.decls.iterator.filter(m => m.isMethod && !scalaPrimitives.isPrimitive(m)).flatMap({
case methodSym =>
- val methodBType = methodBTypeFromSymbol(methodSym)
- val name = methodSym.javaSimpleName.toString // same as in genDefDef
- val signature = name + methodBType.descriptor
- val info = MethodInlineInfo(
- effectivelyFinal = methodSym.isEffectivelyFinalOrNotOverridden,
- traitMethodWithStaticImplementation = false, // temporary, fixed in future commit
- annotatedInline = methodSym.hasAnnotation(ScalaInlineClass),
- annotatedNoInline = methodSym.hasAnnotation(ScalaNoInlineClass)
- )
- (signature, info)
+ if (completeSilentlyAndCheckErroneous(methodSym)) {
+ // Happens due to SI-9111. Just don't provide any InlineInfo for that method, we don't
+ // need fail the compiler.
+ None
+ } else {
+ val methodBType = methodBTypeFromSymbol(methodSym)
+ val name = methodSym.javaSimpleName.toString // same as in genDefDef
+ val signature = name + methodBType.descriptor
+ val info = MethodInlineInfo(
+ effectivelyFinal = methodSym.isEffectivelyFinalOrNotOverridden,
+ traitMethodWithStaticImplementation = false, // temporary, fixed in future commit
+ annotatedInline = methodSym.hasAnnotation(ScalaInlineClass),
+ annotatedNoInline = methodSym.hasAnnotation(ScalaNoInlineClass)
+ )
+ Some((signature, info))
+ }
}).toMap
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/OptimizerReporting.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/OptimizerReporting.scala
index 53c00c7724..5b47bc88c2 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/OptimizerReporting.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/OptimizerReporting.scala
@@ -5,6 +5,7 @@
package scala.tools.nsc
package backend.jvm
+package opt
import scala.tools.asm
import asm.tree._