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