From 7a007dcd3845fa11458b7f0b71b776770622eaab Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 2 May 2017 14:41:44 +0200 Subject: [PATCH 1/2] Fix #2345: Handle case of overloaded local vars in assignment Clean up logic of typedAssign, so that it now correctly handles the case of an overloaded left-hand-side consisting of a provate[this] var and one or more methods. --- .../src/dotty/tools/dotc/typer/Typer.scala | 57 ++++++++++--------- tests/pos/i2345.scala | 6 ++ 2 files changed, 37 insertions(+), 26 deletions(-) create mode 100644 tests/pos/i2345.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index f84263a98760..b859d536dce4 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -567,37 +567,42 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case lhs => val lhsCore = typedUnadapted(lhs, AssignProto) def lhs1 = typed(untpd.TypedSplice(lhsCore)) - def canAssign(sym: Symbol) = // allow assignments from the primary constructor to class fields + lazy val lhsVal = lhsCore.asInstanceOf[TermRef].denot.suchThat(!_.is(Method)) + + def reassignmentToVal = + errorTree(cpy.Assign(tree)(lhsCore, typed(tree.rhs, lhs1.tpe.widen)), + "reassignment to val") + + def canAssign(sym: Symbol) = sym.is(Mutable, butNot = Accessor) || ctx.owner.isPrimaryConstructor && !sym.is(Method) && sym.owner == ctx.owner.owner || + // allow assignments from the primary constructor to class fields ctx.owner.name.is(TraitSetterName) || ctx.owner.isStaticConstructor + lhsCore.tpe match { - case ref: TermRef if canAssign(ref.symbol) => - assignType(cpy.Assign(tree)(lhs1, typed(tree.rhs, ref.info))) - case _ => - def reassignmentToVal = - errorTree(cpy.Assign(tree)(lhsCore, typed(tree.rhs, lhs1.tpe.widen)), - "reassignment to val") - lhsCore.tpe match { - case ref: TermRef => // todo: further conditions to impose on getter? - val pre = ref.prefix - val setterName = ref.name.setterName - val setter = pre.member(setterName) - lhsCore match { - case lhsCore: RefTree if setter.exists => - val setterTypeRaw = pre.select(setterName, setter) - val setterType = ensureAccessible(setterTypeRaw, isSuperSelection(lhsCore), tree.pos) - val lhs2 = healNonvariant( - untpd.rename(lhsCore, setterName).withType(setterType), WildcardType) - typedUnadapted(cpy.Apply(tree)(untpd.TypedSplice(lhs2), tree.rhs :: Nil)) - case _ => - reassignmentToVal - } - case TryDynamicCallType => - typedDynamicAssign(tree, pt) - case tpe => - reassignmentToVal + case ref: TermRef => + val lhsVal = lhsCore.denot.suchThat(!_.is(Method)) + if (canAssign(lhsVal.symbol)) + assignType(cpy.Assign(tree)(lhs1, typed(tree.rhs, lhsVal.info))) + else { + val pre = ref.prefix + val setterName = ref.name.setterName + val setter = pre.member(setterName) + lhsCore match { + case lhsCore: RefTree if setter.exists => + val setterTypeRaw = pre.select(setterName, setter) + val setterType = ensureAccessible(setterTypeRaw, isSuperSelection(lhsCore), tree.pos) + val lhs2 = healNonvariant( + untpd.rename(lhsCore, setterName).withType(setterType), WildcardType) + typedUnadapted(cpy.Apply(tree)(untpd.TypedSplice(lhs2), tree.rhs :: Nil)) + case _ => + reassignmentToVal + } } + case TryDynamicCallType => + typedDynamicAssign(tree, pt) + case tpe => + reassignmentToVal } } } diff --git a/tests/pos/i2345.scala b/tests/pos/i2345.scala new file mode 100644 index 000000000000..4cca209835df --- /dev/null +++ b/tests/pos/i2345.scala @@ -0,0 +1,6 @@ +import scala.collection.mutable + +abstract class Whatever[A] extends mutable.Set[A] { + private[this] var count = 0 + count = 0 +} From 64cdb433c31a45465ebd17f6f7d83a24ca276041 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 2 May 2017 14:56:17 +0200 Subject: [PATCH 2/2] Eliminate unused definition --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index b859d536dce4..0b0ef92f06cc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -567,7 +567,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case lhs => val lhsCore = typedUnadapted(lhs, AssignProto) def lhs1 = typed(untpd.TypedSplice(lhsCore)) - lazy val lhsVal = lhsCore.asInstanceOf[TermRef].denot.suchThat(!_.is(Method)) def reassignmentToVal = errorTree(cpy.Assign(tree)(lhsCore, typed(tree.rhs, lhs1.tpe.widen)),