From 14b1dd5b4235e08b1fa42fde43ca209f8b1bf8b0 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 21 Mar 2022 09:56:05 +0100 Subject: [PATCH 1/2] Extend "cannot override mutable variable" restriction to deferred variables. Extend "cannot override mutable variable" restriction also to deferred variables. This aligns the behavior with Scala 2. Fixes #14722 --- compiler/src/dotty/tools/dotc/typer/RefChecks.scala | 6 +++++- tests/neg/i14722.scala | 9 +++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i14722.scala diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 8d96d256a881..627451b0c852 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -474,7 +474,11 @@ object RefChecks { overrideError("needs `override` modifier") else if (other.is(AbsOverride) && other.isIncompleteIn(clazz) && !member.is(AbsOverride)) overrideError("needs `abstract override` modifiers") - else if member.is(Override) && other.is(Accessor, butNot = Deferred) && other.accessedFieldOrGetter.is(Mutable, butNot = Lazy) then + else if member.is(Override) + && (other.is(Mutable) + || other.is(Accessor, butNot = Deferred) + && other.accessedFieldOrGetter.is(Mutable, butNot = Lazy)) + then overrideError("cannot override a mutable variable") else if (member.isAnyOverride && !(member.owner.thisType.baseClasses exists (_ isSubClass other.owner)) && diff --git a/tests/neg/i14722.scala b/tests/neg/i14722.scala new file mode 100644 index 000000000000..b6e26341a487 --- /dev/null +++ b/tests/neg/i14722.scala @@ -0,0 +1,9 @@ +abstract class HasId(var id: String) + +case class Entity(override val id: String) extends HasId(id) // error + +object Test extends App { + val entity = Entity("0001") + entity.id = "0002" + println(entity.id) +} From 1a5b8589f27860ed7b490d91a71d6bc6909cbdff Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 21 Mar 2022 11:02:59 +0100 Subject: [PATCH 2/2] Simplify logic and reclassify test --- compiler/src/dotty/tools/dotc/typer/RefChecks.scala | 6 +----- tests/{pos => neg}/i13019.scala | 2 +- tests/neg/i14722.scala | 11 +++++++++++ 3 files changed, 13 insertions(+), 6 deletions(-) rename tests/{pos => neg}/i13019.scala (80%) diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 627451b0c852..4a0db540ca2d 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -474,11 +474,7 @@ object RefChecks { overrideError("needs `override` modifier") else if (other.is(AbsOverride) && other.isIncompleteIn(clazz) && !member.is(AbsOverride)) overrideError("needs `abstract override` modifiers") - else if member.is(Override) - && (other.is(Mutable) - || other.is(Accessor, butNot = Deferred) - && other.accessedFieldOrGetter.is(Mutable, butNot = Lazy)) - then + else if member.is(Override) && other.is(Mutable) then overrideError("cannot override a mutable variable") else if (member.isAnyOverride && !(member.owner.thisType.baseClasses exists (_ isSubClass other.owner)) && diff --git a/tests/pos/i13019.scala b/tests/neg/i13019.scala similarity index 80% rename from tests/pos/i13019.scala rename to tests/neg/i13019.scala index 491b6df03d0b..7f0958df083c 100644 --- a/tests/pos/i13019.scala +++ b/tests/neg/i13019.scala @@ -10,4 +10,4 @@ class Ok2C extends Ok2 { override var i: Int = 1 } // was: variable i of type Int cannot override a mutable variable trait NotOk {var i: Int} -class NotOkC extends NotOk { override var i: Int = 1 } +class NotOkC extends NotOk { override var i: Int = 1 } // error diff --git a/tests/neg/i14722.scala b/tests/neg/i14722.scala index b6e26341a487..c129eb42b53d 100644 --- a/tests/neg/i14722.scala +++ b/tests/neg/i14722.scala @@ -7,3 +7,14 @@ object Test extends App { entity.id = "0002" println(entity.id) } + +trait HasId2: + var id: String = "" + +case class Entity2(override val id: String) extends HasId2 // error + +trait HasId3: + def id: String + def id_=(x: String): Unit + +case class Entity3(override var id: String) extends HasId3 // ok