@@ -209,7 +209,27 @@ object Types {
209209 def isAnyRef (using Context ): Boolean = isRef(defn.ObjectClass , skipRefined = false )
210210 def isAnyKind (using Context ): Boolean = isRef(defn.AnyKindClass , skipRefined = false )
211211
212- def isFromJavaObject (using Context ): Boolean = typeSymbol eq defn.FromJavaObjectSymbol
212+ /** Is this type exactly Nothing (no vars, aliases, refinements etc allowed)? */
213+ def isExactlyNothing (using Context ): Boolean = this match {
214+ case tp : TypeRef =>
215+ tp.name == tpnme.Nothing && (tp.symbol eq defn.NothingClass )
216+ case _ => false
217+ }
218+
219+ /** Is this type exactly Any (no vars, aliases, refinements etc allowed)? */
220+ def isExactlyAny (using Context ): Boolean = this match {
221+ case tp : TypeRef =>
222+ tp.name == tpnme.Any && (tp.symbol eq defn.AnyClass )
223+ case _ => false
224+ }
225+
226+ def isBottomType (using Context ): Boolean =
227+ if ctx.explicitNulls && ! ctx.phase.erasedTypes then hasClassSymbol(defn.NothingClass )
228+ else isBottomTypeAfterErasure
229+
230+ def isBottomTypeAfterErasure (using Context ): Boolean =
231+ val d = defn
232+ hasClassSymbol(d.NothingClass ) || hasClassSymbol(d.NullClass )
213233
214234 /** Does this type refer exactly to class symbol `sym`, instead of to a subclass of `sym`?
215235 * Implemented like `isRef`, but follows more types: all type proxies as well as and- and or-types
@@ -224,7 +244,9 @@ object Types {
224244 case _ => false
225245 }
226246
227- /** Is this type an instance of a non-bottom subclass of the given class `cls`? */
247+ /** True if this type is an instance of the given `cls` or an instance of
248+ * a non-bottom subclass of `cls`.
249+ */
228250 final def derivesFrom (cls : Symbol )(using Context ): Boolean = {
229251 def loop (tp : Type ): Boolean = tp match {
230252 case tp : TypeRef =>
@@ -239,11 +261,15 @@ object Types {
239261 case tp : AndType =>
240262 loop(tp.tp1) || loop(tp.tp2)
241263 case tp : OrType =>
242- // If the type is `T | Null` or `T | Nothing`, and `T` derivesFrom the class,
243- // then the OrType derivesFrom the class. Otherwise, we need to check both sides
244- // derivesFrom the class.
245- if defn.isBottomType(tp.tp1) then loop(tp.tp2)
246- else loop(tp.tp1) && (defn.isBottomType(tp.tp2) || loop(tp.tp2))
264+ // If the type is `T | Null` or `T | Nothing`, the class is != Nothing,
265+ // and `T` derivesFrom the class, then the OrType derivesFrom the class.
266+ // Otherwise, we need to check both sides derivesFrom the class.
267+ if tp.tp1.isBottomType && cls != defn.NothingClass then
268+ loop(tp.tp2)
269+ else if tp.tp2.isBottomType && cls != defn.NothingClass then
270+ loop(tp.tp1)
271+ else
272+ loop(tp.tp1) && loop(tp.tp2)
247273 case tp : JavaArrayType =>
248274 cls == defn.ObjectClass
249275 case _ =>
@@ -252,6 +278,8 @@ object Types {
252278 loop(this )
253279 }
254280
281+ def isFromJavaObject (using Context ): Boolean = typeSymbol eq defn.FromJavaObjectSymbol
282+
255283 /** True iff `symd` is a denotation of a class type parameter and the reference
256284 * `<this> . <symd>` is an actual argument reference, i.e. `this` is different
257285 * from the ThisType of `symd`'s owner.
@@ -265,20 +293,6 @@ object Types {
265293 }
266294 }
267295
268- /** Is this type exactly Nothing (no vars, aliases, refinements etc allowed)? */
269- def isNothing (using Context ): Boolean = this match {
270- case tp : TypeRef =>
271- tp.name == tpnme.Nothing && (tp.symbol eq defn.NothingClass )
272- case _ => false
273- }
274-
275- /** Is this type exactly Any (no vars, aliases, refinements etc allowed)? */
276- def isTopType (using Context ): Boolean = this match {
277- case tp : TypeRef =>
278- tp.name == tpnme.Any && (tp.symbol eq defn.AnyClass )
279- case _ => false
280- }
281-
282296 /** Is this type a (possibly aliased) singleton type? */
283297 def isSingleton (using Context ): Boolean = dealias.isInstanceOf [SingletonType ]
284298
@@ -478,6 +492,22 @@ object Types {
478492 final def classSymbols (using Context ): List [ClassSymbol ] =
479493 parentSymbols(_.isClass).asInstanceOf
480494
495+ /** Same as `this.classSymbols.contains(cls)` but more efficient */
496+ final def hasClassSymbol (cls : Symbol )(using Context ): Boolean = this match
497+ case tp : TypeRef =>
498+ val sym = tp.symbol
499+ sym == cls || ! sym.isClass && tp.superType.hasClassSymbol(cls)
500+ case tp : TypeProxy =>
501+ tp.underlying.hasClassSymbol(cls)
502+ case tp : ClassInfo =>
503+ tp.cls == cls
504+ case AndType (l, r) =>
505+ l.hasClassSymbol(cls) || r.hasClassSymbol(cls)
506+ case OrType (l, r) =>
507+ l.hasClassSymbol(cls) && r.hasClassSymbol(cls)
508+ case _ =>
509+ false
510+
481511 /** The term symbol associated with the type */
482512 @ tailrec final def termSymbol (using Context ): Symbol = this match {
483513 case tp : TermRef => tp.symbol
@@ -2134,8 +2164,8 @@ object Types {
21342164 case arg : TypeBounds =>
21352165 val v = param.paramVarianceSign
21362166 val pbounds = param.paramInfo
2137- if (v > 0 && pbounds.loBound.dealiasKeepAnnots.isNothing ) TypeAlias (arg.hiBound & rebase(pbounds.hiBound))
2138- else if (v < 0 && pbounds.hiBound.dealiasKeepAnnots.isTopType ) TypeAlias (arg.loBound | rebase(pbounds.loBound))
2167+ if (v > 0 && pbounds.loBound.dealiasKeepAnnots.isExactlyNothing ) TypeAlias (arg.hiBound & rebase(pbounds.hiBound))
2168+ else if (v < 0 && pbounds.hiBound.dealiasKeepAnnots.isExactlyAny ) TypeAlias (arg.loBound | rebase(pbounds.loBound))
21392169 else arg recoverable_& rebase(pbounds)
21402170 case arg => TypeAlias (arg)
21412171 }
@@ -2297,7 +2327,7 @@ object Types {
22972327 if (base.isAnd == variance >= 0 ) tp1 & tp2 else tp1 | tp2
22982328 case _ =>
22992329 if (pre.termSymbol.is(Package )) argForParam(pre.select(nme.PACKAGE ))
2300- else if (pre.isNothing ) pre
2330+ else if (pre.isExactlyNothing ) pre
23012331 else NoType
23022332 }
23032333 }
@@ -2316,7 +2346,7 @@ object Types {
23162346 */
23172347 def derivedSelect (prefix : Type )(using Context ): Type =
23182348 if (prefix eq this .prefix) this
2319- else if (prefix.isNothing ) prefix
2349+ else if (prefix.isExactlyNothing ) prefix
23202350 else {
23212351 if (isType) {
23222352 val res =
@@ -4304,7 +4334,7 @@ object Types {
43044334
43054335 /** For uninstantiated type variables: Is the lower bound different from Nothing? */
43064336 def hasLowerBound (using Context ): Boolean =
4307- ! ctx.typerState.constraint.entry(origin).loBound.isNothing
4337+ ! ctx.typerState.constraint.entry(origin).loBound.isExactlyNothing
43084338
43094339 /** For uninstantiated type variables: Is the upper bound different from Any? */
43104340 def hasUpperBound (using Context ): Boolean =
@@ -5309,7 +5339,7 @@ object Types {
53095339 case _ =>
53105340 def propagate (lo : Type , hi : Type ) =
53115341 range(derivedRefinedType(tp, parent, lo), derivedRefinedType(tp, parent, hi))
5312- if (parent.isNothing ) parent
5342+ if (parent.isExactlyNothing ) parent
53135343 else info match {
53145344 case Range (infoLo : TypeBounds , infoHi : TypeBounds ) =>
53155345 assert(variance == 0 )
@@ -5402,7 +5432,7 @@ object Types {
54025432 case Range (lo, hi) =>
54035433 range(tp.derivedAnnotatedType(lo, annot), tp.derivedAnnotatedType(hi, annot))
54045434 case _ =>
5405- if (underlying.isNothing ) underlying
5435+ if (underlying.isExactlyNothing ) underlying
54065436 else tp.derivedAnnotatedType(underlying, annot)
54075437 }
54085438 override protected def derivedWildcardType (tp : WildcardType , bounds : Type ): WildcardType =
@@ -5650,7 +5680,7 @@ object Types {
56505680 else {
56515681 seen += tp
56525682 tp match {
5653- case tp if tp.isTopType || tp.isNothing =>
5683+ case tp if tp.isExactlyAny || tp.isExactlyNothing =>
56545684 cs
56555685 case tp : AppliedType =>
56565686 foldOver(cs + tp.typeSymbol, tp)
0 commit comments