1
+ package dotty .tools
2
+ package dotc
3
+ package core
4
+
5
+ import util .common ._
6
+ import Types ._
7
+ import Symbols ._
8
+ import Flags ._
9
+ import Names ._
10
+ import Contexts ._
11
+ import SymDenotations ._
12
+ import Denotations ._
13
+ import Decorators ._
14
+ import reporting .diagnostic .Message
15
+ import reporting .diagnostic .messages ._
16
+ import ast .untpd
17
+ import config .Printers .cyclicErrors
18
+
19
+ class TypeError (msg : String ) extends Exception (msg) {
20
+ def this () = this (" " )
21
+ def toMessage (implicit ctx : Context ): Message = getMessage
22
+ }
23
+
24
+ class MalformedType (pre : Type , denot : Denotation , absMembers : Set [Name ]) extends TypeError {
25
+ override def toMessage (implicit ctx : Context ): Message =
26
+ 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(" , " )}"
27
+ }
28
+
29
+ class MissingType (pre : Type , name : Name ) extends TypeError {
30
+ private def otherReason (pre : Type )(implicit ctx : Context ): String = pre match {
31
+ case pre : ThisType if pre.cls.givenSelfType.exists =>
32
+ i " \n or the self type of $pre might not contain all transitive dependencies "
33
+ case _ => " "
34
+ }
35
+
36
+ override def toMessage (implicit ctx : Context ): Message = {
37
+ if (ctx.debug) printStackTrace()
38
+ i """ cannot resolve reference to type $pre. $name
39
+ |the classfile defining the type might be missing from the classpath ${otherReason(pre)}"""
40
+ }
41
+ }
42
+
43
+ class RecursionOverflow (val op : String , details : => String , previous : Throwable , val weight : Int ) extends TypeError {
44
+
45
+ def explanation = s " $op $details"
46
+
47
+ private def recursions : List [RecursionOverflow ] = {
48
+ val nested = previous match {
49
+ case previous : RecursionOverflow => previous.recursions
50
+ case _ => Nil
51
+ }
52
+ this :: nested
53
+ }
54
+
55
+ def opsString (rs : List [RecursionOverflow ])(implicit ctx : Context ): String = {
56
+ val maxShown = 20
57
+ if (rs.lengthCompare(maxShown) > 0 )
58
+ i """ ${opsString(rs.take(maxShown / 2 ))}
59
+ | ...
60
+ | ${opsString(rs.takeRight(maxShown / 2 ))}"""
61
+ else
62
+ (rs.map(_.explanation): List [String ]).mkString(" \n " , " \n | " , " " )
63
+ }
64
+
65
+ override def toMessage (implicit ctx : Context ): Message = {
66
+ val mostCommon = recursions.groupBy(_.op).toList.maxBy(_._2.map(_.weight).sum)._2.reverse
67
+ s """ Recursion limit exceeded.
68
+ |Maybe there is an illegal cyclic reference?
69
+ |A recurring operation is (inner to outer):
70
+ | ${opsString(mostCommon)}""" .stripMargin
71
+ }
72
+
73
+ override def fillInStackTrace (): Throwable = this
74
+ override def getStackTrace () = previous.getStackTrace()
75
+ }
76
+
77
+ object handleRecursive {
78
+ def apply (op : String , details : => String , exc : Throwable , weight : Int = 1 ): Nothing = exc match {
79
+ case _ : RecursionOverflow =>
80
+ throw new RecursionOverflow (op, details, exc, weight)
81
+ case _ =>
82
+ var e = exc
83
+ while (e != null && ! e.isInstanceOf [StackOverflowError ]) e = e.getCause
84
+ if (e != null ) throw new RecursionOverflow (op, details, e, weight)
85
+ else throw exc
86
+ }
87
+ }
88
+
89
+ class CyclicReference private (val denot : SymDenotation ) extends TypeError {
90
+ override def toMessage (implicit ctx : Context ) = {
91
+ val cycleSym = denot.symbol
92
+ def errorMsg (msg : Message , cx : Context ): Message =
93
+ if (cx.mode is Mode .InferringReturnType ) {
94
+ cx.tree match {
95
+ case tree : untpd.DefDef if ! tree.tpt.typeOpt.exists =>
96
+ OverloadedOrRecursiveMethodNeedsResultType (tree.name)
97
+ case tree : untpd.ValDef if ! tree.tpt.typeOpt.exists =>
98
+ RecursiveValueNeedsResultType (tree.name)
99
+ case _ =>
100
+ errorMsg(msg, cx.outer)
101
+ }
102
+ } else msg
103
+
104
+ if (cycleSym.is(Implicit , butNot = Method ) && cycleSym.owner.isTerm)
105
+ CyclicReferenceInvolvingImplicit (cycleSym)
106
+ else
107
+ CyclicReferenceInvolving (denot)
108
+ }
109
+ }
110
+
111
+ object CyclicReference {
112
+ def apply (denot : SymDenotation )(implicit ctx : Context ): CyclicReference = {
113
+ val ex = new CyclicReference (denot)
114
+ if (! (ctx.mode is Mode .CheckCyclic )) {
115
+ cyclicErrors.println(ex.getMessage)
116
+ for (elem <- ex.getStackTrace take 200 )
117
+ cyclicErrors.println(elem.toString)
118
+ }
119
+ ex
120
+ }
121
+ }
122
+
123
+ class MergeError (msg : String , val tp1 : Type , val tp2 : Type ) extends TypeError (msg)
0 commit comments