@@ -1062,6 +1062,40 @@ object Types {
1062
1062
tp
1063
1063
}
1064
1064
1065
+ /** Widen all top-level singletons reachable by dealising
1066
+ * and going to the operands of & and |.
1067
+ * Overridden and cached in OrType.
1068
+ */
1069
+ def widenSingletons (implicit ctx : Context ): Type = dealias match {
1070
+ case tp : SingletonType =>
1071
+ tp.widen
1072
+ case tp : OrType =>
1073
+ val tp1w = tp.widenSingletons
1074
+ if (tp1w eq tp) this else tp1w
1075
+ case tp : AndType =>
1076
+ val tp1w = tp.tp1.widenSingletons
1077
+ val tp2w = tp.tp2.widenSingletons
1078
+ if ((tp.tp1 eq tp1w) && (tp.tp2 eq tp2w)) this else tp1w & tp2w
1079
+ case _ =>
1080
+ this
1081
+ }
1082
+
1083
+ /** If this type is an alias of a disjunction of stable singleton types,
1084
+ * these types as a set, otherwise the empty set.
1085
+ * Overridden and cached in OrType.
1086
+ */
1087
+ def atoms (implicit ctx : Context ): Set [Type ] = dealias match {
1088
+ case tp : SingletonType if tp.isStable =>
1089
+ def normalize (tp : SingletonType ): SingletonType = tp.underlying match {
1090
+ case tp1 : SingletonType => normalize(tp1)
1091
+ case _ => tp
1092
+ }
1093
+ Set .empty + normalize(tp)
1094
+ case tp : OrType => tp.atoms
1095
+ case tp : AndType => tp.tp1.atoms & tp.tp2.atoms
1096
+ case _ => Set .empty
1097
+ }
1098
+
1065
1099
private def dealias1 (keep : AnnotatedType => Context => Boolean )(implicit ctx : Context ): Type = this match {
1066
1100
case tp : TypeRef =>
1067
1101
if (tp.symbol.isClass) tp
@@ -2777,6 +2811,31 @@ object Types {
2777
2811
myJoin
2778
2812
}
2779
2813
2814
+ private [this ] var atomsRunId : RunId = NoRunId
2815
+ private [this ] var myAtoms : Set [Type ] = _
2816
+ private [this ] var myWidened : Type = _
2817
+
2818
+ private def ensureAtomsComputed ()(implicit ctx : Context ): Unit =
2819
+ if (atomsRunId != ctx.runId) {
2820
+ val atoms1 = tp1.atoms
2821
+ val atoms2 = tp2.atoms
2822
+ myAtoms = if (atoms1.nonEmpty && atoms2.nonEmpty) atoms1 | atoms2 else Set .empty
2823
+ val tp1w = tp1.widenSingletons
2824
+ val tp2w = tp2.widenSingletons
2825
+ myWidened = if ((tp1 eq tp1w) && (tp2 eq tp2w)) this else tp1w | tp2w
2826
+ atomsRunId = ctx.runId
2827
+ }
2828
+
2829
+ override def atoms (implicit ctx : Context ): Set [Type ] = {
2830
+ ensureAtomsComputed()
2831
+ myAtoms
2832
+ }
2833
+
2834
+ override def widenSingletons (implicit ctx : Context ): Type = {
2835
+ ensureAtomsComputed()
2836
+ myWidened
2837
+ }
2838
+
2780
2839
def derivedOrType (tp1 : Type , tp2 : Type )(implicit ctx : Context ): Type =
2781
2840
if ((tp1 eq this .tp1) && (tp2 eq this .tp2)) this
2782
2841
else OrType .make(tp1, tp2)
0 commit comments