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