@@ -278,7 +278,11 @@ object Implicits {
278278 /** A "no matching implicit found" failure */
279279 case object NoImplicitMatches extends SearchFailure
280280
281- case object DivergingImplicit extends SearchFailure
281+ /** A tree representing a failed search for an implicit argument */
282+ case class FailedSearch (failure : SearchFailure , errorFn : String => String ) extends WithoutTypeOrPos [Type ] {
283+ override def tag = - 1
284+ override def isEmpty = true
285+ }
282286
283287 /** A search failure that can show information about the cause */
284288 abstract class ExplainedSearchFailure extends SearchFailure {
@@ -552,7 +556,7 @@ trait Implicits { self: Typer =>
552556 * which is itself parameterized by another string,
553557 * indicating where the implicit parameter is needed
554558 */
555- def inferImplicitArg (formal : Type , error : ( String => String ) => Unit , pos : Position )(implicit ctx : Context ): Tree = {
559+ def inferImplicitArg (formal : Type , pos : Position )(implicit ctx : Context ): Tree = {
556560
557561 /** If `formal` is of the form ClassTag[T], where `T` is a class type,
558562 * synthesize a class tag for `T`.
@@ -562,16 +566,18 @@ trait Implicits { self: Typer =>
562566 case arg :: Nil =>
563567 fullyDefinedType(arg, " ClassTag argument" , pos) match {
564568 case defn.ArrayOf (elemTp) =>
565- val etag = inferImplicitArg(defn.ClassTagType .appliedTo(elemTp), error, pos)
569+ val etag = inferImplicitArg(defn.ClassTagType .appliedTo(elemTp), pos)
566570 if (etag.isEmpty) etag else etag.select(nme.wrap)
567571 case tp if hasStableErasure(tp) =>
568572 if (defn.isBottomClass(tp.typeSymbol))
569- error(where => i " attempt to take ClassTag of undetermined type for $where" )
570- ref(defn.ClassTagModule )
571- .select(nme.apply)
572- .appliedToType(tp)
573- .appliedTo(clsOf(erasure(tp)))
574- .withPos(pos)
573+ FailedSearch (NoImplicitMatches ,
574+ where => i " attempt to take ClassTag of undetermined type for $where" )
575+ else
576+ ref(defn.ClassTagModule )
577+ .select(nme.apply)
578+ .appliedToType(tp)
579+ .appliedTo(clsOf(erasure(tp)))
580+ .withPos(pos)
575581 case tp =>
576582 EmptyTree
577583 }
@@ -635,17 +641,16 @@ trait Implicits { self: Typer =>
635641 else
636642 arg
637643 case ambi : AmbiguousImplicits =>
638- error(where => s " ambiguous implicits: ${ambi.explanation} of $where" )
639- EmptyTree
644+ FailedSearch (ambi, where => s " ambiguous implicits: ${ambi.explanation} of $where" )
640645 case failure : SearchFailure =>
641- val arg =
646+ val fallbackArg =
642647 if (formalValue.isRef(defn.ClassTagClass ))
643648 synthesizedClassTag(formalValue)
644649 else if (formalValue.isRef(defn.EqClass ))
645650 synthesizedEq(formalValue)
646651 else
647652 EmptyTree
648- if (! arg .isEmpty) arg
653+ if (! fallbackArg .isEmpty) fallbackArg
649654 else {
650655 var msgFn = (where : String ) =>
651656 em " no implicit argument of type $formal found for $where" + failure.postscript
@@ -659,12 +664,21 @@ trait Implicits { self: Typer =>
659664 formalValue.typeSymbol.typeParams.map(_.name.unexpandedName.toString),
660665 formalValue.argInfos)
661666 }
662- error(msgFn)
663- EmptyTree
667+ FailedSearch (failure, msgFn)
664668 }
665669 }
666670 }
667671
672+ /** Search an implicit argument and report error if not found */
673+ def implicitArgTree (formal : Type , pos : Position , where : String = " " )(implicit ctx : Context ): Tree =
674+ inferImplicitArg(formal, pos) match {
675+ case FailedSearch (fail, errorFn) =>
676+ ctx.error(errorFn(where), pos)
677+ EmptyTree
678+ case tree =>
679+ tree
680+ }
681+
668682 private def assumedCanEqual (ltp : Type , rtp : Type )(implicit ctx : Context ) = {
669683 def eqNullable : Boolean = {
670684 val other =
@@ -694,8 +708,7 @@ trait Implicits { self: Typer =>
694708 /** Check that equality tests between types `ltp` and `rtp` make sense */
695709 def checkCanEqual (ltp : Type , rtp : Type , pos : Position )(implicit ctx : Context ): Unit =
696710 if (! ctx.isAfterTyper && ! assumedCanEqual(ltp, rtp)) {
697- val res = inferImplicitArg(
698- defn.EqType .appliedTo(ltp, rtp), msgFun => ctx.error(msgFun(" " ), pos), pos)
711+ val res = implicitArgTree(defn.EqType .appliedTo(ltp, rtp), pos)
699712 implicits.println(i " Eq witness found for $ltp / $rtp: $res: ${res.tpe}" )
700713 }
701714
@@ -771,7 +784,10 @@ trait Implicits { self: Typer =>
771784
772785 /** Search failures; overridden in ExplainedImplicitSearch */
773786 protected def nonMatchingImplicit (ref : TermRef , trail : List [MessageContainer ]): SearchFailure = NoImplicitMatches
774- protected def divergingImplicit (ref : TermRef ): SearchFailure = NoImplicitMatches
787+ protected def divergingImplicit (ref : TermRef ): SearchFailure = {
788+ implicits.println(i " diverging implicit: $ref for $pt, search history = ${ctx.searchHistory}" )
789+ new DivergingImplicit (ref, pt, argument)
790+ }
775791 protected def shadowedImplicit (ref : TermRef , shadowing : Type ): SearchFailure = NoImplicitMatches
776792 protected def failedSearch : SearchFailure = NoImplicitMatches
777793
@@ -802,11 +818,16 @@ trait Implicits { self: Typer =>
802818 }
803819 }
804820
805- if (ctx.reporter.hasErrors)
806- nonMatchingImplicit(ref, ctx.reporter.removeBufferedMessages)
821+ if (ctx.reporter.hasErrors) {
822+ val trail = ctx.reporter.removeBufferedMessages
823+ generated1 match {
824+ case failed : FailedSearch => failed.failure
825+ case _ => nonMatchingImplicit(ref, trail)
826+ }
827+ }
807828 else if (contextual && ! ctx.mode.is(Mode .ImplicitShadowing ) &&
808829 ! shadowing.tpe.isError && ! refSameAs(shadowing)) {
809- implicits.println(i " SHADOWING $ref in ${ref.termSymbol.owner } is shadowed by $shadowing in ${shadowing.symbol.owner }" )
830+ implicits.println(i " SHADOWING $ref in ${ref.termSymbol.maybeOwner } is shadowed by $shadowing in ${shadowing.symbol.maybeOwner }" )
810831 shadowedImplicit(ref, methPart(shadowing).tpe)
811832 }
812833 else
@@ -815,28 +836,38 @@ trait Implicits { self: Typer =>
815836
816837 /** Given a list of implicit references, produce a list of all implicit search successes,
817838 * where the first is supposed to be the best one.
839+ * Except if one of the results is a diverging implicit, produce a list consisting
840+ * of just that result.
818841 * @param pending The list of implicit references that remain to be investigated
819842 * @param acc An accumulator of successful matches found so far.
820843 */
821- def rankImplicits (pending : List [Candidate ], acc : List [SearchSuccess ]): List [SearchSuccess ] = pending match {
822- case cand :: pending1 =>
823- val history = ctx.searchHistory nest wildProto
824- val result =
825- if (history eq ctx.searchHistory) divergingImplicit(cand.ref)
826- else typedImplicit(cand)(nestedContext.setNewTyperState().setSearchHistory(history))
827- result match {
828- case fail : SearchFailure =>
829- rankImplicits(pending1, acc)
830- case best : SearchSuccess =>
831- if (ctx.mode.is(Mode .ImplicitExploration ) || isCoherent) best :: Nil
832- else {
833- val newPending = pending1.filter(cand1 =>
834- ctx.typerState.test(isAsGood(cand1.ref, best.ref, cand1.level, best.level)(nestedContext)))
835- rankImplicits(newPending, best :: acc)
836- }
837- }
838- case nil => acc
839- }
844+ def rankImplicits (pending : List [Candidate ],
845+ successes : List [SearchSuccess ],
846+ failures : mutable.ListBuffer [SearchFailure ]): (List [SearchSuccess ], List [SearchFailure ]) =
847+ pending match {
848+ case cand :: pending1 =>
849+ val history = ctx.searchHistory nest wildProto
850+ val result =
851+ if (history eq ctx.searchHistory) divergingImplicit(cand.ref)
852+ else typedImplicit(cand)(nestedContext.setNewTyperState().setSearchHistory(history))
853+ result match {
854+ case fail : AmbiguousImplicits =>
855+ (Nil , fail :: Nil )
856+ case fail : SearchFailure =>
857+ rankImplicits(pending1, successes,
858+ if (fail.isInstanceOf [DivergingImplicit ]) fail +=: failures
859+ else failures += fail)
860+ case best : SearchSuccess =>
861+ if (ctx.mode.is(Mode .ImplicitExploration ) || isCoherent)
862+ (best :: Nil , failures.toList)
863+ else {
864+ val newPending = pending1.filter(cand1 =>
865+ ctx.typerState.test(isAsGood(cand1.ref, best.ref, cand1.level, best.level)(nestedContext)))
866+ rankImplicits(newPending, best :: successes, failures)
867+ }
868+ }
869+ case nil => (successes, failures.toList)
870+ }
840871
841872 /** If the (result types of) the expected type, and both alternatives
842873 * are all numeric value types, return the alternative which has
@@ -858,26 +889,28 @@ trait Implicits { self: Typer =>
858889 }
859890
860891 /** Convert a (possibly empty) list of search successes into a single search result */
861- def condense (hits : List [SearchSuccess ]): SearchResult = hits match {
862- case best :: alts =>
892+ def condense (successes : List [SearchSuccess ], failures : List [ SearchFailure ] ): SearchResult = successes match {
893+ case ( best : SearchSuccess ) :: ( alts : List [ SearchSuccess ] @ unchecked) =>
863894 alts.find(alt =>
864895 ctx.typerState.test(isAsGood(alt.ref, best.ref, alt.level, best.level))) match {
865- case Some (alt) =>
866- typr.println(i " ambiguous implicits for $pt: ${best.ref} @ ${best.level}, ${alt.ref} @ ${alt.level}" )
867- /* !!! DEBUG
868- println(i"ambiguous refs: ${hits map (_.ref) map (_.show) mkString ", "}")
869- isAsGood(best.ref, alt.ref, explain = true)(ctx.fresh.withExploreTyperState)
870- */
871- numericValueTieBreak(best, alt) match {
872- case eliminated : SearchSuccess => condense(hits.filter(_ ne eliminated))
873- case _ => new AmbiguousImplicits (best.ref, alt.ref, pt, argument)
874- }
875- case None =>
876- ctx.runInfo.useCount(best.ref) += 1
877- best
878- }
896+ case Some (alt) =>
897+ implicits.println(i " ambiguous implicits for $pt: ${best.ref} @ ${best.level}, ${alt.ref} @ ${alt.level}" )
898+ /* !!! DEBUG
899+ println(i"ambiguous refs: ${hits map (_.ref) map (_.show) mkString ", "}")
900+ isAsGood(best.ref, alt.ref, explain = true)(ctx.fresh.withExploreTyperState)
901+ */
902+ numericValueTieBreak(best, alt) match {
903+ case eliminated : SearchSuccess =>
904+ condense(successes.filter(_ ne eliminated), failures)
905+ case _ =>
906+ new AmbiguousImplicits (best.ref, alt.ref, pt, argument)
907+ }
908+ case None =>
909+ ctx.runInfo.useCount(best.ref) += 1
910+ best
911+ }
879912 case Nil =>
880- failedSearch
913+ failures.headOption.getOrElse( NoImplicitMatches )
881914 }
882915
883916 def ranking (cand : Candidate ) = - ctx.runInfo.useCount(cand.ref)
@@ -894,7 +927,8 @@ trait Implicits { self: Typer =>
894927 case _ => eligible.sortBy(ranking)
895928 }
896929
897- condense(rankImplicits(sort(eligible), Nil ))
930+ val (successes, failures) = rankImplicits(sort(eligible), Nil , new mutable.ListBuffer )
931+ condense(successes, failures)
898932 }
899933
900934 /** Find a unique best implicit reference */
@@ -905,6 +939,7 @@ trait Implicits { self: Typer =>
905939 searchImplicits(eligible, contextual) match {
906940 case result : SearchSuccess => result
907941 case result : AmbiguousImplicits => result
942+ case result : DivergingImplicit => result
908943 case result : SearchFailure =>
909944 if (contextual) bestImplicit(contextual = false ) else result
910945 }
@@ -994,6 +1029,8 @@ class SearchHistory(val searchDepth: Int, val seen: Map[ClassSymbol, Int]) {
9941029 else updateMap(proto.classSymbols, seen)
9951030 }
9961031 }
1032+
1033+ override def toString = s " SearchHistory(depth = $searchDepth, seen = $seen) "
9971034}
9981035
9991036/** A set of term references where equality is =:= */
0 commit comments