@@ -471,7 +471,23 @@ trait ImplicitRunInfo { self: Run =>
471471
472472 private val EmptyTermRefSet = new TermRefSet ()(NoContext )
473473
474- /** The implicit scope of a type `tp`
474+ /** The implicit scope of a type `tp`, defined as follows:
475+ *
476+ * The implicit scope of a type `tp` is the smallest set S of object references (i.e. TermRefs
477+ * with Module symbol) such that
478+ *
479+ * - If `tp` is a class reference, S contains a reference to the companion object of the class,
480+ * if it exists, as well as the implicit scopes of all of `tp`'s parent class references.
481+ * - If `tp` is an opaque type alias `p.A` of type `tp'`, S contains a reference to an object `A` defined in the
482+ * same scope as the opaque type, if it exists, as well as the implicit scope of `tp'`.
483+ * - If `tp` is a reference `p.T` to a class or opaque type alias, S also contains all object references
484+ * on the prefix path `p`. Under Scala-2 mode, package objects of package references on `p` also
485+ * count towards the implicit scope.
486+ * - If `tp` is a (non-opaque) alias of `tp'`, S contains the implicit scope of `tp'`.
487+ * - If `tp` is a singleton type, S contains the implicit scope of its underlying type.
488+ * - If `tp` is some other type, its implicit scope is the union of the implicit scopes of
489+ * its parts (parts defined as in the spec).
490+ *
475491 * @param liftingCtx A context to be used when computing the class symbols of
476492 * a type. Types may contain type variables with their instances
477493 * recorded in the current context. To find out the instance of
@@ -483,28 +499,31 @@ trait ImplicitRunInfo { self: Run =>
483499 val seen : mutable.Set [Type ] = mutable.Set ()
484500 val incomplete : mutable.Set [Type ] = mutable.Set ()
485501
486- /** Replace every typeref that does not refer to a class by a conjunction of class types
502+ /** Is `sym` an anchor type for which givens may exist? Anchor types are classes,
503+ * opaque type aliases, and abstract types, but not type parameters
504+ */
505+ def isAnchor (sym : Symbol ) = sym.isClass && ! sym.is(Package ) || sym.isOpaqueAlias
506+
507+ def anchors (tp : Type ): List [Type ] = tp match {
508+ case tp : NamedType if isAnchor(tp.symbol) => tp :: Nil
509+ case tp : TypeProxy => anchors(tp.superType)
510+ case tp : AndOrType => anchors(tp.tp1) ++ anchors(tp.tp2)
511+ case _ => Nil
512+ }
513+
514+ /** Replace every typeref that does not refer to a class by a conjunction of anchor types
487515 * that has the same implicit scope as the original typeref. The motivation for applying
488516 * this map is that it reduces the total number of types for which we need to
489517 * compute and cache the implicit scope; all variations wrt type parameters or
490518 * abstract types are eliminated.
491519 */
492- object liftToClasses extends TypeMap {
520+ object liftToAnchors extends TypeMap {
493521 override implicit protected val ctx : Context = liftingCtx
494522 override def stopAtStatic = true
495523
496- private def isLiftTarget (sym : Symbol ) = sym.isClass || sym.isOpaqueAlias
497-
498- def apply (tp : Type ) = tp match {
524+ def apply (tp : Type ) = tp.widenDealias match {
499525 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- }
526+ ((defn.AnyType : Type ) /: anchors(tp))(AndType .make(_, _))
508527 case tp : TypeVar =>
509528 apply(tp.underlying)
510529 case tp : AppliedType if ! tp.tycon.typeSymbol.isClass =>
@@ -521,7 +540,6 @@ trait ImplicitRunInfo { self: Run =>
521540 }
522541 }
523542
524- // todo: compute implicits directly, without going via companionRefs?
525543 def collectCompanions (tp : Type ): TermRefSet = track(" computeImplicitScope" ) {
526544 trace(i " collectCompanions( $tp) " , implicitsDetailed) {
527545
@@ -541,46 +559,53 @@ trait ImplicitRunInfo { self: Run =>
541559 }
542560
543561 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 ))
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+ def addCompanion (pre : Type , companion : Symbol ) =
563+ if (companion.exists && ! companion.isAbsent()) comps += TermRef (pre, companion)
564+
565+ def addPath (pre : Type ): Unit = pre.dealias match {
566+ case pre : ThisType if pre.cls.is(Module ) && pre.cls.isStaticOwner =>
567+ addPath(pre.cls.sourceModule.termRef)
568+ case pre : TermRef =>
569+ if (pre.symbol.is(Package )) {
570+ if (ctx.scala2Mode) {
571+ addCompanion(pre, pre.member(nme.PACKAGE ).symbol)
572+ addPath(pre.prefix)
562573 }
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+ }
575+ else {
576+ comps += pre
577+ addPath(pre.prefix)
569578 }
570579 case _ =>
580+ }
581+ tp.widenDealias match {
582+ case tp : TypeRef =>
583+ val sym = tp.symbol
584+ if (isAnchor(sym)) {
585+ val pre = tp.prefix
586+ addPath(pre)
587+ if (sym.isClass) addCompanion(pre, sym.companionModule)
588+ else addCompanion(pre,
589+ pre.member(sym.name.toTermName)
590+ .suchThat(companion => companion.is(Module ) && companion.owner == sym.owner)
591+ .symbol)
592+ }
593+ val superAnchors = if (sym.isClass) tp.parents else anchors(tp.superType)
594+ for (anchor <- superAnchors) comps ++= iscopeRefs(anchor)
595+ case tp =>
571596 for (part <- tp.namedPartsWith(_.isType)) comps ++= iscopeRefs(part)
572597 }
573598 comps
574599 }
575600 }
576601
577602 /** The implicit scope of type `tp`
578- * @param isLifted Type `tp` is the result of a `liftToClasses ` application
603+ * @param isLifted Type `tp` is the result of a `liftToAnchors ` application
579604 */
580605 def iscope (tp : Type , isLifted : Boolean = false ): OfTypeImplicits = {
581606 val canCache = Config .cacheImplicitScopes && tp.hash != NotCached && ! tp.isProvisional
582607 def computeIScope () = {
583- val liftedTp = if (isLifted) tp else liftToClasses (tp)
608+ val liftedTp = if (isLifted) tp else liftToAnchors (tp)
584609 val refs =
585610 if (liftedTp ne tp) {
586611 implicitsDetailed.println(i " lifted of $tp = $liftedTp" )
0 commit comments