Skip to content

Commit 7efb315

Browse files
oderskytgodzik
authored andcommitted
Better error message: reassignment to val
[Cherry-picked 09086bf]
1 parent 913408e commit 7efb315

File tree

5 files changed

+83
-12
lines changed

5 files changed

+83
-12
lines changed

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,17 +1532,25 @@ class AmbiguousExtensionMethod(tree: untpd.Tree, expansion1: tpd.Tree, expansion
15321532
|are possible expansions of $tree"""
15331533
def explain(using Context) = ""
15341534

1535-
class ReassignmentToVal(name: Name)(using Context)
1535+
class ReassignmentToVal(name: Name, pt: Type)(using Context)
15361536
extends TypeMsg(ReassignmentToValID) {
1537-
def msg(using Context) = i"""Reassignment to val $name"""
1538-
def explain(using Context) =
1539-
i"""|You can not assign a new value to $name as values can't be changed.
1540-
|Keep in mind that every statement has a value, so you may e.g. use
1541-
| ${hl("val")} $name ${hl("= if (condition) 2 else 5")}
1542-
|In case you need a reassignable name, you can declare it as
1543-
|variable
1544-
| ${hl("var")} $name ${hl("=")} ...
1545-
|"""
1537+
1538+
def booleanExpected = pt.isRef(defn.BooleanClass)
1539+
def booleanNote =
1540+
if booleanExpected then
1541+
". Maybe you meant to write an equality test using `==`?"
1542+
else ""
1543+
def msg(using Context)
1544+
= i"""Reassignment to val $name$booleanNote"""
1545+
1546+
def explain(using Context) =
1547+
if booleanExpected then
1548+
i"""An equality test is written "x == y" using `==`. A single `=` stands
1549+
|for assigment, where a variable on the left gets a new value on the right.
1550+
|This is only permitted if the variable is declared with `var`."""
1551+
else
1552+
i"""You can not assign a new value to $name as values can't be changed.
1553+
|Reassigment is only permitted if the variable is declared with `var`."""
15461554
}
15471555

15481556
class TypeDoesNotTakeParameters(tpe: Type, params: List[untpd.Tree])(using Context)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ trait Dynamic {
137137
case TypeApply(sel @ Select(qual, name), targs) if !isDynamicMethod(name) =>
138138
typedDynamicAssign(qual, name, sel.span, targs)
139139
case _ =>
140-
errorTree(tree, ReassignmentToVal(tree.lhs.symbol.name))
140+
errorTree(tree, ReassignmentToVal(tree.lhs.symbol.name, pt))
141141
}
142142
}
143143

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1157,7 +1157,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
11571157
def lhs1 = adapt(lhsCore, AssignProto, locked)
11581158

11591159
def reassignmentToVal =
1160-
report.error(ReassignmentToVal(lhsCore.symbol.name), tree.srcPos)
1160+
report.error(ReassignmentToVal(lhsCore.symbol.name, pt), tree.srcPos)
11611161
cpy.Assign(tree)(lhsCore, typed(tree.rhs, lhs1.tpe.widen)).withType(defn.UnitType)
11621162

11631163
def canAssign(sym: Symbol) =

tests/neg/reassignment.check

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
-- [E052] Type Error: tests/neg/reassignment.scala:4:10 ----------------------------------------------------------------
2+
4 |val y = x = 0 // error
3+
| ^^^^^
4+
| Reassignment to val x
5+
|---------------------------------------------------------------------------------------------------------------------
6+
| Explanation (enabled by `-explain`)
7+
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
8+
| You can not assign a new value to x as values can't be changed.
9+
| Reassigment is only permitted if the variable is declared with `var`.
10+
---------------------------------------------------------------------------------------------------------------------
11+
-- [E052] Type Error: tests/neg/reassignment.scala:5:19 ----------------------------------------------------------------
12+
5 |val z: Boolean = x = 0 // error
13+
| ^^^^^
14+
| Reassignment to val x. Maybe you meant to write an equality test using `==`?
15+
|---------------------------------------------------------------------------------------------------------------------
16+
| Explanation (enabled by `-explain`)
17+
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
18+
| An equality test is written "x == y" using `==`. A single `=` stands
19+
| for assigment, where a variable on the left gets a new value on the right.
20+
| This is only permitted if the variable is declared with `var`.
21+
---------------------------------------------------------------------------------------------------------------------
22+
-- [E052] Type Error: tests/neg/reassignment.scala:6:13 ----------------------------------------------------------------
23+
6 |def f = if x = 0 then 1 else 2 // error
24+
| ^^^^^
25+
| Reassignment to val x. Maybe you meant to write an equality test using `==`?
26+
|---------------------------------------------------------------------------------------------------------------------
27+
| Explanation (enabled by `-explain`)
28+
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
29+
| An equality test is written "x == y" using `==`. A single `=` stands
30+
| for assigment, where a variable on the left gets a new value on the right.
31+
| This is only permitted if the variable is declared with `var`.
32+
---------------------------------------------------------------------------------------------------------------------
33+
-- [E052] Type Error: tests/neg/reassignment.scala:8:4 -----------------------------------------------------------------
34+
8 | x = 0 // error
35+
| ^^^^^
36+
| Reassignment to val x
37+
|---------------------------------------------------------------------------------------------------------------------
38+
| Explanation (enabled by `-explain`)
39+
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
40+
| You can not assign a new value to x as values can't be changed.
41+
| Reassigment is only permitted if the variable is declared with `var`.
42+
---------------------------------------------------------------------------------------------------------------------
43+
-- [E052] Type Error: tests/neg/reassignment.scala:9:4 -----------------------------------------------------------------
44+
9 | x = 2 // error
45+
| ^^^^^
46+
| Reassignment to val x. Maybe you meant to write an equality test using `==`?
47+
|---------------------------------------------------------------------------------------------------------------------
48+
| Explanation (enabled by `-explain`)
49+
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
50+
| An equality test is written "x == y" using `==`. A single `=` stands
51+
| for assigment, where a variable on the left gets a new value on the right.
52+
| This is only permitted if the variable is declared with `var`.
53+
---------------------------------------------------------------------------------------------------------------------

tests/neg/reassignment.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//> using options -explain
2+
3+
val x = 1
4+
val y = x = 0 // error
5+
val z: Boolean = x = 0 // error
6+
def f = if x = 0 then 1 else 2 // error
7+
def g: Boolean =
8+
x = 0 // error
9+
x = 2 // error
10+

0 commit comments

Comments
 (0)