diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/icode/ICodes.scala | 19 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala | 7 | ||||
-rw-r--r-- | test/files/pos/bug4840.flags | 1 | ||||
-rw-r--r-- | test/files/pos/bug4840.scala | 13 | ||||
-rw-r--r-- | test/files/run/run-bug4840.check | 2 | ||||
-rw-r--r-- | test/files/run/run-bug4840.flags | 1 | ||||
-rw-r--r-- | test/files/run/run-bug4840.scala | 30 |
7 files changed, 68 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala index 9553d5cf9b..06c3ee2a9e 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala @@ -35,7 +35,7 @@ abstract class ICodes extends AnyRef with Repository { val global: Global - import global.{ definitions, settings, perRunCaches } + import global.{ log, definitions, settings, perRunCaches } /** The ICode representation of classes */ val classes = perRunCaches.newMap[global.Symbol, IClass]() @@ -72,11 +72,22 @@ abstract class ICodes extends AnyRef } def checkValid(m: IMethod) { - for (b <- m.code.blocks) - if (!b.closed) { + // always dicey to iterate over mutable structures + val bs = m.code.blocks.toList + + for (b <- bs ; if !b.closed) { + // Something is leaving open/empty blocks around (see SI-4840) so + // let's not kill the deal unless it's nonempty. + if (b.isEmpty) { + log("!!! Found open but empty block while inlining " + m + ": removing from block list.") + m.code removeBlock b + } + else { + Console.println("Fatal bug in inliner: found open block when inlining " + m) m.dump - global.abort("Open block: " + b + " " + b.flagsString) + global.abort("Open block was: " + b + " " + b.flagsString) } + } } object liveness extends Liveness { diff --git a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala index 9f22a6de90..8130c99978 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala @@ -14,6 +14,8 @@ import mutable.ListBuffer trait Linearizers { self: ICodes => + + import global.debuglog import opcodes._ abstract class Linearizer { @@ -178,11 +180,14 @@ trait Linearizers { * Prepend b to the list, if not already scheduled. * @return Returns true if the block was added. */ - def add(b: BasicBlock) = + def add(b: BasicBlock) = { + debuglog("Linearizer adding block " + b.label) + if (!added(b.label)) { added += b.label blocks = b :: blocks; } + } } /** A 'dump' of the blocks in this method, which does not diff --git a/test/files/pos/bug4840.flags b/test/files/pos/bug4840.flags new file mode 100644 index 0000000000..eb4d19bcb9 --- /dev/null +++ b/test/files/pos/bug4840.flags @@ -0,0 +1 @@ +-optimise
\ No newline at end of file diff --git a/test/files/pos/bug4840.scala b/test/files/pos/bug4840.scala new file mode 100644 index 0000000000..bf44f71d7a --- /dev/null +++ b/test/files/pos/bug4840.scala @@ -0,0 +1,13 @@ +class Crashy { + def g(): Option[Any] = None + + def crashy() = { + for (_ <- g()) { + (null: Any) match { + case Some(_) => 5 + case None => sys.error("") + } + } + } +} + diff --git a/test/files/run/run-bug4840.check b/test/files/run/run-bug4840.check new file mode 100644 index 0000000000..cdfc1f911f --- /dev/null +++ b/test/files/run/run-bug4840.check @@ -0,0 +1,2 @@ +Some(5) +Some(Some(Some(5))) diff --git a/test/files/run/run-bug4840.flags b/test/files/run/run-bug4840.flags new file mode 100644 index 0000000000..eb4d19bcb9 --- /dev/null +++ b/test/files/run/run-bug4840.flags @@ -0,0 +1 @@ +-optimise
\ No newline at end of file diff --git a/test/files/run/run-bug4840.scala b/test/files/run/run-bug4840.scala new file mode 100644 index 0000000000..dda280fd17 --- /dev/null +++ b/test/files/run/run-bug4840.scala @@ -0,0 +1,30 @@ +object Test { + def g(x: Boolean): Option[String] = if (x) Some("booya") else None + + def f1() = { + for (x <- g(true)) yield { + g(false) match { + case Some(_) => sys.error("") + case None => 5 + } + } + } + + def f2() = { + for (x <- g(true) ; y <- g(true) ; z <- g(true)) yield { + for (x <- g(true) ; y <- g(true) ; z <- g(true)) yield { + g(true) map { _ => + (null: Any) match { + case Some(x: Int) => x + case _ => 5 + } + } + } + } + } + + def main(args: Array[String]): Unit = { + println(f1()) + println(f2()) + } +} |