diff options
author | Martin Odersky <odersky@gmail.com> | 2013-12-16 18:33:39 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-12-16 18:34:24 +0100 |
commit | e1e372cc833e3e9d0d02c1ffa453667f50dbc784 (patch) | |
tree | a28dd45cf2c696204e82dddfd2a4e0ba8e06517e /src | |
parent | 00507cf758cfafa36dc4da372a7e53028fa979a4 (diff) | |
download | dotty-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.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/ErrorReporting.scala | 19 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Mode.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 19 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 4 |
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) } } |