-
Notifications
You must be signed in to change notification settings - Fork 1k
/
Errors.scala
116 lines (95 loc) · 3.94 KB
/
Errors.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package dotty.tools.dotc
package transform
package init
import ast.tpd._
import core._
import Decorators._
import Types._, Symbols._, Contexts._
import util.NoSourcePosition
import Effects._, Potentials._
object Errors {
type Errors = Set[Error]
val empty: Errors = Set.empty
def show(errs: Errors)(implicit ctx: Context): String =
errs.map(_.show).mkString(", ")
sealed trait Error {
def source: Tree
def trace: Vector[Tree]
def show(implicit ctx: Context): String
def report(implicit ctx: Context): Unit =
ctx.warning(show + stacktrace, source.sourcePos)
def toErrors: Errors = Set(this)
def stacktrace(implicit ctx: Context): String = if (trace.isEmpty) "" else " Calling trace:\n" + {
var indentCount = 0
var last = ""
val sb = new StringBuilder
trace.foreach { tree =>
indentCount += 1
val pos = tree.sourcePos
val line = "[ " + pos.source.file.name + ":" + (pos.line + 1) + " ]"
if (last != line)
sb.append(
if (pos.source.exists)
i"${ " " * indentCount }-> ${pos.lineContent.trim}\t$line\n"
else
i"${tree.show}\n"
)
last = line
}
sb.toString
}
/** Flatten UnsafePromotion errors
*/
def flatten: Errors = this match {
case unsafe: UnsafePromotion => unsafe.errors.flatMap(_.flatten)
case _ => Set(this)
}
}
/** Access non-initialized field */
case class AccessNonInit(field: Symbol, trace: Vector[Tree]) extends Error {
def source: Tree = trace.last
def show(implicit ctx: Context): String =
"Access non-initialized field " + field.show + "."
override def report(implicit ctx: Context): Unit = ctx.error(show + stacktrace, field.sourcePos)
}
/** Promote `this` under initialization to fully-initialized */
case class PromoteThis(pot: ThisRef, source: Tree, trace: Vector[Tree]) extends Error {
def show(implicit ctx: Context): String = "Promote the value under initialization to fully-initialized."
}
/** Promote `this` under initialization to fully-initialized */
case class PromoteWarm(pot: Warm, source: Tree, trace: Vector[Tree]) extends Error {
def show(implicit ctx: Context): String =
"Promoting the value under initialization to fully-initialized."
}
/** Promote a cold value under initialization to fully-initialized */
case class PromoteCold(source: Tree, trace: Vector[Tree]) extends Error {
def show(implicit ctx: Context): String =
"Promoting the value " + source.show + " to fully-initialized while it is under initialization" + "."
}
case class AccessCold(field: Symbol, source: Tree, trace: Vector[Tree]) extends Error {
def show(implicit ctx: Context): String =
"Access field " + source.show + " on a value with an unknown initialization status" + "."
}
case class CallCold(meth: Symbol, source: Tree, trace: Vector[Tree]) extends Error {
def show(implicit ctx: Context): String =
"Call method " + source.show + " on a value with an unknown initialization" + "."
}
case class CallUnknown(meth: Symbol, source: Tree, trace: Vector[Tree]) extends Error {
def show(implicit ctx: Context): String =
"Calling the external method " + meth.show + " may cause initialization errors" + "."
}
/** Promote a value under initialization to fully-initialized */
case class UnsafePromotion(pot: Potential, source: Tree, trace: Vector[Tree], errors: Errors) extends Error {
assert(errors.nonEmpty)
override def report(implicit ctx: Context): Unit = ctx.warning(show, source.sourcePos)
def show(implicit ctx: Context): String = {
var index = 0
"Promoting the value to fully-initialized is unsafe.\n" + stacktrace +
"\nThe unsafe promotion may cause the following problem(s):\n" +
(errors.flatMap(_.flatten).map { error =>
index += 1
s"\n$index. " + error.show + error.stacktrace
}.mkString)
}
}
}