@@ -257,6 +257,7 @@ trait Implicits {
257
257
258
258
var useCountArg : Int = 0
259
259
var useCountView : Int = 0
260
+ def useCount (isView : Boolean ): Int = if (isView) useCountView else useCountArg
260
261
261
262
/** Does type `tp` contain an Error type as parameter or result?
262
263
*/
@@ -995,8 +996,83 @@ trait Implicits {
995
996
// most frequent one first
996
997
matches sortBy (x => if (isView) - x.useCountView else - x.useCountArg)
997
998
}
999
+
1000
+ /** Sorted list of eligible implicits.
1001
+ */
1002
+ private def eligibleNew = {
1003
+ final case class Candidate (info : ImplicitInfo , level : Int )
1004
+ var matches : java.util.ArrayList [Candidate ] = null
1005
+ var matchesNames : java.util.HashSet [Name ] = null
1006
+
1007
+ var maxCandidateLevel = 0
1008
+
1009
+ {
1010
+ var i = 0
1011
+ // Collect candidates, the level at which each was found and build a set of their names
1012
+ var iss = this .iss
1013
+ while (! iss.isEmpty) {
1014
+ var is = iss.head
1015
+ while (! is.isEmpty) {
1016
+ val info = is.head
1017
+ if (checkValid(info.sym) && survives(info, NoShadower )) {
1018
+ if (matches == null ) {
1019
+ matches = new java.util.ArrayList (16 )
1020
+ matchesNames = new java.util.HashSet (16 )
1021
+ }
1022
+ matches.add(Candidate (info, i))
1023
+ matchesNames.add(info.name)
1024
+ maxCandidateLevel = i
1025
+ }
1026
+ is = is.tail
1027
+ }
1028
+ iss = iss.tail
1029
+ i += 1
1030
+ }
1031
+ }
1032
+
1033
+ if (matches == null )
1034
+ Nil // OPT common case: no candidates
1035
+ else {
1036
+ if (isLocalToCallsite) {
1037
+ // A second pass to filter out results that are shadowed by implicits in inner scopes.
1038
+ var i = 0
1039
+ var removed = false
1040
+ var iss = this .iss
1041
+ while (! iss.isEmpty && i < maxCandidateLevel) {
1042
+ var is = iss.head
1043
+ while (! is.isEmpty) {
1044
+ val info = is.head
1045
+ if (matchesNames.contains(info.name)) {
1046
+ var j = 0
1047
+ val numMatches = matches.size()
1048
+ while (j < numMatches) {
1049
+ val matchInfo = matches.get(j)
1050
+ if (matchInfo != null && matchInfo.info.name == info.name && matchInfo.level > i) {
1051
+ // Shadowed. For now set to null, so as not to mess up the indexing our current loop.
1052
+ matches.set(j, null )
1053
+ removed = true
1054
+ }
1055
+ j += 1
1056
+ }
1057
+ }
1058
+ is = is.tail
1059
+ }
1060
+ iss = iss.tail
1061
+ i += 1
1062
+ }
1063
+ if (removed) matches.removeIf(_ == null ) // remove for real now.
1064
+ }
1065
+ // most frequent one first. Sort in-place.
1066
+ matches.sort(((x, y) => java.lang.Integer .compare(y.info.useCount(isView), x.info.useCount(isView))))
1067
+ val result = new ListBuffer [ImplicitInfo ]
1068
+ matches.forEach(x => result += x.info)
1069
+ result.toList
1070
+ }
1071
+ }
1072
+
998
1073
if (eligible.nonEmpty)
999
1074
printTyping(tree, eligible.size + s " eligible for pt= $pt at ${fullSiteString(context)}" )
1075
+ assert(eligibleNew == eligible, (eligibleNew, eligible))
1000
1076
1001
1077
/** Faster implicit search. Overall idea:
1002
1078
* - prune aggressively
0 commit comments