summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala21
-rw-r--r--test/files/neg/divergent-implicit.check6
-rw-r--r--test/files/pos/t8460.scala (renamed from test/pending/pos/t8460.scala)0
3 files changed, 22 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index a777f483e5..0538dfec7e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -839,11 +839,22 @@ trait Implicits {
if (divergentError.isEmpty) divergentError = Some(err)
}
+ def retainRemainingDivergentErrors() = {
+ val saved = divergentError.getOrElse(null)
+ context.reportBuffer.retainErrors {
+ case err: DivergentImplicitTypeError => err ne saved
+ }
+ }
+
def issueSavedDivergentError() {
divergentError foreach (err => context.issue(err))
}
def apply(search: SearchResult, i: ImplicitInfo, errors: Seq[AbsTypeError]): SearchResult = {
+ // A divergent error from a nested implicit search will be found in `errors`. Stash that
+ // aside to be re-issued if this implicit search fails.
+ errors.collectFirst { case err: DivergentImplicitTypeError => err } foreach saveDivergent
+
if (search.isDivergent && divergentError.isEmpty) {
// Divergence triggered by `i` at this level of the implicit serach. We haven't
// seen divergence so far, we won't issue this error just yet, and instead temporarily
@@ -879,16 +890,18 @@ trait Implicits {
case Nil => acc
case i :: is =>
val typedImplicitResult = typedImplicit(i, ptChecked = true, isLocalToCallsite)
+ // Pass the errors to `DivergentImplicitRecovery` so that it can note the first `DivergentImplicitTypeError`
+ // that is being propagated from a nested implicit search;
+ // this one will be re-issued if this level of the search fails.
val recoveredResult = DivergentImplicitRecovery(typedImplicitResult, i, context.errors)
recoveredResult match {
case sr if sr.isDivergent =>
Nil
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 {
- case err: DivergentImplicitTypeError => true
- }
+ // to influence the check of further infos, but we should retain divergent implicit errors
+ // (except for the one we already squirreled away)
+ DivergentImplicitRecovery.retainRemainingDivergentErrors()
rankImplicits(is, acc)
case newBest =>
best = newBest
diff --git a/test/files/neg/divergent-implicit.check b/test/files/neg/divergent-implicit.check
index 60d876409f..d4a3ddfc71 100644
--- a/test/files/neg/divergent-implicit.check
+++ b/test/files/neg/divergent-implicit.check
@@ -3,6 +3,10 @@ divergent-implicit.scala:4: error: type mismatch;
required: String
val x1: String = 1
^
+divergent-implicit.scala:5: error: diverging implicit expansion for type Int => String
+starting with method $conforms in object Predef
+ val x2: String = cast[Int, String](1)
+ ^
divergent-implicit.scala:14: error: type mismatch;
found : Test2.Foo
required: Test2.Bar
@@ -13,4 +17,4 @@ divergent-implicit.scala:15: error: type mismatch;
required: Test2.Bar
val y: Bar = new Baz
^
-three errors found
+four errors found
diff --git a/test/pending/pos/t8460.scala b/test/files/pos/t8460.scala
index 10d2ed432c..10d2ed432c 100644
--- a/test/pending/pos/t8460.scala
+++ b/test/files/pos/t8460.scala