diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2012-07-04 07:28:42 -0700 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2012-07-04 07:28:42 -0700 |
commit | cb066cc6af2e836d66593d2fec56bc2c6a786d1a (patch) | |
tree | 79e33807d1192c50835a98c3987df45225c28481 | |
parent | d033ced739068c3c40dc23d055dea1a0005fa39e (diff) | |
parent | 59300ee6e3fc2c34482c7fb10ee4f7b298a6fbce (diff) | |
download | scala-cb066cc6af2e836d66593d2fec56bc2c6a786d1a.tar.gz scala-cb066cc6af2e836d66593d2fec56bc2c6a786d1a.tar.bz2 scala-cb066cc6af2e836d66593d2fec56bc2c6a786d1a.zip |
Merge pull request #809 from dragos/issue/fix-5929
Fix SI-5929 - Verify error with finally and pattern match
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/icode/GenICode.scala | 18 | ||||
-rw-r--r-- | test/files/run/patmat-finally.scala | 25 |
2 files changed, 32 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index f7541a4739..b638745327 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -860,7 +860,7 @@ abstract class GenICode extends SubComponent { if (sym.isLabel) { // jump to a label val label = ctx.labels.getOrElse(sym, { // it is a forward jump, scan for labels - scanForLabels(ctx.defdef, ctx) + resolveForwardLabel(ctx.defdef, ctx, sym) ctx.labels.get(sym) match { case Some(l) => log("Forward jump for " + sym.fullLocationString + ": scan found label " + l) @@ -1406,21 +1406,17 @@ abstract class GenICode extends SubComponent { def ifOneIsNull(l: Tree, r: Tree) = if (isNull(l)) r else if (isNull(r)) l else null /** - * Traverse the tree and store label stubs in the context. This is - * necessary to handle forward jumps, because at a label application - * with arguments, the symbols of the corresponding LabelDef parameters - * are not yet known. + * Find the label denoted by `lsym` and enter it in context `ctx`. * - * Since it is expensive to traverse each method twice, this method is called - * only when forward jumps really happen, and then it re-traverses the whole - * method, scanning for LabelDefs. + * We only enter one symbol at a time, even though we might traverse the same + * tree more than once per method. That's because we cannot enter labels that + * might be duplicated (for instance, inside finally blocks). * * TODO: restrict the scanning to smaller subtrees than the whole method. * It is sufficient to scan the trees of the innermost enclosing block. */ - // - private def scanForLabels(tree: Tree, ctx: Context): Unit = tree foreachPartial { - case t @ LabelDef(_, params, rhs) => + private def resolveForwardLabel(tree: Tree, ctx: Context, lsym: Symbol): Unit = tree foreachPartial { + case t @ LabelDef(_, params, rhs) if t.symbol == lsym => ctx.labels.getOrElseUpdate(t.symbol, { val locals = params map (p => new Local(p.symbol, toTypeKind(p.symbol.info), false)) ctx.method addLocals locals diff --git a/test/files/run/patmat-finally.scala b/test/files/run/patmat-finally.scala new file mode 100644 index 0000000000..6f769b30a0 --- /dev/null +++ b/test/files/run/patmat-finally.scala @@ -0,0 +1,25 @@ +/** Test pattern matching and finally, see SI-5929. */ +object Test extends App { + def bar(s1: Object, s2: Object) { + s1 match { + case _ => + } + + try { + () + } finally { + s2 match { + case _ => + } + } + } + + def x = { + null match { case _ => } + + try { 1 } finally { while(false) { } } + } + + bar(null, null) + x +} |