Skip to content

Underline assignment correctly in error message #15584

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 25 additions & 11 deletions compiler/src/dotty/tools/dotc/transform/init/Semantic.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,17 @@ object Semantic:
*
*/
sealed abstract class Value:
def show: String = this.toString()
def show(using Context): String = this match
case ThisRef(klass) =>
"ThisRef[" + klass.show + "]"
case Warm(klass, outer, ctor, args) =>
"Warm[" + klass.show + "] { outer = " + outer.show + ", args = " + args.map(_.show).mkString("(", ", ", ")") + " }"
case Fun(expr, thisV, klass) =>
"Fun { this = " + thisV.show + ", owner = " + klass.show + " }"
case RefSet(values) =>
values.map(_.show).mkString("Set { ", ", ", " }")
case _ =>
this.toString()

def isHot = this == Hot
def isCold = this == Cold
Expand Down Expand Up @@ -792,8 +802,11 @@ object Semantic:
else
// no source code available
promoteArgs()
val error = CallUnknown(target, trace.toVector)
reporter.report(error)
// try promoting the receiver as last resort
val hasErrors = Reporter.hasErrors { ref.promote("try promote value to hot") }
if hasErrors then
val error = CallUnknown(target, trace.toVector)
reporter.report(error)
Hot
else
// method call resolves to a field
Expand Down Expand Up @@ -1036,9 +1049,9 @@ object Semantic:
extension (value: Value)
/** Promotion of values to hot */
def promote(msg: String): Contextual[Unit] = log("promoting " + value + ", promoted = " + promoted, printer) {
if promoted.isCurrentObjectPromoted then Nil else
if !promoted.isCurrentObjectPromoted then

value.match
value match
case Hot =>

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

val errors = Reporter.stopEarly {
for klass <- warm.klass.baseClasses if klass.hasSource do
Expand Down Expand Up @@ -1349,13 +1363,13 @@ object Semantic:
case Select(qual, _) =>
eval(qual, thisV, klass)
val res = eval(rhs, thisV, klass)
extendTrace(rhs) {
res.ensureHot("The RHS of reassignment must be fully initialized.")
extendTrace(expr) {
res.ensureHot("The RHS of reassignment must be fully initialized. Found = " + res.show + ". ")
}
case id: Ident =>
val res = eval(rhs, thisV, klass)
extendTrace(rhs) {
res.ensureHot("The RHS of reassignment must be fully initialized.")
extendTrace(expr) {
res.ensureHot("The RHS of reassignment must be fully initialized. Found = " + res.show + ". ")
}

case closureDef(ddef) =>
Expand Down
4 changes: 2 additions & 2 deletions tests/init/neg/apply2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ object O:
println(n)

class B:
val a = A(this) // error
val a = A(this)

val b = new B
val n = 10
val n = 10 // error
end O
26 changes: 13 additions & 13 deletions tests/init/neg/inherit-non-hot.check
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
-- Error: tests/init/neg/inherit-non-hot.scala:6:34 --------------------------------------------------------------------
-- Error: tests/init/neg/inherit-non-hot.scala:6:32 --------------------------------------------------------------------
6 | if b == null then b = new B(this) // error
| ^^^^^^^^^^^
| The RHS of reassignment must be fully initialized. Calling trace:
| -> class C extends A { [ inherit-non-hot.scala:15 ]
| ^
| -> val bAgain = toB.getBAgain [ inherit-non-hot.scala:16 ]
| ^^^
| -> def toB: B = [ inherit-non-hot.scala:5 ]
| ^
| -> if b == null then b = new B(this) // error [ inherit-non-hot.scala:6 ]
| ^^^^^^^^^^^
| ^^^^^^^^^^^^^^^
|The RHS of reassignment must be fully initialized. Found = Warm[class B] { outer = Hot, args = (Cold) }. Calling trace:
|-> class C extends A { [ inherit-non-hot.scala:15 ]
| ^
|-> val bAgain = toB.getBAgain [ inherit-non-hot.scala:16 ]
| ^^^
|-> def toB: B = [ inherit-non-hot.scala:5 ]
| ^
|-> if b == null then b = new B(this) // error [ inherit-non-hot.scala:6 ]
| ^^^^^^^^^^^^^^^
|
| Promoting the value to fully initialized failed due to the following problem:
| Cannot prove that the field val a is fully initialized.
|Promoting the value to fully initialized failed due to the following problem:
|Cannot prove that the field val a is fully initialized.
26 changes: 0 additions & 26 deletions tests/init/neg/local-warm4.check

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ object localWarm {
override def increment(): Unit = {
def updateA(): Unit = {
val newA = new A(y)
a = newA // error
a = newA // ok: newA can be promoted to hot
}
y = y + 1
updateA()
Expand Down
8 changes: 8 additions & 0 deletions tests/init/pos/patternMatcher.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import scala.collection.mutable

class Translater:
val count = new mutable.HashMap[Int, Int] {
override def default(key: Int) = 0
}
count.get(10)
val n = 10