@@ -483,28 +483,31 @@ trait ImplicitRunInfo { self: Run =>
483483 val seen : mutable.Set [Type ] = mutable.Set ()
484484 val incomplete : mutable.Set [Type ] = mutable.Set ()
485485
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
487499 * that has the same implicit scope as the original typeref. The motivation for applying
488500 * this map is that it reduces the total number of types for which we need to
489501 * compute and cache the implicit scope; all variations wrt type parameters or
490502 * abstract types are eliminated.
491503 */
492- object liftToClasses extends TypeMap {
504+ object liftToAnchors extends TypeMap {
493505 override implicit protected val ctx : Context = liftingCtx
494506 override def stopAtStatic = true
495507
496- private def isLiftTarget (sym : Symbol ) = sym.isClass || sym.isOpaqueAlias
497-
498508 def apply (tp : Type ) = tp match {
499509 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(_, _))
508511 case tp : TypeVar =>
509512 apply(tp.underlying)
510513 case tp : AppliedType if ! tp.tycon.typeSymbol.isClass =>
@@ -521,7 +524,6 @@ trait ImplicitRunInfo { self: Run =>
521524 }
522525 }
523526
524- // todo: compute implicits directly, without going via companionRefs?
525527 def collectCompanions (tp : Type ): TermRefSet = track(" computeImplicitScope" ) {
526528 trace(i " collectCompanions( $tp) " , implicitsDetailed) {
527529
@@ -541,32 +543,41 @@ trait ImplicitRunInfo { self: Run =>
541543 }
542544
543545 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+ }
544567 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)) {
548573 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)
569578 }
579+ val superAnchors = if (sym.isClass) tp.parents else anchors(tp.superType)
580+ for (anchor <- superAnchors) comps ++= iscopeRefs(anchor)
570581 case _ =>
571582 for (part <- tp.namedPartsWith(_.isType)) comps ++= iscopeRefs(part)
572583 }
@@ -575,12 +586,12 @@ trait ImplicitRunInfo { self: Run =>
575586 }
576587
577588 /** 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
579590 */
580591 def iscope (tp : Type , isLifted : Boolean = false ): OfTypeImplicits = {
581592 val canCache = Config .cacheImplicitScopes && tp.hash != NotCached && ! tp.isProvisional
582593 def computeIScope () = {
583- val liftedTp = if (isLifted) tp else liftToClasses (tp)
594+ val liftedTp = if (isLifted) tp else liftToAnchors (tp)
584595 val refs =
585596 if (liftedTp ne tp) {
586597 implicitsDetailed.println(i " lifted of $tp = $liftedTp" )
0 commit comments