@@ -28,7 +28,7 @@ import Trees._
28
28
import transform .SymUtils ._
29
29
import transform .TypeUtils ._
30
30
import Hashable ._
31
- import util .{SourceFile , NoSource , EqHashMap }
31
+ import util .{SourceFile , NoSource , EqHashMap , Stats }
32
32
import config .{Config , Feature }
33
33
import Feature .migrateTo3
34
34
import config .Printers .{implicits , implicitsDetailed }
@@ -228,6 +228,7 @@ object Implicits:
228
228
if (pt.isInstanceOf [ViewProto ]) adjustSingletonArg(ref)
229
229
else ref
230
230
val refNorm = normalize(refAdjusted, pt)
231
+ Stats .record(" eligible check matches" )
231
232
if (! NoViewsAllowed .isCompatible(refNorm, ptNorm))
232
233
ckind = Candidate .None
233
234
}
@@ -314,20 +315,19 @@ object Implicits:
314
315
315
316
/** The implicit references that are eligible for type `tp`. */
316
317
def eligible (tp : Type ): List [Candidate ] =
317
- if (tp.hash == NotCached ) computeEligible(tp)
318
+ if (tp.hash == NotCached )
319
+ Stats .record(i " compute eligible not cached ${tp.getClass}" )
320
+ Stats .record(i " compute eligible not cached " )
321
+ computeEligible(tp)
318
322
else {
319
323
val eligibles = eligibleCache.lookup(tp)
320
324
if (eligibles != null ) {
321
- def elided (ci : ContextualImplicits ): Int = {
322
- val n = ci.refs.length
323
- if (ci.isOuterMost) n
324
- else n + elided(ci.outerImplicits)
325
- }
326
- if (monitored) record(s " elided eligible refs " , elided(this ))
325
+ Stats .record(" cached eligible" )
327
326
eligibles
328
327
}
329
328
else if (irefCtx eq NoContext ) Nil
330
329
else {
330
+ Stats .record(i " compute eligible cached " )
331
331
val result = computeEligible(tp)
332
332
eligibleCache(tp) = result
333
333
result
@@ -507,7 +507,7 @@ import Implicits._
507
507
trait ImplicitRunInfo :
508
508
self : Run =>
509
509
510
- private val implicitScopeCache = mutable. AnyRefMap [Type , OfTypeImplicits ]()
510
+ private val implicitScopeCache = util. EqHashMap [Type , OfTypeImplicits ]()
511
511
512
512
private def isExcluded (sym : Symbol ) =
513
513
if migrateTo3 then false else sym.is(Package ) || sym.isPackageObject
@@ -573,10 +573,10 @@ trait ImplicitRunInfo:
573
573
val companions = new TermRefSet
574
574
575
575
def iscopeRefs (t : Type ): TermRefSet =
576
- implicitScopeCache.get (t) match
577
- case Some (is) =>
576
+ implicitScopeCache.lookup (t) match
577
+ case is : OfTypeImplicits =>
578
578
is.companionRefs
579
- case None =>
579
+ case null =>
580
580
if seen.contains(t) then
581
581
incomplete += tp // all references for `t` will be accounted for in `seen` so we return `EmptySet`.
582
582
TermRefSet .empty // on the other hand, the refs of `tp` are now inaccurate, so `tp` is marked incomplete.
@@ -591,10 +591,10 @@ trait ImplicitRunInfo:
591
591
if companion.exists && ! companion.isAbsent() then
592
592
companions += TermRef (pre, companion)
593
593
594
- def addCompanions (t : Type ) = implicitScopeCache.get (t) match
595
- case Some ( iscope) =>
594
+ def addCompanions (t : Type ) = implicitScopeCache.lookup (t) match
595
+ case iscope : OfTypeImplicits =>
596
596
companions ++= iscope.companionRefs
597
- case None => t match
597
+ case null => t match
598
598
case t : TypeRef =>
599
599
val sym = t.symbol
600
600
val pre = t.prefix
@@ -634,7 +634,7 @@ trait ImplicitRunInfo:
634
634
val companions = collectCompanions(tp, parts)
635
635
val result = OfTypeImplicits (tp, companions)(runContext)
636
636
if Config .cacheImplicitScopes
637
- && tp.hash != NotCached
637
+ && tp.hash != NotCached
638
638
&& ! provisional
639
639
&& (tp eq rootTp) // first type traversed is always cached
640
640
|| ! incomplete.contains(tp) // other types are cached if they are not incomplete
@@ -681,9 +681,11 @@ trait ImplicitRunInfo:
681
681
* - If `T` is some other type, S includes the implicit scopes of all anchors of `T`.
682
682
*/
683
683
def implicitScope (tp : Type )(using Context ): OfTypeImplicits =
684
- implicitScopeCache.get(tp) match
685
- case Some (is) => is
686
- case None =>
684
+ implicitScopeCache.lookup(tp) match
685
+ case is : OfTypeImplicits =>
686
+ record(" implicitScope cache hit" )
687
+ is
688
+ case null =>
687
689
record(i " implicitScope " )
688
690
val liftToAnchors = new TypeMap :
689
691
override def stopAtStatic = true
@@ -713,9 +715,11 @@ trait ImplicitRunInfo:
713
715
record(i " implicitScope unlifted " )
714
716
computeIScope(tp)
715
717
else
716
- record(i " implicitScope lifted " )
718
+ record(" implicitScope lifted" )
717
719
val liftedIScope = implicitScopeCache.getOrElse(liftedTp, computeIScope(liftedTp))
718
- OfTypeImplicits (tp, liftedIScope.companionRefs)(runContext)
720
+ val result = OfTypeImplicits (tp, liftedIScope.companionRefs)(runContext)
721
+ implicitScopeCache(tp) = result
722
+ result
719
723
end implicitScope
720
724
721
725
protected def reset (): Unit =
@@ -1358,7 +1362,7 @@ trait Implicits:
1358
1362
def checkDivergence (cand : Candidate ): Boolean =
1359
1363
// For full details of the algorithm see the SIP:
1360
1364
// https://docs.scala-lang.org/sips/byname-implicits.html
1361
- util. Stats .record(" checkDivergence" )
1365
+ Stats .record(" checkDivergence" )
1362
1366
1363
1367
// Unless we are able to tie a recursive knot, we report divergence if there is an
1364
1368
// open implicit using the same candidate implicit definition which has a type which
0 commit comments