summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala31
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala48
-rw-r--r--test/files/pos/bug3278.scala15
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