Skip to content

Commit 5c43324

Browse files
authored
Merge pull request #15682 from dotty-staging/zero-init-warnings
Fix remaining initialization warnings in bootstrapping
2 parents bb9c8ff + df875ee commit 5c43324

17 files changed

+241
-141
lines changed

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

Lines changed: 64 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,107 +6,119 @@ package init
66
import ast.tpd._
77
import core._
88
import util.SourcePosition
9+
import util.Property
910
import Decorators._, printing.SyntaxHighlighting
1011
import Types._, Symbols._, Contexts._
1112

1213
import scala.collection.mutable
1314

1415
object Errors:
16+
private val IsFromPromotion = new Property.Key[Boolean]
17+
1518
sealed trait Error:
1619
def trace: Seq[Tree]
1720
def show(using Context): String
1821

1922
def pos(using Context): SourcePosition = trace.last.sourcePos
2023

24+
def stacktrace(using Context): String =
25+
val preamble: String =
26+
if ctx.property(IsFromPromotion).nonEmpty
27+
then " Promotion trace:\n"
28+
else " Calling trace:\n"
29+
buildStacktrace(trace, preamble)
30+
2131
def issue(using Context): Unit =
2232
report.warning(show, this.pos)
33+
end Error
34+
35+
def buildStacktrace(trace: Seq[Tree], preamble: String)(using Context): String = if trace.isEmpty then "" else preamble + {
36+
var lastLineNum = -1
37+
var lines: mutable.ArrayBuffer[String] = new mutable.ArrayBuffer
38+
trace.foreach { tree =>
39+
val pos = tree.sourcePos
40+
val prefix = "-> "
41+
val line =
42+
if pos.source.exists then
43+
val loc = "[ " + pos.source.file.name + ":" + (pos.line + 1) + " ]"
44+
val code = SyntaxHighlighting.highlight(pos.lineContent.trim.nn)
45+
i"$code\t$loc"
46+
else
47+
tree.show
48+
val positionMarkerLine =
49+
if pos.exists && pos.source.exists then
50+
positionMarker(pos)
51+
else ""
52+
53+
// always use the more precise trace location
54+
if lastLineNum == pos.line then
55+
lines.dropRightInPlace(1)
2356

24-
def stacktrace(preamble: String = " Calling trace:\n")(using Context): String = if trace.isEmpty then "" else preamble + {
25-
var lastLineNum = -1
26-
var lines: mutable.ArrayBuffer[String] = new mutable.ArrayBuffer
27-
trace.foreach { tree =>
28-
val pos = tree.sourcePos
29-
val prefix = "-> "
30-
val line =
31-
if pos.source.exists then
32-
val loc = "[ " + pos.source.file.name + ":" + (pos.line + 1) + " ]"
33-
val code = SyntaxHighlighting.highlight(pos.lineContent.trim.nn)
34-
i"$code\t$loc"
35-
else
36-
tree.show
37-
val positionMarkerLine =
38-
if pos.exists && pos.source.exists then
39-
positionMarker(pos)
40-
else ""
41-
42-
// always use the more precise trace location
43-
if lastLineNum == pos.line then
44-
lines.dropRightInPlace(1)
45-
46-
lines += (prefix + line + "\n" + positionMarkerLine)
47-
48-
lastLineNum = pos.line
49-
}
50-
val sb = new StringBuilder
51-
for line <- lines do sb.append(line)
52-
sb.toString
57+
lines += (prefix + line + "\n" + positionMarkerLine)
58+
59+
lastLineNum = pos.line
5360
}
61+
val sb = new StringBuilder
62+
for line <- lines do sb.append(line)
63+
sb.toString
64+
}
5465

55-
/** Used to underline source positions in the stack trace
56-
* pos.source must exist
57-
*/
58-
private def positionMarker(pos: SourcePosition): String =
59-
val trimmed = pos.lineContent.takeWhile(c => c.isWhitespace).length
60-
val padding = pos.startColumnPadding.substring(trimmed).nn + " "
61-
val carets =
62-
if (pos.startLine == pos.endLine)
63-
"^" * math.max(1, pos.endColumn - pos.startColumn)
64-
else "^"
66+
/** Used to underline source positions in the stack trace
67+
* pos.source must exist
68+
*/
69+
private def positionMarker(pos: SourcePosition): String =
70+
val trimmed = pos.lineContent.takeWhile(c => c.isWhitespace).length
71+
val padding = pos.startColumnPadding.substring(trimmed).nn + " "
72+
val carets =
73+
if (pos.startLine == pos.endLine)
74+
"^" * math.max(1, pos.endColumn - pos.startColumn)
75+
else "^"
6576

66-
s"$padding$carets\n"
77+
s"$padding$carets\n"
6778

68-
override def toString() = this.getClass.getName.nn
69-
end Error
79+
override def toString() = this.getClass.getName.nn
7080

7181
/** Access non-initialized field */
7282
case class AccessNonInit(field: Symbol, trace: Seq[Tree]) extends Error:
7383
def source: Tree = trace.last
7484
def show(using Context): String =
75-
"Access non-initialized " + field.show + "." + stacktrace()
85+
"Access non-initialized " + field.show + "." + stacktrace
7686

7787
override def pos(using Context): SourcePosition = field.sourcePos
7888

7989
/** Promote a value under initialization to fully-initialized */
8090
case class PromoteError(msg: String, trace: Seq[Tree]) extends Error:
81-
def show(using Context): String = msg + stacktrace()
91+
def show(using Context): String = msg + stacktrace
8292

8393
case class AccessCold(field: Symbol, trace: Seq[Tree]) extends Error:
8494
def show(using Context): String =
85-
"Access field " + field.show + " on a cold object." + stacktrace()
95+
"Access field " + field.show + " on a cold object." + stacktrace
8696

8797
case class CallCold(meth: Symbol, trace: Seq[Tree]) extends Error:
8898
def show(using Context): String =
89-
"Call method " + meth.show + " on a cold object." + stacktrace()
99+
"Call method " + meth.show + " on a cold object." + stacktrace
90100

91101
case class CallUnknown(meth: Symbol, trace: Seq[Tree]) extends Error:
92102
def show(using Context): String =
93103
val prefix = if meth.is(Flags.Method) then "Calling the external method " else "Accessing the external field"
94-
prefix + meth.show + " may cause initialization errors." + stacktrace()
104+
prefix + meth.show + " may cause initialization errors." + stacktrace
95105

96106
/** Promote a value under initialization to fully-initialized */
97107
case class UnsafePromotion(msg: String, trace: Seq[Tree], error: Error) extends Error:
98108
def show(using Context): String =
99-
msg + stacktrace() + "\n" +
100-
"Promoting the value to fully initialized failed due to the following problem:\n" +
101-
error.show
109+
msg + stacktrace + "\n" +
110+
"Promoting the value to hot failed due to the following problem:\n" + {
111+
val ctx2 = ctx.withProperty(IsFromPromotion, Some(true))
112+
error.show(using ctx2)
113+
}
102114

103115
/** Unsafe leaking a non-hot value as constructor arguments
104116
*
105117
* Invariant: argsIndices.nonEmpty
106118
*/
107119
case class UnsafeLeaking(trace: Seq[Tree], error: Error, nonHotOuterClass: Symbol, argsIndices: List[Int]) extends Error:
108120
def show(using Context): String =
109-
"Problematic object instantiation: " + argumentInfo() + stacktrace() + "\n" +
121+
"Problematic object instantiation: " + argumentInfo() + stacktrace + "\n" +
110122
"It leads to the following error during object initialization:\n" +
111123
error.show
112124

@@ -129,5 +141,5 @@ object Errors:
129141
acc + text2
130142
}
131143
val verb = if multiple then " are " else " is "
132-
val adjective = "not fully initialized."
144+
val adjective = "not hot."
133145
subject + verb + adjective

0 commit comments

Comments
 (0)