@@ -567,19 +567,7 @@ object Types {
567
567
if (rinfo.isAlias) rinfo
568
568
else if (pdenot.info.isAlias) pdenot.info
569
569
else if (ctx.pendingMemberSearches.contains(name)) pdenot.info safe_& rinfo
570
- else
571
- try pdenot.info & rinfo
572
- catch {
573
- case ex : CyclicReference =>
574
- // ??? can this still happen? ???
575
- // happens for tests/pos/sets.scala. findMember is called from baseTypeRef.
576
- // The & causes a subtype check which calls baseTypeRef again with the same
577
- // superclass. In the observed case, the superclass was Any, and
578
- // the special shortcut for Any in derivesFrom was as yet absent. To reproduce,
579
- // remove the special treatment of Any in derivesFrom and compile
580
- // sets.scala.
581
- pdenot.info safe_& rinfo
582
- }
570
+ else pdenot.info recoverable_& rinfo
583
571
pdenot.asSingleDenotation.derivedSingleDenotation(pdenot.symbol, jointInfo)
584
572
} else {
585
573
pdenot & (
@@ -859,17 +847,29 @@ object Types {
859
847
860
848
/** Safer version of `&`.
861
849
*
862
- * This version does not simplify the upper bound of the intersection of
850
+ * This version does not simplify the bounds of the intersection of
863
851
* two TypeBounds. The simplification done by `&` requires subtyping checks
864
852
* which may end up calling `&` again, in most cases this should be safe
865
853
* but because of F-bounded types, this can result in an infinite loop
866
854
* (which will be masked unless `-Yno-deep-subtypes` is enabled).
855
+ * pos/i536 demonstrates that the infinite loop can also invole lower bounds.wait
867
856
*/
868
857
def safe_& (that : Type )(implicit ctx : Context ): Type = (this , that) match {
869
- case (TypeBounds (lo1, hi1), TypeBounds (lo2, hi2)) => TypeBounds (lo1 | lo2, AndType (hi1, hi2))
858
+ case (TypeBounds (lo1, hi1), TypeBounds (lo2, hi2)) => TypeBounds (OrType ( lo1, lo2) , AndType (hi1, hi2))
870
859
case _ => this & that
871
860
}
872
861
862
+ /** `this & that`, but handle CyclicReferences by falling back to `safe_&`.
863
+ */
864
+ def recoverable_& (that : Type )(implicit ctx : Context ): Type =
865
+ try this & that
866
+ catch {
867
+ case ex : CyclicReference => this safe_& that
868
+ // A test case where this happens is tests/pos/i536.scala.
869
+ // The & causes a subtype check which calls baseTypeRef again with the same
870
+ // superclass.
871
+ }
872
+
873
873
def | (that : Type )(implicit ctx : Context ): Type = track(" |" ) {
874
874
ctx.typeComparer.lub(this , that)
875
875
}
0 commit comments