@@ -205,12 +205,6 @@ object Types {
205205 false
206206 }
207207
208- /** Like isRef, but also extends to unions and intersections */
209- def isCombinedRef (sym : Symbol )(using Context ): Boolean = stripped match
210- case AndType (tp1 : Type , tp2 : Type ) => tp1.isRef(sym) || tp2.isRef(sym)
211- case OrType (tp1 : Type , tp2 : Type ) => tp1.isRef(sym) && tp2.isRef(sym)
212- case _ => isRef(sym)
213-
214208 def isAny (using Context ): Boolean = isRef(defn.AnyClass , skipRefined = false )
215209 def isAnyRef (using Context ): Boolean = isRef(defn.ObjectClass , skipRefined = false )
216210 def isAnyKind (using Context ): Boolean = isRef(defn.AnyKindClass , skipRefined = false )
@@ -230,7 +224,9 @@ object Types {
230224 case _ => false
231225 }
232226
233- /** Is this type an instance of a non-bottom subclass of the given class `cls`? */
227+ /** True if this type is an instance of the given `cls` or an instance of
228+ * a non-bottom subclass of `cls`.
229+ */
234230 final def derivesFrom (cls : Symbol )(using Context ): Boolean = {
235231 def loop (tp : Type ): Boolean = tp match {
236232 case tp : TypeRef =>
@@ -245,11 +241,15 @@ object Types {
245241 case tp : AndType =>
246242 loop(tp.tp1) || loop(tp.tp2)
247243 case tp : OrType =>
248- // If the type is `T | Null` or `T | Nothing`, and `T` derivesFrom the class,
249- // then the OrType derivesFrom the class. Otherwise, we need to check both sides
250- // derivesFrom the class.
251- loop(tp.tp1) && (loop(tp.tp2) || defn.isBottomType(tp.tp2))
252- || defn.isBottomType(tp.tp1) && loop(tp.tp2)
244+ // If the type is `T | Null` or `T | Nothing`, the class is != Nothing,
245+ // and `T` derivesFrom the class, then the OrType derivesFrom the class.
246+ // Otherwise, we need to check both sides derivesFrom the class.
247+ if defn.isBottomType(tp.tp1) && cls != defn.NothingClass then
248+ loop(tp.tp2)
249+ else if defn.isBottomType(tp.tp2) && cls != defn.NothingClass then
250+ loop(tp.tp1)
251+ else
252+ loop(tp.tp1) && loop(tp.tp2)
253253 case tp : JavaArrayType =>
254254 cls == defn.ObjectClass
255255 case _ =>
@@ -484,6 +484,22 @@ object Types {
484484 final def classSymbols (using Context ): List [ClassSymbol ] =
485485 parentSymbols(_.isClass).asInstanceOf
486486
487+ /** Same as `this.classSymbols.contains(cls)` but more efficient */
488+ final def hasClassSymbol (cls : Symbol )(using Context ): Boolean = this match
489+ case tp : TypeRef =>
490+ val sym = tp.symbol
491+ sym == cls || ! sym.isClass && tp.superType.hasClassSymbol(cls)
492+ case tp : TypeProxy =>
493+ tp.underlying.hasClassSymbol(cls)
494+ case tp : ClassInfo =>
495+ tp.cls == cls
496+ case AndType (l, r) =>
497+ l.hasClassSymbol(cls) || r.hasClassSymbol(cls)
498+ case OrType (l, r) =>
499+ l.hasClassSymbol(cls) && r.hasClassSymbol(cls)
500+ case _ =>
501+ false
502+
487503 /** The term symbol associated with the type */
488504 @ tailrec final def termSymbol (using Context ): Symbol = this match {
489505 case tp : TermRef => tp.symbol
0 commit comments