@@ -209,7 +209,27 @@ object Types {
209
209
def isAnyRef (using Context ): Boolean = isRef(defn.ObjectClass , skipRefined = false )
210
210
def isAnyKind (using Context ): Boolean = isRef(defn.AnyKindClass , skipRefined = false )
211
211
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 )
213
233
214
234
/** Does this type refer exactly to class symbol `sym`, instead of to a subclass of `sym`?
215
235
* Implemented like `isRef`, but follows more types: all type proxies as well as and- and or-types
@@ -224,7 +244,9 @@ object Types {
224
244
case _ => false
225
245
}
226
246
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
+ */
228
250
final def derivesFrom (cls : Symbol )(using Context ): Boolean = {
229
251
def loop (tp : Type ): Boolean = tp match {
230
252
case tp : TypeRef =>
@@ -239,11 +261,15 @@ object Types {
239
261
case tp : AndType =>
240
262
loop(tp.tp1) || loop(tp.tp2)
241
263
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)
247
273
case tp : JavaArrayType =>
248
274
cls == defn.ObjectClass
249
275
case _ =>
@@ -252,6 +278,8 @@ object Types {
252
278
loop(this )
253
279
}
254
280
281
+ def isFromJavaObject (using Context ): Boolean = typeSymbol eq defn.FromJavaObjectSymbol
282
+
255
283
/** True iff `symd` is a denotation of a class type parameter and the reference
256
284
* `<this> . <symd>` is an actual argument reference, i.e. `this` is different
257
285
* from the ThisType of `symd`'s owner.
@@ -265,20 +293,6 @@ object Types {
265
293
}
266
294
}
267
295
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
-
282
296
/** Is this type a (possibly aliased) singleton type? */
283
297
def isSingleton (using Context ): Boolean = dealias.isInstanceOf [SingletonType ]
284
298
@@ -478,6 +492,22 @@ object Types {
478
492
final def classSymbols (using Context ): List [ClassSymbol ] =
479
493
parentSymbols(_.isClass).asInstanceOf
480
494
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
+
481
511
/** The term symbol associated with the type */
482
512
@ tailrec final def termSymbol (using Context ): Symbol = this match {
483
513
case tp : TermRef => tp.symbol
@@ -2134,8 +2164,8 @@ object Types {
2134
2164
case arg : TypeBounds =>
2135
2165
val v = param.paramVarianceSign
2136
2166
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))
2139
2169
else arg recoverable_& rebase(pbounds)
2140
2170
case arg => TypeAlias (arg)
2141
2171
}
@@ -2297,7 +2327,7 @@ object Types {
2297
2327
if (base.isAnd == variance >= 0 ) tp1 & tp2 else tp1 | tp2
2298
2328
case _ =>
2299
2329
if (pre.termSymbol.is(Package )) argForParam(pre.select(nme.PACKAGE ))
2300
- else if (pre.isNothing ) pre
2330
+ else if (pre.isExactlyNothing ) pre
2301
2331
else NoType
2302
2332
}
2303
2333
}
@@ -2316,7 +2346,7 @@ object Types {
2316
2346
*/
2317
2347
def derivedSelect (prefix : Type )(using Context ): Type =
2318
2348
if (prefix eq this .prefix) this
2319
- else if (prefix.isNothing ) prefix
2349
+ else if (prefix.isExactlyNothing ) prefix
2320
2350
else {
2321
2351
if (isType) {
2322
2352
val res =
@@ -4304,7 +4334,7 @@ object Types {
4304
4334
4305
4335
/** For uninstantiated type variables: Is the lower bound different from Nothing? */
4306
4336
def hasLowerBound (using Context ): Boolean =
4307
- ! ctx.typerState.constraint.entry(origin).loBound.isNothing
4337
+ ! ctx.typerState.constraint.entry(origin).loBound.isExactlyNothing
4308
4338
4309
4339
/** For uninstantiated type variables: Is the upper bound different from Any? */
4310
4340
def hasUpperBound (using Context ): Boolean =
@@ -5309,7 +5339,7 @@ object Types {
5309
5339
case _ =>
5310
5340
def propagate (lo : Type , hi : Type ) =
5311
5341
range(derivedRefinedType(tp, parent, lo), derivedRefinedType(tp, parent, hi))
5312
- if (parent.isNothing ) parent
5342
+ if (parent.isExactlyNothing ) parent
5313
5343
else info match {
5314
5344
case Range (infoLo : TypeBounds , infoHi : TypeBounds ) =>
5315
5345
assert(variance == 0 )
@@ -5402,7 +5432,7 @@ object Types {
5402
5432
case Range (lo, hi) =>
5403
5433
range(tp.derivedAnnotatedType(lo, annot), tp.derivedAnnotatedType(hi, annot))
5404
5434
case _ =>
5405
- if (underlying.isNothing ) underlying
5435
+ if (underlying.isExactlyNothing ) underlying
5406
5436
else tp.derivedAnnotatedType(underlying, annot)
5407
5437
}
5408
5438
override protected def derivedWildcardType (tp : WildcardType , bounds : Type ): WildcardType =
@@ -5650,7 +5680,7 @@ object Types {
5650
5680
else {
5651
5681
seen += tp
5652
5682
tp match {
5653
- case tp if tp.isTopType || tp.isNothing =>
5683
+ case tp if tp.isExactlyAny || tp.isExactlyNothing =>
5654
5684
cs
5655
5685
case tp : AppliedType =>
5656
5686
foldOver(cs + tp.typeSymbol, tp)
0 commit comments