@@ -483,12 +483,47 @@ trait ImplicitRunInfo { self: Run =>
483
483
val seen : mutable.Set [Type ] = mutable.Set ()
484
484
val incomplete : mutable.Set [Type ] = mutable.Set ()
485
485
486
- /** Replace every typeref that does not refer to a class by a conjunction of class types
486
+ /** Is `sym` an anchor type for which givens may exist? Anchor types are classes,
487
+ * opaque type aliases, and abstract types, but not type parameters
488
+ */
489
+ def isAnchor (sym : Symbol ) = sym.isClass && ! sym.is(Package ) || sym.isOpaqueAlias
490
+
491
+ def anchors (tp : Type ): List [Type ] = tp match {
492
+ case tp : NamedType if isAnchor(tp.symbol) => tp :: Nil
493
+ case tp : TypeProxy => anchors(tp.superType)
494
+ case tp : AndOrType => anchors(tp.tp1) ++ anchors(tp.tp2)
495
+ case _ => Nil
496
+ }
497
+
498
+ /** Replace every typeref that does not refer to a class by a conjunction of anchor types
487
499
* that has the same implicit scope as the original typeref. The motivation for applying
488
500
* this map is that it reduces the total number of types for which we need to
489
501
* compute and cache the implicit scope; all variations wrt type parameters or
490
502
* abstract types are eliminated.
491
503
*/
504
+ object liftToAnchors extends TypeMap {
505
+ override implicit protected val ctx : Context = liftingCtx
506
+ override def stopAtStatic = true
507
+
508
+ def apply (tp : Type ) = tp match {
509
+ case tp : TypeRef =>
510
+ ((defn.AnyType : Type ) /: anchors(tp))(AndType .make(_, _))
511
+ case tp : TypeVar =>
512
+ apply(tp.underlying)
513
+ case tp : AppliedType if ! tp.tycon.typeSymbol.isClass =>
514
+ def applyArg (arg : Type ) = arg match {
515
+ case TypeBounds (lo, hi) => AndType .make(lo, hi)
516
+ case WildcardType (TypeBounds (lo, hi)) => AndType .make(lo, hi)
517
+ case _ => arg
518
+ }
519
+ (apply(tp.tycon) /: tp.args)((tc, arg) => AndType .make(tc, applyArg(arg)))
520
+ case tp : TypeLambda =>
521
+ apply(tp.resType)
522
+ case _ =>
523
+ mapOver(tp)
524
+ }
525
+ }
526
+
492
527
object liftToClasses extends TypeMap {
493
528
override implicit protected val ctx : Context = liftingCtx
494
529
override def stopAtStatic = true
@@ -521,7 +556,6 @@ trait ImplicitRunInfo { self: Run =>
521
556
}
522
557
}
523
558
524
- // todo: compute implicits directly, without going via companionRefs?
525
559
def collectCompanions (tp : Type ): TermRefSet = track(" computeImplicitScope" ) {
526
560
trace(i " collectCompanions( $tp) " , implicitsDetailed) {
527
561
@@ -540,47 +574,102 @@ trait ImplicitRunInfo { self: Run =>
540
574
}
541
575
}
542
576
543
- val comps = new TermRefSet
544
- tp match {
545
- case tp : NamedType =>
546
- if (! tp.symbol.is(Package ) || ctx.scala2Mode) {
547
- // Don't consider implicits in package prefixes unless under -language:Scala2
548
- val pre = tp.prefix
549
- comps ++= iscopeRefs(pre)
550
- def addRef (companion : TermRef ): Unit = {
551
- val compSym = companion.symbol
552
- if (compSym is Package ) {
553
- assert(ctx.scala2Mode)
554
- addRef(companion.select(nme.PACKAGE ))
577
+ def was = {
578
+ val comps = new TermRefSet
579
+ tp match {
580
+ case tp : NamedType =>
581
+ if (! tp.symbol.is(Package ) || ctx.scala2Mode) {
582
+ // Don't consider implicits in package prefixes unless under -language:Scala2
583
+ val pre = tp.prefix
584
+ comps ++= iscopeRefs(pre)
585
+ def addRef (companion : TermRef ): Unit = {
586
+ val compSym = companion.symbol
587
+ if (compSym is Package ) {
588
+ assert(ctx.scala2Mode)
589
+ addRef(companion.select(nme.PACKAGE ))
590
+ }
591
+ else if (compSym.exists)
592
+ comps += companion.asSeenFrom(pre, compSym.owner).asInstanceOf [TermRef ]
593
+ }
594
+ def addCompanionOf (sym : Symbol ) = {
595
+ val companion = sym.companionModule
596
+ if (companion.exists) addRef(companion.termRef)
597
+ }
598
+ def addClassScope (cls : ClassSymbol ): Unit = {
599
+ addCompanionOf(cls)
600
+ for (parent <- cls.classParents; ref <- iscopeRefs(tp.baseType(parent.classSymbol)))
601
+ addRef(ref)
602
+ }
603
+ tp.classSymbols(liftingCtx).foreach(addClassScope)
604
+ }
605
+ case _ =>
606
+ for (part <- tp.namedPartsWith(_.isType)) comps ++= iscopeRefs(part)
607
+ }
608
+ comps
609
+ }
610
+
611
+ def now = {
612
+ val comps = new TermRefSet
613
+ def addCompanion (pre : Type , companion : Symbol ) =
614
+ if (companion.exists && ! companion.isAbsent) comps += TermRef (pre, companion)
615
+ def addCompanionNamed (pre : Type , name : TermName ) =
616
+ addCompanion(pre, pre.member(name).suchThat(_.is(Module )).symbol)
617
+
618
+ def addPath (pre : Type ): Unit = pre.dealias match {
619
+ case pre : ThisType if pre.cls.is(Module ) && pre.cls.isStaticOwner =>
620
+ addPath(pre.cls.sourceModule.termRef)
621
+ case pre : TermRef =>
622
+ if (pre.symbol.is(Package )) {
623
+ if (ctx.scala2Mode) {
624
+ addCompanionNamed(pre, nme.PACKAGE )
625
+ addPath(pre.prefix)
555
626
}
556
- else if (compSym.exists)
557
- comps += companion.asSeenFrom(pre, compSym.owner).asInstanceOf [TermRef ]
558
627
}
559
- def addCompanionOf ( sym : Symbol ) = {
560
- val companion = sym.companionModule
561
- if (companion.exists) addRef(companion.termRef )
628
+ else {
629
+ comps += pre
630
+ addPath(pre.prefix )
562
631
}
563
- def addClassScope (cls : ClassSymbol ): Unit = {
564
- addCompanionOf(cls)
565
- for (parent <- cls.classParents; ref <- iscopeRefs(tp.baseType(parent.classSymbol)))
566
- addRef(ref)
632
+ case _ =>
633
+ }
634
+ tp match {
635
+ case tp : TermRef =>
636
+ addPath(tp.prefix)
637
+ case tp : TypeRef =>
638
+ val sym = tp.symbol
639
+ if (isAnchor(sym)) {
640
+ val pre = tp.prefix
641
+ addPath(pre)
642
+ if (sym.is(Module )) addCompanion(pre, sym.sourceModule)
643
+ else if (sym.isClass) addCompanion(pre, sym.companionModule)
644
+ else addCompanionNamed(pre, sym.name.stripModuleClassSuffix.toTermName)
567
645
}
568
- tp.classSymbols(liftingCtx).foreach(addClassScope)
569
- }
570
- case _ =>
571
- for (part <- tp.namedPartsWith(_.isType)) comps ++= iscopeRefs(part)
646
+ val superAnchors = if (sym.isClass) tp.parents else anchors(tp.superType)
647
+ for (anchor <- superAnchors) comps ++= iscopeRefs(anchor)
648
+ case _ =>
649
+ for (part <- tp.namedPartsWith(_.isType)) comps ++= iscopeRefs(part)
650
+ }
651
+ comps
572
652
}
573
- comps
653
+ /*
654
+ val wasSet = was.toList.toSet
655
+ val nowSet = now.toList.toSet
656
+ if (wasSet != nowSet)
657
+ println(i"""Diff for $tp
658
+ |all: ${(wasSet ++ nowSet).toList}%, %
659
+ |was: ${(wasSet -- nowSet).toList}%, %
660
+ |now: ${(nowSet -- wasSet).toList}%, %""")
661
+ */
662
+ now
574
663
}
575
664
}
576
665
577
666
/** The implicit scope of type `tp`
578
- * @param isLifted Type `tp` is the result of a `liftToClasses ` application
667
+ * @param isLifted Type `tp` is the result of a `liftToAnchors ` application
579
668
*/
580
669
def iscope (tp : Type , isLifted : Boolean = false ): OfTypeImplicits = {
581
670
val canCache = Config .cacheImplicitScopes && tp.hash != NotCached && ! tp.isProvisional
582
671
def computeIScope () = {
583
- val liftedTp = if (isLifted) tp else liftToClasses (tp)
672
+ val liftedTp = if (isLifted) tp else liftToAnchors (tp)
584
673
val refs =
585
674
if (liftedTp ne tp) {
586
675
implicitsDetailed.println(i " lifted of $tp = $liftedTp" )
0 commit comments