diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreeInfo.scala | 31 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 48 | ||||
-rw-r--r-- | test/files/pos/bug3278.scala | 15 |
3 files changed, 61 insertions, 33 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala index 0f31a3a9f2..430967298c 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala @@ -102,17 +102,20 @@ abstract class TreeInfo { case _ => false } - def isVariableOrGetter(tree: Tree) = tree match { - case Ident(_) => - tree.symbol.isVariable - case Select(qual, _) => - tree.symbol.isVariable || - (mayBeVarGetter(tree.symbol) && - tree.symbol.owner.info.member(nme.getterToSetter(tree.symbol.name)) != NoSymbol) - case Apply(Select(qual, nme.apply), _) => - qual.tpe.member(nme.update) != NoSymbol - case _ => - false + def isVariableOrGetter(tree: Tree) = { + def sym = tree.symbol + def isVar = sym.isVariable + def isGetter = mayBeVarGetter(sym) && sym.owner.info.member(nme.getterToSetter(sym.name)) != NoSymbol + + tree match { + case Ident(_) => isVar + case Select(_, _) => isVar || isGetter + case _ => + methPart(tree) match { + case Select(qual, nme.apply) => qual.tpe.member(nme.update) != NoSymbol + case _ => false + } + } } /** Is tree a self constructor call? @@ -295,10 +298,10 @@ abstract class TreeInfo { /** The method part of an application node */ def methPart(tree: Tree): Tree = tree match { - case Apply(fn, _) => methPart(fn) - case TypeApply(fn, _) => methPart(fn) + case Apply(fn, _) => methPart(fn) + case TypeApply(fn, _) => methPart(fn) case AppliedTypeTree(fn, _) => methPart(fn) - case _ => tree + case _ => tree } def firstArgument(tree: Tree): Tree = tree match { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 0274dc8871..0311d3e53c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3334,31 +3334,41 @@ trait Typers { self: Analyzer => Apply( Select(vble.duplicate, prefix) setPos fun.pos.focus, args) setPos tree.pos.makeTransparent ) setPos tree.pos + + def mkUpdate(table: Tree, indices: List[Tree]) = { + gen.evalOnceAll(table :: indices, context.owner, context.unit) { ts => + val tab = ts.head + val is = ts.tail + Apply( + Select(tab(), nme.update) setPos table.pos, + ((is map (i => i())) ::: List( + Apply( + Select( + Apply( + Select(tab(), nme.apply) setPos table.pos, + is map (i => i())) setPos qual.pos, + prefix) setPos fun.pos, + args) setPos tree.pos) + ) + ) setPos tree.pos + } + } + val tree1 = qual match { + case Ident(_) => + mkAssign(qual) + case Select(qualqual, vname) => gen.evalOnce(qualqual, context.owner, context.unit) { qq => val qq1 = qq() mkAssign(Select(qq1, vname) setPos qual.pos) } - case Apply(Select(table, nme.apply), indices) => - gen.evalOnceAll(table :: indices, context.owner, context.unit) { ts => - val tab = ts.head - val is = ts.tail - Apply( - Select(tab(), nme.update) setPos table.pos, - ((is map (i => i())) ::: List( - Apply( - Select( - Apply( - Select(tab(), nme.apply) setPos table.pos, - is map (i => i())) setPos qual.pos, - prefix) setPos fun.pos, - args) setPos tree.pos) - ) - ) setPos tree.pos - } - case Ident(_) => - mkAssign(qual) + + case Apply(fn, indices) => + treeInfo.methPart(fn) match { + case Select(table, nme.apply) => mkUpdate(table, indices) + case _ => errorTree(qual, "Unexpected tree during assignment conversion.") + } } typed1(tree1, mode, pt) /* diff --git a/test/files/pos/bug3278.scala b/test/files/pos/bug3278.scala new file mode 100644 index 0000000000..788ec75d26 --- /dev/null +++ b/test/files/pos/bug3278.scala @@ -0,0 +1,15 @@ +class Foo +class Test { + def update[B](x : B, b : Int) {} + def apply[B](x : B) = 1 +} + +object Test { + def main(a : Array[String]) { + val a = new Test + val f = new Foo + a(f) = 1 //works + a(f) = a(f) + 1 //works + a(f) += 1 //error: reassignment to val + } +}
\ No newline at end of file |