aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-12-16 18:33:39 +0100
committerMartin Odersky <odersky@gmail.com>2013-12-16 18:34:24 +0100
commite1e372cc833e3e9d0d02c1ffa453667f50dbc784 (patch)
treea28dd45cf2c696204e82dddfd2a4e0ba8e06517e /src
parent00507cf758cfafa36dc4da372a7e53028fa979a4 (diff)
downloaddotty-e1e372cc833e3e9d0d02c1ffa453667f50dbc784.tar.gz
dotty-e1e372cc833e3e9d0d02c1ffa453667f50dbc784.tar.bz2
dotty-e1e372cc833e3e9d0d02c1ffa453667f50dbc784.zip
Better handling of cyclic reference errors.
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala1
-rw-r--r--src/dotty/tools/dotc/typer/ErrorReporting.scala19
-rw-r--r--src/dotty/tools/dotc/typer/Mode.scala1
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala19
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala4
5 files changed, 42 insertions, 2 deletions
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index ccf4f83e7..0fd8f1acb 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -692,6 +692,7 @@ object SymDenotations {
else if (isClass) "class"
else if (isType) "type"
else if (this is Module) "module"
+ else if (this is Method) "method"
else "val"
s"$kindString $name"
}
diff --git a/src/dotty/tools/dotc/typer/ErrorReporting.scala b/src/dotty/tools/dotc/typer/ErrorReporting.scala
index 9b6188fe6..372d12f82 100644
--- a/src/dotty/tools/dotc/typer/ErrorReporting.scala
+++ b/src/dotty/tools/dotc/typer/ErrorReporting.scala
@@ -24,6 +24,25 @@ object ErrorReporting {
ErrorType
}
+ def cyclicErrorMsg(ex: CyclicReference)(implicit ctx: Context) = {
+ val cycleSym = ex.denot.symbol
+ def errorMsg(msg: String, cx: Context): String =
+ if (cx.mode is Mode.InferringReturnType) {
+ cx.tree match {
+ case tree: Trees.ValOrDefDef[_] =>
+ val treeSym = ctx.symOfContextTree(tree)
+ if (treeSym.exists && treeSym.name == cycleSym.name && treeSym.owner == cycleSym.owner) {
+ val result = if (cycleSym.isSourceMethod) " result" else ""
+ i"overloaded or recursive $cycleSym needs$result type"
+ }
+ else errorMsg(msg, cx.outer)
+ case _ =>
+ errorMsg(msg, cx.outer)
+ }
+ } else msg
+ errorMsg(ex.getMessage, ctx)
+ }
+
class Errors(implicit ctx: Context) {
def expectedTypeStr(tp: Type): String = tp match {
diff --git a/src/dotty/tools/dotc/typer/Mode.scala b/src/dotty/tools/dotc/typer/Mode.scala
index 8b8b74b84..b11d4dc7d 100644
--- a/src/dotty/tools/dotc/typer/Mode.scala
+++ b/src/dotty/tools/dotc/typer/Mode.scala
@@ -29,6 +29,7 @@ object Mode {
val Type = newMode(1, "Type")
val ImplicitsEnabled = newMode(2, "ImplicitsEnabled")
+ val InferringReturnType = newMode(3, "InferencingReturnType")
val PatternOrType = Pattern | Type
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index e054aaa3a..3e39c3926 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -47,6 +47,22 @@ trait NamerContextOps { this: Context =>
def effectiveScope: Scope =
if (owner != null && owner.isClass) owner.asClass.decls
else scope
+
+ /** The symbol (stored in some typer's symTree) of an enclosing context definition */
+ def symOfContextTree(tree: untpd.Tree) = {
+ def go(ctx: Context): Symbol = {
+ val typer = ctx.typer
+ if (typer == null) NoSymbol
+ else typer.symOfTree get tree match {
+ case Some(sym) => sym
+ case None =>
+ var cx = ctx.outer
+ while (cx.typer eq typer) cx = cx.outer
+ go(cx)
+ }
+ }
+ go(this)
+ }
}
/** This class creates symbols from definitions and imports and gives them
@@ -416,7 +432,8 @@ class Namer { typer: Typer =>
}
// println(s"final inherited for $sym: ${inherited.toString}") !!!
// println(s"owner = ${sym.owner}, decls = ${sym.owner.info.decls.show}")
- def rhsType = adapt(typedAheadExpr(mdef.rhs), WildcardType).tpe.widen
+ val rhsCtx = ctx.fresh addMode Mode.InferringReturnType
+ def rhsType = adapt(typedAheadExpr(mdef.rhs)(rhsCtx), WildcardType).tpe.widen
def lhsType = fullyDefinedType(rhsType, "right-hand side", mdef.pos)
inherited orElse lhsType
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 20f9aeb19..6b6252638 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -831,8 +831,9 @@ class Typer extends Namer with Applications with Implicits {
typedTree remove xtree match {
case Some(ttree) => ttree
case none =>
- val sym = symOfTree.remove(xtree).getOrElse(NoSymbol)
+ val sym = symOfTree.getOrElse(xtree, NoSymbol)
sym.ensureCompleted()
+ symOfTree.remove(xtree)
def localContext = ctx.fresh.withOwner(sym).withTree(xtree)
def typedNamed(tree: untpd.NameTree): Tree = tree match {
@@ -900,6 +901,7 @@ class Typer extends Namer with Applications with Implicits {
def typed(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = ctx.traceIndented (s"typing ${tree.show}", show = true) {
try adapt(typedUnadapted(tree, pt), pt)
catch {
+ case ex: CyclicReference => errorTree(tree, cyclicErrorMsg(ex))
case ex: FatalTypeError => errorTree(tree, ex.getMessage)
}
}