@@ -14,37 +14,44 @@ import reporting._
14
14
import ast .untpd
15
15
import config .Printers .cyclicErrors
16
16
17
- class TypeError (msg : String ) extends Exception (msg) {
18
- def this () = this (" " )
19
- final def toMessage (using Context ): Message =
20
- withMode(Mode .Printing )(produceMessage)
21
- def produceMessage (using Context ): Message = super .getMessage.nn.toMessage
22
- override def getMessage : String = super .getMessage.nn
23
- }
24
-
25
- class MalformedType (pre : Type , denot : Denotation , absMembers : Set [Name ]) extends TypeError {
26
- override def produceMessage (using Context ): Message =
27
- i " malformed type: $pre is not a legal prefix for $denot because it contains abstract type member ${if (absMembers.size == 1 ) " " else " s" } ${absMembers.mkString(" , " )}"
28
- .toMessage
29
- }
30
-
31
- class MissingType (pre : Type , name : Name ) extends TypeError {
17
+ abstract class TypeError (using creationContext : Context ) extends Exception (" " ):
18
+
19
+ /** Convert to message. This uses an additional Context, so that we
20
+ * use the context when the message is first produced, i.e. when the TypeError
21
+ * is handled. This makes a difference for CyclicErrors since we need to know
22
+ * the context where the completed symbol is referenced, but the creation
23
+ * context of the CyclicReference is the completion context for the symbol.
24
+ * See i2887b for a test case, where we want to see
25
+ * "recursive or overloaded method needs result type".
26
+ */
27
+ def toMessage (using Context ): Message
28
+
29
+ /** Uses creation context to produce the message */
30
+ override def getMessage : String = toMessage.message
31
+
32
+ object TypeError :
33
+ def apply (msg : Message )(using Context ) = new TypeError :
34
+ def toMessage (using Context ) = msg
35
+ end TypeError
36
+
37
+ class MalformedType (pre : Type , denot : Denotation , absMembers : Set [Name ])(using Context ) extends TypeError :
38
+ def toMessage (using Context ) = em " malformed type: $pre is not a legal prefix for $denot because it contains abstract type member ${if (absMembers.size == 1 ) " " else " s" } ${absMembers.mkString(" , " )}"
39
+
40
+ class MissingType (pre : Type , name : Name )(using Context ) extends TypeError :
32
41
private def otherReason (pre : Type )(using Context ): String = pre match {
33
42
case pre : ThisType if pre.cls.givenSelfType.exists =>
34
43
i " \n or the self type of $pre might not contain all transitive dependencies "
35
44
case _ => " "
36
45
}
37
46
38
- override def produceMessage (using Context ): Message = {
39
- if (ctx.debug) printStackTrace()
40
- i """ cannot resolve reference to type $pre. $name
41
- |the classfile defining the type might be missing from the classpath ${otherReason(pre)}"""
42
- .toMessage
43
- }
44
- }
47
+ override def toMessage (using Context ): Message =
48
+ if ctx.debug then printStackTrace()
49
+ em """ cannot resolve reference to type $pre. $name
50
+ |the classfile defining the type might be missing from the classpath ${otherReason(pre)}"""
51
+ end MissingType
45
52
46
- class RecursionOverflow (val op : String , details : => String , val previous : Throwable , val weight : Int )
47
- extends TypeError {
53
+ class RecursionOverflow (val op : String , details : => String , val previous : Throwable , val weight : Int )( using Context )
54
+ extends TypeError :
48
55
49
56
def explanation : String = s " $op $details"
50
57
@@ -71,19 +78,18 @@ extends TypeError {
71
78
(rs.map(_.explanation): List [String ]).mkString(" \n " , " \n | " , " " )
72
79
}
73
80
74
- override def produceMessage (using Context ): Message = NoExplanation {
81
+ override def toMessage (using Context ): Message =
75
82
val mostCommon = recursions.groupBy(_.op).toList.maxBy(_._2.map(_.weight).sum)._2.reverse
76
- s """ Recursion limit exceeded.
77
- |Maybe there is an illegal cyclic reference?
78
- |If that's not the case, you could also try to increase the stacksize using the -Xss JVM option.
79
- |For the unprocessed stack trace, compile with -Yno-decode-stacktraces.
80
- |A recurring operation is (inner to outer):
81
- | ${opsString(mostCommon)}""" .stripMargin
82
- }
83
+ em """ Recursion limit exceeded.
84
+ |Maybe there is an illegal cyclic reference?
85
+ |If that's not the case, you could also try to increase the stacksize using the -Xss JVM option.
86
+ |For the unprocessed stack trace, compile with -Yno-decode-stacktraces.
87
+ |A recurring operation is (inner to outer):
88
+ | ${opsString(mostCommon).stripMargin}"""
83
89
84
90
override def fillInStackTrace (): Throwable = this
85
91
override def getStackTrace (): Array [StackTraceElement ] = previous.getStackTrace().asInstanceOf
86
- }
92
+ end RecursionOverflow
87
93
88
94
/** Post-process exceptions that might result from StackOverflow to add
89
95
* tracing information while unwalking the stack.
@@ -111,10 +117,10 @@ object handleRecursive {
111
117
* so it requires knowing denot already.
112
118
* @param denot
113
119
*/
114
- class CyclicReference private (val denot : SymDenotation ) extends TypeError {
120
+ class CyclicReference private (val denot : SymDenotation )( using Context ) extends TypeError :
115
121
var inImplicitSearch : Boolean = false
116
122
117
- override def produceMessage (using Context ): Message = {
123
+ override def toMessage (using Context ): Message =
118
124
val cycleSym = denot.symbol
119
125
120
126
// cycleSym.flags would try completing denot and would fail, but here we can use flagsUNSAFE to detect flags
@@ -151,19 +157,16 @@ class CyclicReference private (val denot: SymDenotation) extends TypeError {
151
157
CyclicReferenceInvolving (denot)
152
158
153
159
errorMsg(ctx)
154
- }
155
- }
160
+ end toMessage
156
161
157
- object CyclicReference {
158
- def apply (denot : SymDenotation )(using Context ): CyclicReference = {
162
+ object CyclicReference :
163
+ def apply (denot : SymDenotation )(using Context ): CyclicReference =
159
164
val ex = new CyclicReference (denot)
160
- if ( ! (ctx.mode is Mode .CheckCyclic ) || ctx.settings.Ydebug .value) {
165
+ if ! (ctx.mode is Mode .CheckCyclic ) || ctx.settings.Ydebug .value then
161
166
cyclicErrors.println(s " Cyclic reference involving! $denot" )
162
167
val sts = ex.getStackTrace.asInstanceOf [Array [StackTraceElement ]]
163
168
for (elem <- sts take 200 )
164
169
cyclicErrors.println(elem.toString)
165
- }
166
170
ex
167
- }
168
- }
171
+ end CyclicReference
169
172
0 commit comments