@@ -483,28 +483,31 @@ 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
*/
492
- object liftToClasses extends TypeMap {
504
+ object liftToAnchors extends TypeMap {
493
505
override implicit protected val ctx : Context = liftingCtx
494
506
override def stopAtStatic = true
495
507
496
- private def isLiftTarget (sym : Symbol ) = sym.isClass || sym.isOpaqueAlias
497
-
498
508
def apply (tp : Type ) = tp match {
499
509
case tp : TypeRef =>
500
- if (isLiftTarget(tp.symbol)) tp
501
- else {
502
- val pre = tp.prefix
503
- def joinClass (tp : Type , cls : Symbol ) =
504
- AndType .make(tp, cls.typeRef.asSeenFrom(pre, cls.owner))
505
- val lead = if (pre eq NoPrefix ) defn.AnyType else apply(pre)
506
- (lead /: tp.parentSymbols(isLiftTarget))(joinClass)
507
- }
510
+ ((defn.AnyType : Type ) /: anchors(tp))(AndType .make(_, _))
508
511
case tp : TypeVar =>
509
512
apply(tp.underlying)
510
513
case tp : AppliedType if ! tp.tycon.typeSymbol.isClass =>
@@ -521,7 +524,6 @@ trait ImplicitRunInfo { self: Run =>
521
524
}
522
525
}
523
526
524
- // todo: compute implicits directly, without going via companionRefs?
525
527
def collectCompanions (tp : Type ): TermRefSet = track(" computeImplicitScope" ) {
526
528
trace(i " collectCompanions( $tp) " , implicitsDetailed) {
527
529
@@ -541,32 +543,41 @@ trait ImplicitRunInfo { self: Run =>
541
543
}
542
544
543
545
val comps = new TermRefSet
546
+ def addCompanion (pre : Type , companion : Symbol ) =
547
+ if (companion.exists && ! companion.isAbsent) comps += TermRef (pre, companion)
548
+ def addCompanionNamed (pre : Type , name : TermName ) =
549
+ addCompanion(pre, pre.member(name).suchThat(_.is(Module )).symbol)
550
+
551
+ def addPath (pre : Type ): Unit = pre.dealias match {
552
+ case pre : ThisType if pre.cls.is(Module ) && pre.cls.isStaticOwner =>
553
+ addPath(pre.cls.sourceModule.termRef)
554
+ case pre : TermRef =>
555
+ if (pre.symbol.is(Package )) {
556
+ if (ctx.scala2Mode) {
557
+ addCompanionNamed(pre, nme.PACKAGE )
558
+ addPath(pre.prefix)
559
+ }
560
+ }
561
+ else {
562
+ comps += pre
563
+ addPath(pre.prefix)
564
+ }
565
+ case _ =>
566
+ }
544
567
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
568
+ case tp : TermRef =>
569
+ addPath(tp.prefix)
570
+ case tp : TypeRef =>
571
+ val sym = tp.symbol
572
+ if (isAnchor(sym)) {
548
573
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 ))
555
- }
556
- else if (compSym.exists)
557
- comps += companion.asSeenFrom(pre, compSym.owner).asInstanceOf [TermRef ]
558
- }
559
- def addCompanionOf (sym : Symbol ) = {
560
- val companion = sym.companionModule
561
- if (companion.exists) addRef(companion.termRef)
562
- }
563
- def addClassScope (cls : ClassSymbol ): Unit = {
564
- addCompanionOf(cls)
565
- for (parent <- cls.classParents; ref <- iscopeRefs(tp.baseType(parent.classSymbol)))
566
- addRef(ref)
567
- }
568
- tp.classSymbols(liftingCtx).foreach(addClassScope)
574
+ addPath(pre)
575
+ if (sym.is(Module )) addCompanion(pre, sym.sourceModule)
576
+ else if (sym.isClass) addCompanion(pre, sym.companionModule)
577
+ else addCompanionNamed(pre, sym.name.stripModuleClassSuffix.toTermName)
569
578
}
579
+ val superAnchors = if (sym.isClass) tp.parents else anchors(tp.superType)
580
+ for (anchor <- superAnchors) comps ++= iscopeRefs(anchor)
570
581
case _ =>
571
582
for (part <- tp.namedPartsWith(_.isType)) comps ++= iscopeRefs(part)
572
583
}
@@ -575,12 +586,12 @@ trait ImplicitRunInfo { self: Run =>
575
586
}
576
587
577
588
/** The implicit scope of type `tp`
578
- * @param isLifted Type `tp` is the result of a `liftToClasses ` application
589
+ * @param isLifted Type `tp` is the result of a `liftToAnchors ` application
579
590
*/
580
591
def iscope (tp : Type , isLifted : Boolean = false ): OfTypeImplicits = {
581
592
val canCache = Config .cacheImplicitScopes && tp.hash != NotCached && ! tp.isProvisional
582
593
def computeIScope () = {
583
- val liftedTp = if (isLifted) tp else liftToClasses (tp)
594
+ val liftedTp = if (isLifted) tp else liftToAnchors (tp)
584
595
val refs =
585
596
if (liftedTp ne tp) {
586
597
implicitsDetailed.println(i " lifted of $tp = $liftedTp" )
0 commit comments