@@ -247,11 +247,9 @@ object Implicits:
247
247
candidates += Candidate (ref, ckind, level)
248
248
249
249
if considerExtension then
250
- val tryExtension = tryCandidate(extensionOnly = true )
251
- companionRefs.foreach(tryExtension)
250
+ companionRefs.foreach(tryCandidate(extensionOnly = true ))
252
251
if refs.nonEmpty then
253
- val tryGiven = tryCandidate(extensionOnly = false )
254
- refs.foreach(tryGiven)
252
+ refs.foreach(tryCandidate(extensionOnly = false ))
255
253
candidates.toList
256
254
}
257
255
}
@@ -488,9 +486,10 @@ object Implicits:
488
486
489
487
class DivergingImplicit (ref : TermRef ,
490
488
val expectedType : Type ,
491
- val argument : Tree ) extends SearchFailureType {
489
+ val argument : Tree ,
490
+ addendum : => String = " " ) extends SearchFailureType {
492
491
def explanation (using Context ): String =
493
- em " ${err.refStr(ref)} produces a diverging implicit search when trying to $qualify"
492
+ em " ${err.refStr(ref)} produces a diverging implicit search when trying to $qualify$addendum "
494
493
}
495
494
496
495
class FailedExtension (extApp : Tree , val expectedType : Type ) extends SearchFailureType :
@@ -1101,7 +1100,13 @@ trait Implicits:
1101
1100
*/
1102
1101
def tryImplicit (cand : Candidate , contextual : Boolean ): SearchResult =
1103
1102
if checkDivergence(cand) then
1104
- SearchFailure (new DivergingImplicit (cand.ref, wideProto, argument))
1103
+ val addendum = ctx.searchHistory.disqualifiedType match
1104
+ case NoType => " "
1105
+ case disTp =>
1106
+ em """ .
1107
+ |Note that open search type $disTp cannot be re-used as a by-name implicit parameter
1108
+ |since it is not fully defined """
1109
+ SearchFailure (new DivergingImplicit (cand.ref, wideProto, argument, addendum))
1105
1110
else {
1106
1111
val history = ctx.searchHistory.nest(cand, pt)
1107
1112
val result =
@@ -1371,8 +1376,12 @@ trait Implicits:
1371
1376
history match
1372
1377
case prev @ OpenSearch (cand1, tp, outer) =>
1373
1378
if cand1.ref eq cand.ref then
1379
+ def checkFullyDefined =
1380
+ val result = isFullyDefined(tp, ForceDegree .failBottom)
1381
+ if ! result then prev.disqualified = true
1382
+ result
1374
1383
lazy val wildTp = wildApprox(tp.widenExpr)
1375
- if belowByname && (wildTp <:< wildPt) then
1384
+ if belowByname && (wildTp <:< wildPt) && checkFullyDefined then
1376
1385
false
1377
1386
else if prev.typeSize > ptSize || prev.coveringSet != ptCoveringSet then
1378
1387
loop(outer, tp.isByName || belowByname)
@@ -1464,6 +1473,15 @@ abstract class SearchHistory:
1464
1473
def defineBynameImplicit (tpe : Type , result : SearchSuccess )(using Context ): SearchResult =
1465
1474
root.defineBynameImplicit(tpe, result)
1466
1475
1476
+ /** There is a qualifying call-by-name parameter in the history
1477
+ * that cannot be used since is it not fully defined. Used for error reporting.
1478
+ */
1479
+ def disqualifiedType : Type =
1480
+ def loop (h : SearchHistory ): Type = h match
1481
+ case h : OpenSearch => if h.disqualified then h.pt else loop(h.outer)
1482
+ case _ => NoType
1483
+ loop(this )
1484
+
1467
1485
// This is NOOP unless at the root of this search history.
1468
1486
def emitDictionary (span : Span , result : SearchResult )(using Context ): SearchResult = result
1469
1487
@@ -1483,6 +1501,10 @@ case class OpenSearch(cand: Candidate, pt: Type, outer: SearchHistory)(using Con
1483
1501
// An example is in neg/9504.scala
1484
1502
lazy val typeSize = pt.typeSize
1485
1503
lazy val coveringSet = pt.coveringSet
1504
+
1505
+ // Set if there would be a qualifying call-by-name parameter
1506
+ // that cannot be used since is it not fully defined
1507
+ var disqualified : Boolean = false
1486
1508
end OpenSearch
1487
1509
1488
1510
/**
0 commit comments