summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorHubert Plociniczak <hubert.plociniczak@gmail.com>2013-02-19 17:16:13 +0100
committerHubert Plociniczak <hubert.plociniczak@gmail.com>2013-04-26 16:20:38 +0200
commitaccaa314f3473553d9ffaff8c37e3c5b29f0f2e3 (patch)
treeb020cbdb01a335ce41aa597c8f3cef8551b0370e /src/compiler/scala/tools/nsc/typechecker/Typers.scala
parentf33af58f3b6538398da6974275099fb18560e92d (diff)
downloadscala-accaa314f3473553d9ffaff8c37e3c5b29f0f2e3.tar.gz
scala-accaa314f3473553d9ffaff8c37e3c5b29f0f2e3.tar.bz2
scala-accaa314f3473553d9ffaff8c37e3c5b29f0f2e3.zip
SI-7291: No exception throwing for diverging implicit expansion
Since we don't throw exceptions for normal errors it was a bit odd that we don't do that for DivergingImplicit. As SI-7291 shows, the logic behind catching/throwing exception was broken for divergence. Instead of patching it, I rewrote the mechanism so that we now another SearchFailure type related to diverging expansion, similar to ambiguous implicit scenario. The logic to prevent diverging expansion from stopping the search had to be slightly adapted but works as usual. The upside is that we don't have to catch diverging implicit for example in the presentation compiler which was again showing that something was utterly broken with the exception approach.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala41
1 files changed, 23 insertions, 18 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 6e26b12226..637abe4be2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -151,11 +151,11 @@ trait Typers extends Adaptations with Tags {
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(divergentImplicit) =>
+ case Some(divergent: DivergentImplicitTypeError) =>
// 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(divergentImplicit)
+ context.issue(divergent.withPt(paramTp))
context.reportBuffer.clearErrors(ErrorKinds.Divergent)
}
case None =>
@@ -1627,22 +1627,27 @@ trait Typers extends Adaptations with Tags {
/** Makes sure that the first type tree in the list of parent types is always a class.
* If the first parent is a trait, prepend its supertype to the list until it's a class.
-*/
- private def normalizeFirstParent(parents: List[Tree]): List[Tree] = parents match {
- case first :: rest if treeInfo.isTraitRef(first) =>
- def explode(supertpt: Tree, acc: List[Tree]): List[Tree] = {
- if (treeInfo.isTraitRef(supertpt)) {
- val supertpt1 = typedType(supertpt)
- if (!supertpt1.isErrorTyped) {
- val supersupertpt = TypeTree(supertpt1.tpe.firstParent) setPos supertpt.pos.focus
- return explode(supersupertpt, supertpt1 :: acc)
- }
- }
- if (supertpt.tpe.typeSymbol == AnyClass) supertpt setType AnyRefClass.tpe
- supertpt :: acc
- }
- explode(first, Nil) ++ rest
- case _ => parents
+ */
+ private def normalizeFirstParent(parents: List[Tree]): List[Tree] = {
+ @annotation.tailrec
+ def explode0(parents: List[Tree]): List[Tree] = {
+ val supertpt :: rest = parents // parents is always non-empty here - it only grows
+ if (supertpt.tpe.typeSymbol == AnyClass) {
+ supertpt setType AnyRefTpe
+ parents
+ } else if (treeInfo isTraitRef supertpt) {
+ val supertpt1 = typedType(supertpt)
+ def supersuper = TypeTree(supertpt1.tpe.firstParent) setPos supertpt.pos.focus
+ if (supertpt1.isErrorTyped) rest
+ else explode0(supersuper :: supertpt1 :: rest)
+ } else parents
+ }
+
+ def explode(parents: List[Tree]) =
+ if (treeInfo isTraitRef parents.head) explode0(parents)
+ else parents
+
+ if (parents.isEmpty) Nil else explode(parents)
}
/** Certain parents are added in the parser before it is known whether