diff options
author | Hubert Plociniczak <hubert.plociniczak@gmail.com> | 2013-04-23 22:22:25 +0200 |
---|---|---|
committer | Hubert Plociniczak <hubert.plociniczak@gmail.com> | 2013-04-26 16:20:38 +0200 |
commit | 71581425746e9d3239998569d6f85c710efbf17b (patch) | |
tree | bf243f80f644cd49f1c10050dff831845fcceb47 /src/compiler | |
parent | accaa314f3473553d9ffaff8c37e3c5b29f0f2e3 (diff) | |
download | scala-71581425746e9d3239998569d6f85c710efbf17b.tar.gz scala-71581425746e9d3239998569d6f85c710efbf17b.tar.bz2 scala-71581425746e9d3239998569d6f85c710efbf17b.zip |
SI-7291: Remove error kinds.
What seemed like a good idea initially (since potentially there were
many different kinds of errors that could be treated specially),
started to complicate the error logic.
So let's just match on the specific instance of an error to
manipulate the buffer.
Diffstat (limited to 'src/compiler')
4 files changed, 54 insertions, 46 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 5dd945eaea..a0660ce71d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -21,39 +21,39 @@ trait ContextErrors { import global._ import definitions._ - object ErrorKinds extends Enumeration { - type ErrorKind = Value - val Normal, Access, Ambiguous, Divergent = Value - } - - import ErrorKinds.ErrorKind - - trait AbsTypeError extends Throwable { + abstract class AbsTypeError extends Throwable { def errPos: Position def errMsg: String - def kind: ErrorKind + override def toString() = "[Type error at:" + errPos + "] " + errMsg } - case class NormalTypeError(underlyingTree: Tree, errMsg: String, kind: ErrorKind = ErrorKinds.Normal) - extends AbsTypeError { - - def errPos:Position = underlyingTree.pos - override def toString() = "[Type error at:" + underlyingTree.pos + "] " + errMsg + abstract class TreeTypeError extends AbsTypeError { + def underlyingTree: Tree + def errPos = underlyingTree.pos } - case class SymbolTypeError(underlyingSym: Symbol, errMsg: String, kind: ErrorKind = ErrorKinds.Normal) + case class NormalTypeError(underlyingTree: Tree, errMsg: String) + extends TreeTypeError + + case class AccessTypeError(underlyingTree: Tree, errMsg: String) + extends TreeTypeError + + case class AmbiguousTypeError(errPos: Position, errMsg: String) + extends AbsTypeError + + case class SymbolTypeError(underlyingSym: Symbol, errMsg: String) extends AbsTypeError { def errPos = underlyingSym.pos } - case class TypeErrorWrapper(ex: TypeError, kind: ErrorKind = ErrorKinds.Normal) + case class TypeErrorWrapper(ex: TypeError) extends AbsTypeError { def errMsg = ex.msg def errPos = ex.pos } - case class TypeErrorWithUnderlyingTree(tree: Tree, ex: TypeError, kind: ErrorKind = ErrorKinds.Normal) + case class TypeErrorWithUnderlyingTree(tree: Tree, ex: TypeError) extends AbsTypeError { def errMsg = ex.msg def errPos = tree.pos @@ -67,18 +67,19 @@ trait ContextErrors { // (pt at the point of divergence gives less information to the user) // Note: it is safe to delay error message generation in this case // becasue we don't modify implicits' infos. - case class DivergentImplicitTypeError(tree: Tree, pt0: Type, sym: Symbol) extends AbsTypeError { - def errPos: Position = tree.pos + case class DivergentImplicitTypeError(underlyingTree: Tree, pt0: Type, sym: Symbol) + extends TreeTypeError { def errMsg: String = errMsgForPt(pt0) - def kind = ErrorKinds.Divergent - def withPt(pt: Type): AbsTypeError = NormalTypeError(tree, errMsgForPt(pt), kind) + def withPt(pt: Type): AbsTypeError = this.copy(pt0 = pt) private def errMsgForPt(pt: Type) = s"diverging implicit expansion for type ${pt}\nstarting with ${sym.fullLocationString}" } - case class AmbiguousTypeError(underlyingTree: Tree, errPos: Position, errMsg: String, kind: ErrorKind = ErrorKinds.Ambiguous) extends AbsTypeError + case class AmbiguousImplicitTypeError(underlyingTree: Tree, errMsg: String) + extends TreeTypeError - case class PosAndMsgTypeError(errPos: Position, errMsg: String, kind: ErrorKind = ErrorKinds.Normal) extends AbsTypeError + case class PosAndMsgTypeError(errPos: Position, errMsg: String) + extends AbsTypeError object ErrorUtils { def issueNormalTypeError(tree: Tree, msg: String)(implicit context: Context) { @@ -89,7 +90,6 @@ trait ContextErrors { issueTypeError(SymbolTypeError(sym, msg)) } - def issueAmbiguousTypeError(pre: Type, sym1: Symbol, sym2: Symbol, err: AmbiguousTypeError)(implicit context: Context) { context.issueAmbiguousError(pre, sym1, sym2, err) } @@ -844,7 +844,7 @@ trait ContextErrors { underlyingSymbol(sym).fullLocationString + " cannot be accessed in " + location + explanation } - NormalTypeError(tree, errMsg, ErrorKinds.Access) + AccessTypeError(tree, errMsg) } def NoMethodInstanceError(fn: Tree, args: List[Tree], msg: String) = @@ -889,7 +889,7 @@ trait ContextErrors { "argument types " + argtpes.mkString("(", ",", ")") + (if (pt == WildcardType) "" else " and expected result type " + pt) val (pos, msg) = ambiguousErrorMsgPos(tree.pos, pre, best, firstCompeting, msg0) - issueAmbiguousTypeError(pre, best, firstCompeting, AmbiguousTypeError(tree, pos, msg)) + issueAmbiguousTypeError(pre, best, firstCompeting, AmbiguousTypeError(pos, msg)) setErrorOnLastTry(lastTry, tree) } else setError(tree) // do not even try further attempts because they should all fail // even if this is not the last attempt (because of the SO's possibility on the horizon) @@ -903,7 +903,7 @@ trait ContextErrors { def AmbiguousExprAlternativeError(tree: Tree, pre: Type, best: Symbol, firstCompeting: Symbol, pt: Type, lastTry: Boolean) = { val (pos, msg) = ambiguousErrorMsgPos(tree.pos, pre, best, firstCompeting, "expected type " + pt) - issueAmbiguousTypeError(pre, best, firstCompeting, AmbiguousTypeError(tree, pos, msg)) + issueAmbiguousTypeError(pre, best, firstCompeting, AmbiguousTypeError(pos, msg)) setErrorOnLastTry(lastTry, tree) } @@ -1188,7 +1188,7 @@ trait ContextErrors { if (explanation == "") "" else "\n" + explanation ) } - context.issueAmbiguousError(AmbiguousTypeError(tree, tree.pos, + context.issueAmbiguousError(AmbiguousImplicitTypeError(tree, if (isView) viewMsg else s"ambiguous implicit values:\n${coreMsg}match expected type $pt") ) diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 538b3b3b6c..f7b4a60144 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -1195,12 +1195,12 @@ trait Contexts { self: Analyzer => errorBuffer.clear() this } - def clearErrors(kind: ErrorKinds.ErrorKind): this.type = { - errorBuffer.retain(_.kind != kind) + def clearErrors(removeF: PartialFunction[AbsTypeError, Boolean]): this.type = { + errorBuffer.retain(!PartialFunction.cond(_)(removeF)) this } - def retainErrors(kind: ErrorKinds.ErrorKind): this.type = { - errorBuffer.retain(_.kind == kind) + def retainErrors(leaveF: PartialFunction[AbsTypeError, Boolean]): this.type = { + errorBuffer.retain(PartialFunction.cond(_)(leaveF)) this } def clearAllWarnings(): this.type = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 59ed64ac03..875aa5a9d3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -81,7 +81,10 @@ trait Implicits { val implicitSearchContext = context.makeImplicit(reportAmbiguous) val result = new ImplicitSearch(tree, pt, isView, implicitSearchContext, pos).bestImplicit if (result.isFailure && saveAmbiguousDivergent && implicitSearchContext.hasErrors) { - context.updateBuffer(implicitSearchContext.reportBuffer.errors.filter(err => err.kind == ErrorKinds.Ambiguous || err.kind == ErrorKinds.Divergent)) + context.updateBuffer(implicitSearchContext.reportBuffer.errors.collect { + case dte: DivergentImplicitTypeError => dte + case ate: AmbiguousImplicitTypeError => ate + }) debuglog("update buffer: " + implicitSearchContext.reportBuffer.errors) } printInference("[infer implicit] inferred " + result) @@ -590,7 +593,7 @@ trait Implicits { case Some(err) => log("implicit adapt failed: " + err.errMsg) return fail(err.errMsg) - case None => + case None => } if (Statistics.canEnable) Statistics.incCounter(typedImplicits) @@ -639,7 +642,7 @@ trait Implicits { context.firstError match { case Some(err) => return fail("type parameters weren't correctly instantiated outside of the implicit tree: " + err.errMsg) - case None => + case None => } // filter out failures from type inference, don't want to remove them from undetParams! @@ -678,7 +681,7 @@ trait Implicits { context.firstError match { case Some(err) => fail("typing TypeApply reported errors for the implicit tree: " + err.errMsg) - case None => + case None => val result = new SearchResult(itree2, subst) if (Statistics.canEnable) Statistics.incCounter(foundImplicits) printInference("[success] found %s for pt %s".format(result, ptInstantiated)) @@ -839,7 +842,9 @@ trait Implicits { case sr if sr.isFailure => // We don't want errors that occur during checking implicit info // to influence the check of further infos. - context.reportBuffer.retainErrors(ErrorKinds.Divergent) + context.reportBuffer.retainErrors { + case err: DivergentImplicitTypeError => true + } rankImplicits(is, acc) case newBest => best = newBest diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 637abe4be2..fcdc4c1a9c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -150,15 +150,19 @@ trait Typers extends Adaptations with Tags { } else { mkArg = gen.mkNamedArg // don't pass the default argument (if any) here, but start emitting named arguments for the following args if (!param.hasDefault && !paramFailed) { - context.reportBuffer.errors.find(_.kind == ErrorKinds.Divergent) match { - case Some(divergent: DivergentImplicitTypeError) => + context.reportBuffer.errors.collectFirst { + case dte: DivergentImplicitTypeError => dte + } match { + case Some(divergent) => // DivergentImplicit error has higher priority than "no implicit found" // no need to issue the problem again if we are still in silent mode if (context.reportErrors) { context.issue(divergent.withPt(paramTp)) - context.reportBuffer.clearErrors(ErrorKinds.Divergent) + context.reportBuffer.clearErrors { + case dte: DivergentImplicitTypeError => true + } } - case None => + case _ => NoImplicitFoundError(fun, param) } paramFailed = true @@ -4688,12 +4692,11 @@ trait Typers extends Adaptations with Tags { case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name) } val (result, accessibleError) = silent(_.makeAccessible(tree1, sym, qual.tpe, qual)) match { + case SilentTypeError(err: AccessTypeError) => + (tree1, Some(err)) case SilentTypeError(err) => - if (err.kind != ErrorKinds.Access) { - context issue err - return setError(tree) - } - else (tree1, Some(err)) + context issue err + return setError(tree) case SilentResultValue(treeAndPre) => (stabilize(treeAndPre._1, treeAndPre._2, mode, pt), None) } |