@@ -885,7 +885,7 @@ trait Implicits {
885885 * - find the most likely one
886886 * - if it matches, forget about all others it improves upon
887887 */
888- @ tailrec private def rankImplicits (pending : Infos , acc : Infos ) : Infos = pending match {
888+ @ tailrec private def rankImplicits (pending : Infos , acc : List [( SearchResult , ImplicitInfo )]) : List [( SearchResult , ImplicitInfo )] = pending match {
889889 case Nil => acc
890890 case firstPending :: otherPending =>
891891 def firstPendingImproves (alt : ImplicitInfo ) =
@@ -912,7 +912,7 @@ trait Implicits {
912912 val pendingImprovingBest = undoLog undo {
913913 otherPending filterNot firstPendingImproves
914914 }
915- rankImplicits(pendingImprovingBest, firstPending :: acc)
915+ rankImplicits(pendingImprovingBest, (newBest, firstPending) :: acc)
916916 }
917917 }
918918
@@ -928,14 +928,14 @@ trait Implicits {
928928 // So if there is any element not improved upon by the first it is an error.
929929 rankImplicits(eligible, Nil ) match {
930930 case Nil => ()
931- case chosen :: rest =>
932- rest find ( alt => ! improves(chosen , alt)) match {
933- case Some (competing ) =>
934- AmbiguousImplicitError (chosen, competing , " both" , " and" , " " )(isView, pt, tree)(context)
931+ case (chosenResult, chosenInfo) :: rest =>
932+ rest find { case (_, alt) => ! improves(chosenInfo , alt) } match {
933+ case Some ((competingResult, competingInfo) ) =>
934+ AmbiguousImplicitError (chosenInfo, chosenResult.tree, competingInfo, competingResult.tree , " both" , " and" , " " )(isView, pt, tree)(context)
935935 return AmbiguousSearchFailure // Stop the search once ambiguity is encountered, see t4457_2.scala
936936 case _ =>
937- if (isView) chosen .useCountView += 1
938- else chosen .useCountArg += 1
937+ if (isView) chosenInfo .useCountView += 1
938+ else chosenInfo .useCountArg += 1
939939 }
940940 }
941941
@@ -1448,9 +1448,9 @@ trait Implicits {
14481448 }
14491449 }
14501450
1451- object ImplicitNotFoundMsg {
1452- def unapply (sym : Symbol ): Option [(Message )] = sym.implicitNotFoundMsg match {
1453- case Some (m) => Some (new Message (sym, m))
1451+ class ImplicitAnnotationMsg ( f : Symbol => Option [ String ], clazz : Symbol , annotationName : String ) {
1452+ def unapply (sym : Symbol ): Option [(Message )] = f( sym) match {
1453+ case Some (m) => Some (new Message (sym, m, annotationName ))
14541454 case None if sym.isAliasType =>
14551455 // perform exactly one step of dealiasing
14561456 // this is necessary because ClassManifests are now aliased to ClassTags
@@ -1462,39 +1462,43 @@ trait Implicits {
14621462 // check the message's syntax: should be a string literal that may contain occurrences of the string "${X}",
14631463 // where `X` refers to a type parameter of `sym`
14641464 def check (sym : Symbol ): Option [String ] =
1465- sym.getAnnotation(ImplicitNotFoundClass ).flatMap(_.stringArg(0 ) match {
1466- case Some (m) => new Message (sym, m).validate
1467- case None => Some (" Missing argument `msg` on implicitNotFound annotation." )
1465+ sym.getAnnotation(clazz ).flatMap(_.stringArg(0 ) match {
1466+ case Some (m) => new Message (sym, m, annotationName ).validate
1467+ case None => Some (s " Missing argument `msg` on $annotationName annotation. " )
14681468 })
1469+ }
1470+
1471+ object ImplicitNotFoundMsg extends ImplicitAnnotationMsg (_.implicitNotFoundMsg, ImplicitNotFoundClass , " implicitNotFound" )
1472+
1473+ object ImplicitAmbiguousMsg extends ImplicitAnnotationMsg (_.implicitAmbiguousMsg, ImplicitAmbiguousClass , " implicitAmbiguous" )
14691474
1475+ class Message (sym : Symbol , msg : String , annotationName : String ) {
14701476 // http://dcsobral.blogspot.com/2010/01/string-interpolation-in-scala-with.html
14711477 private val Intersobralator = """ \$\{\s*([^}\s]+)\s*\}""" .r
14721478
1473- class Message (sym : Symbol , msg : String ) {
1474- private def interpolate (text : String , vars : Map [String , String ]) =
1475- Intersobralator .replaceAllIn(text, (_ : Regex .Match ) match {
1476- case Regex .Groups (v) => Regex quoteReplacement vars.getOrElse(v, " " )
1479+ private def interpolate (text : String , vars : Map [String , String ]) =
1480+ Intersobralator .replaceAllIn(text, (_ : Regex .Match ) match {
1481+ case Regex .Groups (v) => Regex quoteReplacement vars.getOrElse(v, " " )
14771482 // #3915: need to quote replacement string since it may include $'s (such as the interpreter's $iw)
1478- })
1483+ })
14791484
1480- private lazy val typeParamNames : List [String ] = sym.typeParams.map(_.decodedName)
1485+ private lazy val typeParamNames : List [String ] = sym.typeParams.map(_.decodedName)
14811486
1482- def format (paramName : Name , paramTp : Type ): String = format(paramTp.typeArgs map (_.toString))
1483- def format (typeArgs : List [String ]): String =
1484- interpolate(msg, Map ((typeParamNames zip typeArgs): _* )) // TODO: give access to the name and type of the implicit argument, etc?
1487+ def format (paramName : Name , paramTp : Type ): String = format(paramTp.typeArgs map (_.toString))
1488+ def format (typeArgs : List [String ]): String =
1489+ interpolate(msg, Map ((typeParamNames zip typeArgs): _* )) // TODO: give access to the name and type of the implicit argument, etc?
14851490
1486- def validate : Option [String ] = {
1487- val refs = Intersobralator .findAllMatchIn(msg).map(_ group 1 ).toSet
1488- val decls = typeParamNames.toSet
1491+ def validate : Option [String ] = {
1492+ val refs = Intersobralator .findAllMatchIn(msg).map(_ group 1 ).toSet
1493+ val decls = typeParamNames.toSet
14891494
1490- (refs &~ decls) match {
1491- case s if s.isEmpty => None
1492- case unboundNames =>
1493- val singular = unboundNames.size == 1
1494- val ess = if (singular) " " else " s"
1495- val bee = if (singular) " is" else " are"
1496- Some (s " The type parameter $ess ${unboundNames mkString " , " } referenced in the message of the @implicitNotFound annotation $bee not defined by $sym. " )
1497- }
1495+ (refs &~ decls) match {
1496+ case s if s.isEmpty => None
1497+ case unboundNames =>
1498+ val singular = unboundNames.size == 1
1499+ val ess = if (singular) " " else " s"
1500+ val bee = if (singular) " is" else " are"
1501+ Some (s " The type parameter $ess ${unboundNames mkString " , " } referenced in the message of the @ $annotationName annotation $bee not defined by $sym. " )
14981502 }
14991503 }
15001504 }
0 commit comments