Skip to content

Commit 80f67df

Browse files
authored
Merge pull request #15584 from dotty-staging/fix-init-error
Underline assignment correctly in error message
2 parents ae83f76 + 675fcb1 commit 80f67df

File tree

6 files changed

+49
-53
lines changed

6 files changed

+49
-53
lines changed

compiler/src/dotty/tools/dotc/transform/init/Semantic.scala

+25-11
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,17 @@ object Semantic:
5252
*
5353
*/
5454
sealed abstract class Value:
55-
def show: String = this.toString()
55+
def show(using Context): String = this match
56+
case ThisRef(klass) =>
57+
"ThisRef[" + klass.show + "]"
58+
case Warm(klass, outer, ctor, args) =>
59+
"Warm[" + klass.show + "] { outer = " + outer.show + ", args = " + args.map(_.show).mkString("(", ", ", ")") + " }"
60+
case Fun(expr, thisV, klass) =>
61+
"Fun { this = " + thisV.show + ", owner = " + klass.show + " }"
62+
case RefSet(values) =>
63+
values.map(_.show).mkString("Set { ", ", ", " }")
64+
case _ =>
65+
this.toString()
5666

5767
def isHot = this == Hot
5868
def isCold = this == Cold
@@ -792,8 +802,11 @@ object Semantic:
792802
else
793803
// no source code available
794804
promoteArgs()
795-
val error = CallUnknown(target, trace.toVector)
796-
reporter.report(error)
805+
// try promoting the receiver as last resort
806+
val hasErrors = Reporter.hasErrors { ref.promote("try promote value to hot") }
807+
if hasErrors then
808+
val error = CallUnknown(target, trace.toVector)
809+
reporter.report(error)
797810
Hot
798811
else
799812
// method call resolves to a field
@@ -1036,9 +1049,9 @@ object Semantic:
10361049
extension (value: Value)
10371050
/** Promotion of values to hot */
10381051
def promote(msg: String): Contextual[Unit] = log("promoting " + value + ", promoted = " + promoted, printer) {
1039-
if promoted.isCurrentObjectPromoted then Nil else
1052+
if !promoted.isCurrentObjectPromoted then
10401053

1041-
value.match
1054+
value match
10421055
case Hot =>
10431056

10441057
case Cold =>
@@ -1099,8 +1112,9 @@ object Semantic:
10991112
*/
11001113
def tryPromote(msg: String): Contextual[List[Error]] = log("promote " + warm.show + ", promoted = " + promoted, printer) {
11011114
val classRef = warm.klass.appliedRef
1102-
if classRef.memberClasses.nonEmpty || !warm.isFullyFilled then
1103-
return PromoteError(msg, trace.toVector) :: Nil
1115+
val hasInnerClass = classRef.memberClasses.filter(_.symbol.hasSource).nonEmpty
1116+
if hasInnerClass then
1117+
return PromoteError(msg + "Promotion cancelled as the value contains inner classes. ", trace.toVector) :: Nil
11041118

11051119
val errors = Reporter.stopEarly {
11061120
for klass <- warm.klass.baseClasses if klass.hasSource do
@@ -1352,13 +1366,13 @@ object Semantic:
13521366
case Select(qual, _) =>
13531367
eval(qual, thisV, klass)
13541368
val res = eval(rhs, thisV, klass)
1355-
extendTrace(rhs) {
1356-
res.ensureHot("The RHS of reassignment must be fully initialized.")
1369+
extendTrace(expr) {
1370+
res.ensureHot("The RHS of reassignment must be fully initialized. Found = " + res.show + ". ")
13571371
}
13581372
case id: Ident =>
13591373
val res = eval(rhs, thisV, klass)
1360-
extendTrace(rhs) {
1361-
res.ensureHot("The RHS of reassignment must be fully initialized.")
1374+
extendTrace(expr) {
1375+
res.ensureHot("The RHS of reassignment must be fully initialized. Found = " + res.show + ". ")
13621376
}
13631377

13641378
case closureDef(ddef) =>

tests/init/neg/apply2.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ object O:
33
println(n)
44

55
class B:
6-
val a = A(this) // error
6+
val a = A(this)
77

88
val b = new B
9-
val n = 10
9+
val n = 10 // error
1010
end O

tests/init/neg/inherit-non-hot.check

+13-13
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
-- Error: tests/init/neg/inherit-non-hot.scala:6:34 --------------------------------------------------------------------
1+
-- Error: tests/init/neg/inherit-non-hot.scala:6:32 --------------------------------------------------------------------
22
6 | if b == null then b = new B(this) // error
3-
| ^^^^^^^^^^^
4-
| The RHS of reassignment must be fully initialized. Calling trace:
5-
| -> class C extends A { [ inherit-non-hot.scala:15 ]
6-
| ^
7-
| -> val bAgain = toB.getBAgain [ inherit-non-hot.scala:16 ]
8-
| ^^^
9-
| -> def toB: B = [ inherit-non-hot.scala:5 ]
10-
| ^
11-
| -> if b == null then b = new B(this) // error [ inherit-non-hot.scala:6 ]
12-
| ^^^^^^^^^^^
3+
| ^^^^^^^^^^^^^^^
4+
|The RHS of reassignment must be fully initialized. Found = Warm[class B] { outer = Hot, args = (Cold) }. Calling trace:
5+
|-> class C extends A { [ inherit-non-hot.scala:15 ]
6+
| ^
7+
|-> val bAgain = toB.getBAgain [ inherit-non-hot.scala:16 ]
8+
| ^^^
9+
|-> def toB: B = [ inherit-non-hot.scala:5 ]
10+
| ^
11+
|-> if b == null then b = new B(this) // error [ inherit-non-hot.scala:6 ]
12+
| ^^^^^^^^^^^^^^^
1313
|
14-
| Promoting the value to fully initialized failed due to the following problem:
15-
| Cannot prove that the field val a is fully initialized.
14+
|Promoting the value to fully initialized failed due to the following problem:
15+
|Cannot prove that the field val a is fully initialized.

tests/init/neg/local-warm4.check

-26
This file was deleted.

tests/init/neg/local-warm4.scala renamed to tests/init/pos/local-warm4.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ object localWarm {
1515
override def increment(): Unit = {
1616
def updateA(): Unit = {
1717
val newA = new A(y)
18-
a = newA // error
18+
a = newA // ok: newA can be promoted to hot
1919
}
2020
y = y + 1
2121
updateA()

tests/init/pos/patternMatcher.scala

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import scala.collection.mutable
2+
3+
class Translater:
4+
val count = new mutable.HashMap[Int, Int] {
5+
override def default(key: Int) = 0
6+
}
7+
count.get(10)
8+
val n = 10

0 commit comments

Comments
 (0)