diff options
author | Paul Phillips <paulp@improving.org> | 2011-07-03 19:23:32 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-07-03 19:23:32 +0000 |
commit | 835be39b534accb0d341d0629662f5685ae2cfef (patch) | |
tree | 8887c364b1447e4017bbe4395d75de05003202aa | |
parent | 6d3159db055005719cbff30b48a7fbcd659b7240 (diff) | |
download | scala-835be39b534accb0d341d0629662f5685ae2cfef.tar.gz scala-835be39b534accb0d341d0629662f5685ae2cfef.tar.bz2 scala-835be39b534accb0d341d0629662f5685ae2cfef.zip |
evalOnce needs to pack the type before using it...
evalOnce needs to pack the type before using it on new valdefs to avoid
existential mismatches. Closes #3960, review by moors.
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreeGen.scala | 35 | ||||
-rw-r--r-- | test/files/pos/bug3960.flags | 1 | ||||
-rw-r--r-- | test/files/pos/bug3960.scala | 7 |
3 files changed, 33 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index ad9961fc49..d33ca3a6bc 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -174,18 +174,33 @@ abstract class TreeGen extends reflect.internal.TreeGen { case _ => EmptyTree } + /** Create a ValDef initialized to the given expression, setting the + * symbol to its packed type, and an function for creating Idents + * which refer to it. + */ + private def mkPackedValDef(expr: Tree, owner: Symbol, name: Name): (ValDef, () => Ident) = { + val packedType = typer.packedType(expr, owner) + val sym = ( + owner.newValue(expr.pos.makeTransparent, name) + setFlag SYNTHETIC + setInfo packedType + ) + + (ValDef(sym, expr), () => Ident(sym) setPos sym.pos.focus setType expr.tpe) + } + /** Used in situations where you need to access value of an expression several times */ def evalOnce(expr: Tree, owner: Symbol, unit: CompilationUnit)(within: (() => Tree) => Tree): Tree = { var used = false if (treeInfo.isPureExpr(expr)) { within(() => if (used) expr.duplicate else { used = true; expr }) - } else { - val temp = owner.newValue(expr.pos.makeTransparent, unit.freshTermName("ev$")) - .setFlag(SYNTHETIC).setInfo(expr.tpe) - val containing = within(() => Ident(temp) setPos temp.pos.focus setType expr.tpe) + } + else { + val (valDef, identFn) = mkPackedValDef(expr, owner, unit.freshTermName("ev$")) + val containing = within(identFn) ensureNonOverlapping(containing, List(expr)) - Block(List(ValDef(temp, expr)), containing) setPos (containing.pos union expr.pos) + Block(List(valDef), containing) setPos (containing.pos union expr.pos) } } @@ -200,11 +215,11 @@ abstract class TreeGen extends reflect.internal.TreeGen { val idx = i () => if (used(idx)) expr.duplicate else { used(idx) = true; expr } } - } else { - val temp = owner.newValue(expr.pos.makeTransparent, unit.freshTermName("ev$")) - .setFlag(SYNTHETIC).setInfo(expr.tpe) - vdefs += ValDef(temp, expr) - exprs1 += (() => Ident(temp) setPos temp.pos.focus setType expr.tpe) + } + else { + val (valDef, identFn) = mkPackedValDef(expr, owner, unit.freshTermName("ev$")) + vdefs += valDef + exprs1 += identFn } i += 1 } diff --git a/test/files/pos/bug3960.flags b/test/files/pos/bug3960.flags new file mode 100644 index 0000000000..4449dbbdf3 --- /dev/null +++ b/test/files/pos/bug3960.flags @@ -0,0 +1 @@ +-Ycheck:typer
\ No newline at end of file diff --git a/test/files/pos/bug3960.scala b/test/files/pos/bug3960.scala new file mode 100644 index 0000000000..5c658e9fbc --- /dev/null +++ b/test/files/pos/bug3960.scala @@ -0,0 +1,7 @@ +class A { + class C[x] + val cs = new scala.collection.mutable.HashMap[C[_], Int] + def c: C[_] = sys.error("") + val eval: C[_] = c + cs(c) += 1 +} |