11package dotty .tools .dotc
22package core
33
4- import scala .language .{unsafeNulls => _ }
5-
64import ast .Trees ._
75import Contexts ._
86import Symbols .defn
@@ -11,43 +9,6 @@ import Types._
119/** Defines operations on nullable types and tree. */
1210object NullOpsDecorator :
1311
14- private class StripNullsMap (isDeep : Boolean )(using Context ) extends TypeMap :
15- def strip (tp : Type ): Type = tp match
16- case tp @ OrType (lhs, rhs) =>
17- val llhs = this (lhs)
18- val rrhs = this (rhs)
19- if rrhs.isNullType then llhs
20- else if llhs.isNullType then rrhs
21- else derivedOrType(tp, llhs, rrhs)
22- case tp @ AndType (tp1, tp2) =>
23- // We cannot `tp.derivedAndType(strip(tp1), strip(tp2))` directly,
24- // since `stripNull((A | Null) & B)` would produce the wrong
25- // result `(A & B) | Null`.
26- val tp1s = this (tp1)
27- val tp2s = this (tp2)
28- if isDeep || (tp1s ne tp1) && (tp2s ne tp2) then
29- derivedAndType(tp, tp1s, tp2s)
30- else tp
31- case tp : TypeBounds =>
32- mapOver(tp)
33- case _ => tp
34-
35- def stripOver (tp : Type ): Type = tp match
36- case appTp @ AppliedType (tycon, targs) =>
37- derivedAppliedType(appTp, tycon, targs.map(this ))
38- case ptp : PolyType =>
39- derivedLambdaType(ptp)(ptp.paramInfos, this (ptp.resType))
40- case mtp : MethodType =>
41- mapOver(mtp)
42- case _ => strip(tp)
43-
44- override def apply (tp : Type ): Type =
45- val tpw = tp.widenDealias
46- val tpws = if isDeep then stripOver(tpw) else strip(tpw)
47- if tpws ne tpw then tpws else tp
48-
49- end StripNullsMap
50-
5112 extension (self : Type )
5213 /** Syntactically strips the nullability from this type.
5314 * If the type is `T1 | ... | Tn`, and `Ti` references to `Null`,
@@ -56,22 +17,38 @@ object NullOpsDecorator:
5617 * The type will not be changed if explicit-nulls is not enabled.
5718 */
5819 def stripNull (using Context ): Type = {
59- if ctx.explicitNulls then new StripNullsMap (false )(self) else self
20+ def strip (tp : Type ): Type =
21+ val tpWiden = tp.widenDealias
22+ val tpStripped = tpWiden match {
23+ case tp @ OrType (lhs, rhs) =>
24+ val llhs = strip(lhs)
25+ val rrhs = strip(rhs)
26+ if rrhs.isNullType then llhs
27+ else if llhs.isNullType then rrhs
28+ else tp.derivedOrType(llhs, rrhs)
29+ case tp @ AndType (tp1, tp2) =>
30+ // We cannot `tp.derivedAndType(strip(tp1), strip(tp2))` directly,
31+ // since `stripNull((A | Null) & B)` would produce the wrong
32+ // result `(A & B) | Null`.
33+ val tp1s = strip(tp1)
34+ val tp2s = strip(tp2)
35+ if (tp1s ne tp1) && (tp2s ne tp2) then
36+ tp.derivedAndType(tp1s, tp2s)
37+ else tp
38+ case tp @ TypeBounds (lo, hi) =>
39+ tp.derivedTypeBounds(strip(lo), strip(hi))
40+ case tp => tp
41+ }
42+ if tpStripped ne tpWiden then tpStripped else tp
43+
44+ if ctx.explicitNulls then strip(self) else self
6045 }
6146
6247 /** Is self (after widening and dealiasing) a type of the form `T | Null`? */
6348 def isNullableUnion (using Context ): Boolean = {
6449 val stripped = self.stripNull
6550 stripped ne self
6651 }
67-
68- /** Strips nulls from this type deeply.
69- * Compaired to `stripNull`, `stripNullsDeep` will apply `stripNull` to
70- * each member of function types as well.
71- */
72- def stripNullsDeep (using Context ): Type =
73- if ctx.explicitNulls then new StripNullsMap (true )(self) else self
74-
7552 end extension
7653
7754 import ast .tpd ._
0 commit comments