diff options
author | Hubert Plociniczak <hubert.plociniczak@gmail.com> | 2012-02-17 16:41:33 +0100 |
---|---|---|
committer | Hubert Plociniczak <hubert.plociniczak@gmail.com> | 2012-02-17 16:41:33 +0100 |
commit | b10b5821f40ccfad5e97df754ec35be0d256e41e (patch) | |
tree | 88b39582e6a05a55e70cb748efebfc1d24020ba0 /src/compiler | |
parent | 91148376049a152edec12348ff9b7e9e93e6ebe1 (diff) | |
download | scala-b10b5821f40ccfad5e97df754ec35be0d256e41e.tar.gz scala-b10b5821f40ccfad5e97df754ec35be0d256e41e.tar.bz2 scala-b10b5821f40ccfad5e97df754ec35be0d256e41e.zip |
Closes #5452.
Instead of trying to track the fallback attempts we rely on the
context state to inform us which fallback is the last one.
setError cannot always be called in NoBestMethodAlternativeError
because inferMethodAlternative relies on side-effects.
Review by @paulp.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala | 11 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Infer.scala | 16 |
2 files changed, 19 insertions, 8 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 6ee09d064f..6b67ee886e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -713,10 +713,17 @@ trait ContextErrors { "constructor cannot be instantiated to expected type" + foundReqMsg(restpe, pt)) setError(tree) } - - def NoBestMethodAlternativeError(tree: Tree, argtpes: List[Type], pt: Type) = + + def NoBestMethodAlternativeError(tree: Tree, argtpes: List[Type], pt: Type) = { issueNormalTypeError(tree, applyErrorMsg(tree, " cannot be applied to ", argtpes, pt)) + // since inferMethodAlternative modifies the state of the tree + // we have to set the type of tree to ErrorType only in the very last + // fallback action that is done in the inference (tracking it manually is error prone). + // This avoids entering infinite loop in doTypeApply. + // TODO: maybe we should do the same thing with inferExprAlternative. + if (implicitly[Context].reportErrors) setError(tree) + } def AmbiguousMethodAlternativeError(tree: Tree, pre: Type, best: Symbol, firstCompeting: Symbol, argtpes: List[Type], pt: Type) = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index b97fbebec2..e1aa8b46eb 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -1388,7 +1388,7 @@ trait Infer { NoBestExprAlternativeError(tree, pt) } else if (!competing.isEmpty) { if (secondTry) NoBestExprAlternativeError(tree, pt) - else { if (!pt.isErroneous) AmbiguousExprAlternativeError(tree, pre, best, competing.head, pt) } + else if (!pt.isErroneous) AmbiguousExprAlternativeError(tree, pre, best, competing.head, pt) } else { // val applicable = alts1 filter (alt => // global.typer.infer.isWeaklyCompatible(pre.memberType(alt), pt)) @@ -1398,10 +1398,14 @@ trait Infer { } } - @inline private def inSilentMode(expr: Typer => Boolean): Boolean = { - val silentContext = context.makeSilent(context.ambiguousErrors) - val res = expr(newTyper(silentContext)) - if (silentContext.hasErrors) false else res + @inline private def inSilentMode(context: Context)(expr: => Boolean): Boolean = { + val oldState = context.state + context.setBufferErrors() + val res = expr + val contextWithErrors = context.hasErrors + context.flushBuffer() + context.restoreState(oldState) + res && !contextWithErrors } // Checks against the name of the parameter and also any @deprecatedName. @@ -1472,7 +1476,7 @@ trait Infer { val applicable = resolveOverloadedMethod(argtpes, { alts filter { alt => - inSilentMode(typer0 => typer0.infer.isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt)) && + inSilentMode(context)(isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt)) && (!varArgsOnly || isVarArgsList(alt.tpe.params)) } }) |