@@ -471,7 +471,23 @@ trait ImplicitRunInfo { self: Run =>
471
471
472
472
private val EmptyTermRefSet = new TermRefSet ()(NoContext )
473
473
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
+ *
475
491
* @param liftingCtx A context to be used when computing the class symbols of
476
492
* a type. Types may contain type variables with their instances
477
493
* recorded in the current context. To find out the instance of
@@ -483,28 +499,31 @@ trait ImplicitRunInfo { self: Run =>
483
499
val seen : mutable.Set [Type ] = mutable.Set ()
484
500
val incomplete : mutable.Set [Type ] = mutable.Set ()
485
501
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
487
515
* that has the same implicit scope as the original typeref. The motivation for applying
488
516
* this map is that it reduces the total number of types for which we need to
489
517
* compute and cache the implicit scope; all variations wrt type parameters or
490
518
* abstract types are eliminated.
491
519
*/
492
- object liftToClasses extends TypeMap {
520
+ object liftToAnchors extends TypeMap {
493
521
override implicit protected val ctx : Context = liftingCtx
494
522
override def stopAtStatic = true
495
523
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 {
499
525
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(_, _))
508
527
case tp : TypeVar =>
509
528
apply(tp.underlying)
510
529
case tp : AppliedType if ! tp.tycon.typeSymbol.isClass =>
@@ -521,7 +540,6 @@ trait ImplicitRunInfo { self: Run =>
521
540
}
522
541
}
523
542
524
- // todo: compute implicits directly, without going via companionRefs?
525
543
def collectCompanions (tp : Type ): TermRefSet = track(" computeImplicitScope" ) {
526
544
trace(i " collectCompanions( $tp) " , implicitsDetailed) {
527
545
@@ -541,46 +559,53 @@ trait ImplicitRunInfo { self: Run =>
541
559
}
542
560
543
561
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)
562
573
}
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)
569
578
}
570
579
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 =>
571
596
for (part <- tp.namedPartsWith(_.isType)) comps ++= iscopeRefs(part)
572
597
}
573
598
comps
574
599
}
575
600
}
576
601
577
602
/** 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
579
604
*/
580
605
def iscope (tp : Type , isLifted : Boolean = false ): OfTypeImplicits = {
581
606
val canCache = Config .cacheImplicitScopes && tp.hash != NotCached && ! tp.isProvisional
582
607
def computeIScope () = {
583
- val liftedTp = if (isLifted) tp else liftToClasses (tp)
608
+ val liftedTp = if (isLifted) tp else liftToAnchors (tp)
584
609
val refs =
585
610
if (liftedTp ne tp) {
586
611
implicitsDetailed.println(i " lifted of $tp = $liftedTp" )
0 commit comments