diff options
author | Hubert Plociniczak <hubert.plociniczak@epfl.ch> | 2011-09-07 12:17:54 +0000 |
---|---|---|
committer | Hubert Plociniczak <hubert.plociniczak@epfl.ch> | 2011-09-07 12:17:54 +0000 |
commit | 620f339bbaadad57daa696007660bb887372e927 (patch) | |
tree | e9bf93cfa9d93a299f24cab28577900c36260438 /src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala | |
parent | 596be479f1e527230f92db320642f77bae7e386d (diff) | |
download | scala-620f339bbaadad57daa696007660bb887372e927.tar.gz scala-620f339bbaadad57daa696007660bb887372e927.tar.bz2 scala-620f339bbaadad57daa696007660bb887372e927.zip |
First refactoring related to Error trees.
There are no more direct calls to context.error from Typers and Infer,
so more work needs to be done to finish it for Implicits and Namers.
I am pushing it to trunk so that all of you can share my pain (and
complain). Please do not add any more context.error randomly in that
code, instead deal with it appropriately (by creating specific error
tree).
I was trying to be as informative when it comes to error tree names
as possible, but if you feel like changing names to something more
appropriate then feel free to do so. When it comes to printing error
messages I tried to follow test suite as closily as possible but
obviously there were few changes to some tests (mostly positive, I
believe).
On my machine performance drawback was neglible but I am working on more
aggressive caching to reduce the penalty of containsError() calls even
more. Any suggestions welcome.
At the moment the code supports both styles i.e. throwing type errors
for the cases that are not yet handled and generating error trees. But
in the future we will drop the former completely (apart from cyclic
errors which can pop up almost everywhere).
Review by odersky, extempore and anyone who feels like it.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala | 73 |
1 files changed, 21 insertions, 52 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index 6e0e78e8e2..0b84e67447 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -135,21 +135,6 @@ trait TypeDiagnostics { def alternativesString(tree: Tree) = alternatives(tree) map (x => " " + methodTypeErrorString(x)) mkString ("", " <and>\n", "\n") - def missingParameterTypeMsg(fun: Tree, vparam: ValDef, pt: Type) = { - def anonMessage = ( - "\nThe argument types of an anonymous function must be fully known. (SLS 8.5)" + - "\nExpected type was: " + pt.toLongString - ) - val suffix = - if (!vparam.mods.isSynthetic) "" - else " for expanded function" + (fun match { - case Function(_, Match(_, _)) => anonMessage - case _ => " " + fun - }) - - "missing parameter type" + suffix - } - def treeSymTypeMsg(tree: Tree): String = { val sym = tree.symbol def hasParams = tree.tpe.paramSectionCount > 0 @@ -168,34 +153,6 @@ trait TypeDiagnostics { else defaultMessage } - def notEnoughArgumentsMsg(fun: Tree, missing: List[Symbol]): String = { - val suffix = { - if (missing.isEmpty) "" - else { - val keep = missing take 3 map (_.name) - ".\nUnspecified value parameter%s %s".format( - if (missing.tail.isEmpty) "" else "s", - if (missing drop 3 nonEmpty) (keep :+ "...").mkString(", ") - else keep.mkString("", ", ", ".") - ) - } - } - - "not enough arguments for " + treeSymTypeMsg(fun) + suffix - } - - def applyErrorMsg(tree: Tree, msg: String, argtpes: List[Type], pt: Type) = { - def asParams(xs: List[Any]) = xs.mkString("(", ", ", ")") - - def resType = if (pt isWildcard) "" else " with expected result type " + pt - def allTypes = (alternatives(tree) flatMap (_.paramTypes)) ++ argtpes :+ pt - def locals = alternatives(tree) flatMap (_.typeParams) - - withDisambiguation(locals, allTypes: _*) { - treeSymTypeMsg(tree) + msg + asParams(argtpes) + resType - } - } - def disambiguate(ss: List[String]) = ss match { case Nil => Nil case s :: ss => s :: (ss map { case `s` => "(some other)"+s ; case x => x }) @@ -405,8 +362,10 @@ trait TypeDiagnostics { trait TyperDiagnostics { self: Typer => - private def contextError(pos: Position, msg: String) = context.error(pos, msg) - private def contextError(pos: Position, err: Throwable) = context.error(pos, err) + private def contextError(pos: Position, msg: String) { contextError(context, pos, msg) } + private def contextError(context0: Analyzer#Context, pos: Position, msg: String) { context0.error(pos, msg) } + private def contextError(pos: Position, err: Throwable) { contextError(context, pos, err) } + private def contextError(context0: Analyzer#Context, pos: Position, err: Throwable) { context0.error(pos, err) } object checkDead { private var expr: Symbol = NoSymbol @@ -440,36 +399,46 @@ trait TypeDiagnostics { } } - def symWasOverloaded(sym: Symbol) = sym.owner.isClass && sym.owner.info.member(sym.name).isOverloaded - def cyclicAdjective(sym: Symbol) = if (symWasOverloaded(sym)) "overloaded" else "recursive" + private def symWasOverloaded(sym: Symbol) = sym.owner.isClass && sym.owner.info.member(sym.name).isOverloaded + private def cyclicAdjective(sym: Symbol) = if (symWasOverloaded(sym)) "overloaded" else "recursive" /** Returns Some(msg) if the given tree is untyped apparently due * to a cyclic reference, and None otherwise. */ - def cyclicReferenceMessage(sym: Symbol, tree: Tree) = condOpt(tree) { + private def cyclicReferenceMessage(sym: Symbol, tree: Tree) = condOpt(tree) { case ValDef(_, _, tpt, _) if tpt.tpe == null => "recursive "+sym+" needs type" case DefDef(_, _, _, _, tpt, _) if tpt.tpe == null => List(cyclicAdjective(sym), sym, "needs result type") mkString " " } + def reportTypeError(pos: Position, ex: TypeError) { + reportTypeError(context, pos, ex) + } + /** Report a type error. * * @param pos0 The position where to report the error * @param ex The exception that caused the error */ - def reportTypeError(pos: Position, ex: TypeError) { + def reportTypeError(context0: Analyzer#Context, pos: Position, ex: TypeError) { if (ex.pos == NoPosition) ex.pos = pos - if (!context.reportGeneralErrors) throw ex + if (!context0.reportGeneralErrors) throw ex if (settings.debug.value) ex.printStackTrace() ex match { case CyclicReference(sym, info: TypeCompleter) => - contextError(ex.pos, cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage()) + contextError(context0, ex.pos, cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage()) if (sym == ObjectClass) throw new FatalError("cannot redefine root "+sym) case _ => - contextError(ex.pos, ex) + contextError(context0, ex.pos, ex) } } + + def emitAllErrorTrees(tree: Tree, context: Context) = + errorTreesFinder(tree).foreach(_.emit(context)) + + def findAllNestedErrors(trees: List[Tree]): List[ErrorTree] = + trees.map(errorTreesFinder(_)).flatten } } |