Skip to content

Commit 7a007dc

Browse files
committed
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.
1 parent de53e52 commit 7a007dc

File tree

2 files changed

+37
-26
lines changed

2 files changed

+37
-26
lines changed

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -567,37 +567,42 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
567567
case lhs =>
568568
val lhsCore = typedUnadapted(lhs, AssignProto)
569569
def lhs1 = typed(untpd.TypedSplice(lhsCore))
570-
def canAssign(sym: Symbol) = // allow assignments from the primary constructor to class fields
570+
lazy val lhsVal = lhsCore.asInstanceOf[TermRef].denot.suchThat(!_.is(Method))
571+
572+
def reassignmentToVal =
573+
errorTree(cpy.Assign(tree)(lhsCore, typed(tree.rhs, lhs1.tpe.widen)),
574+
"reassignment to val")
575+
576+
def canAssign(sym: Symbol) =
571577
sym.is(Mutable, butNot = Accessor) ||
572578
ctx.owner.isPrimaryConstructor && !sym.is(Method) && sym.owner == ctx.owner.owner ||
579+
// allow assignments from the primary constructor to class fields
573580
ctx.owner.name.is(TraitSetterName) || ctx.owner.isStaticConstructor
581+
574582
lhsCore.tpe match {
575-
case ref: TermRef if canAssign(ref.symbol) =>
576-
assignType(cpy.Assign(tree)(lhs1, typed(tree.rhs, ref.info)))
577-
case _ =>
578-
def reassignmentToVal =
579-
errorTree(cpy.Assign(tree)(lhsCore, typed(tree.rhs, lhs1.tpe.widen)),
580-
"reassignment to val")
581-
lhsCore.tpe match {
582-
case ref: TermRef => // todo: further conditions to impose on getter?
583-
val pre = ref.prefix
584-
val setterName = ref.name.setterName
585-
val setter = pre.member(setterName)
586-
lhsCore match {
587-
case lhsCore: RefTree if setter.exists =>
588-
val setterTypeRaw = pre.select(setterName, setter)
589-
val setterType = ensureAccessible(setterTypeRaw, isSuperSelection(lhsCore), tree.pos)
590-
val lhs2 = healNonvariant(
591-
untpd.rename(lhsCore, setterName).withType(setterType), WildcardType)
592-
typedUnadapted(cpy.Apply(tree)(untpd.TypedSplice(lhs2), tree.rhs :: Nil))
593-
case _ =>
594-
reassignmentToVal
595-
}
596-
case TryDynamicCallType =>
597-
typedDynamicAssign(tree, pt)
598-
case tpe =>
599-
reassignmentToVal
583+
case ref: TermRef =>
584+
val lhsVal = lhsCore.denot.suchThat(!_.is(Method))
585+
if (canAssign(lhsVal.symbol))
586+
assignType(cpy.Assign(tree)(lhs1, typed(tree.rhs, lhsVal.info)))
587+
else {
588+
val pre = ref.prefix
589+
val setterName = ref.name.setterName
590+
val setter = pre.member(setterName)
591+
lhsCore match {
592+
case lhsCore: RefTree if setter.exists =>
593+
val setterTypeRaw = pre.select(setterName, setter)
594+
val setterType = ensureAccessible(setterTypeRaw, isSuperSelection(lhsCore), tree.pos)
595+
val lhs2 = healNonvariant(
596+
untpd.rename(lhsCore, setterName).withType(setterType), WildcardType)
597+
typedUnadapted(cpy.Apply(tree)(untpd.TypedSplice(lhs2), tree.rhs :: Nil))
598+
case _ =>
599+
reassignmentToVal
600+
}
600601
}
602+
case TryDynamicCallType =>
603+
typedDynamicAssign(tree, pt)
604+
case tpe =>
605+
reassignmentToVal
601606
}
602607
}
603608
}

tests/pos/i2345.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import scala.collection.mutable
2+
3+
abstract class Whatever[A] extends mutable.Set[A] {
4+
private[this] var count = 0
5+
count = 0
6+
}

0 commit comments

Comments
 (0)