Skip to content

Commit 6d7f995

Browse files
committed
Add ctx.explicitNulls helper method to context
1 parent 32ec9e7 commit 6d7f995

15 files changed

+65
-66
lines changed

compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ class DottyPrimitives(ctx: Context) {
156156
addPrimitive(defn.Any_##, HASH)
157157

158158
// java.lang.Object
159-
if (ctx.settings.YexplicitNulls.value) {
159+
if (ctx.explicitNulls) {
160160
// scala.RefEq
161161
addPrimitive(defn.RefEq_eq, ID)
162162
addPrimitive(defn.RefEq_ne, NI)

compiler/src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,9 @@ object Contexts {
427427
def useColors: Boolean =
428428
base.settings.color.value == "always"
429429

430+
/** Is the explicit nulls option set? */
431+
def explicitNulls: Boolean = base.settings.YexplicitNulls.value
432+
430433
protected def init(outer: Context, origin: Context): this.type = {
431434
util.Stats.record("Context.fresh")
432435
_outer = outer

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -286,11 +286,7 @@ class Definitions {
286286
lazy val ObjectClass: ClassSymbol = {
287287
val cls = ctx.requiredClass("java.lang.Object")
288288
assert(!cls.isCompleted, "race for completing java.lang.Object")
289-
val parents = if (ctx.settings.YexplicitNulls.value) {
290-
AnyType :: RefEqType :: Nil
291-
} else {
292-
AnyType :: Nil
293-
}
289+
val parents = if (ctx.explicitNulls) AnyType :: RefEqType :: Nil else AnyType :: Nil
294290
cls.info = ClassInfo(cls.owner.thisType, cls, parents, newScope)
295291
cls.setFlag(NoInits)
296292

@@ -309,12 +305,12 @@ class Definitions {
309305
def AnyRefType: TypeRef = AnyRefAlias.typeRef
310306

311307
// TODO(abeln): modify usage sites to use `RefEq_eq/ne` once we migrate to explicit nulls?
312-
lazy val Object_eq: TermSymbol = if (ctx.settings.YexplicitNulls.value) {
308+
lazy val Object_eq: TermSymbol = if (ctx.explicitNulls) {
313309
RefEq_eq
314310
} else {
315311
enterMethod(ObjectClass, nme.eq, methOfAnyRef(BooleanType), Final)
316312
}
317-
lazy val Object_ne: TermSymbol = if (ctx.settings.YexplicitNulls.value) {
313+
lazy val Object_ne: TermSymbol = if (ctx.explicitNulls) {
318314
RefEq_ne
319315
} else {
320316
enterMethod(ObjectClass, nme.ne, methOfAnyRef(BooleanType), Final)
@@ -353,7 +349,7 @@ class Definitions {
353349

354350
/** Method representing a throw */
355351
lazy val throwMethod: TermSymbol = {
356-
val argTpe = if (ctx.settings.YexplicitNulls.value) {
352+
val argTpe = if (ctx.explicitNulls) {
357353
OrType(ThrowableType, NullType)
358354
} else {
359355
ThrowableType
@@ -372,30 +368,30 @@ class Definitions {
372368
* `RefEq` is just a marker trait and there's no corresponding class file, since it gets erased to `Object`.
373369
*/
374370
lazy val RefEqClass: ClassSymbol = {
375-
assert(ctx.settings.YexplicitNulls.value)
371+
assert(ctx.explicitNulls)
376372
enterCompleteClassSymbol(ScalaPackageClass, tpnme.RefEq, Trait, AnyClass.typeRef :: Nil)
377373
}
378374
def RefEqType: TypeRef = {
379-
assert(ctx.settings.YexplicitNulls.value)
375+
assert(ctx.explicitNulls)
380376
RefEqClass.typeRef
381377
}
382378

383379
lazy val RefEq_eq: TermSymbol = {
384-
assert(ctx.settings.YexplicitNulls.value)
380+
assert(ctx.explicitNulls)
385381
enterMethod(RefEqClass, nme.eq, MethodType(List(RefEqType), BooleanType), Final)
386382
}
387383
lazy val RefEq_ne: TermSymbol = {
388-
assert(ctx.settings.YexplicitNulls.value)
384+
assert(ctx.explicitNulls)
389385
enterMethod(RefEqClass, nme.ne, MethodType(List(RefEqType), BooleanType), Final)
390386
}
391387

392388
def RefEqMethods: List[TermSymbol] = {
393-
assert(ctx.settings.YexplicitNulls.value)
389+
assert(ctx.explicitNulls)
394390
List(RefEq_eq, RefEq_ne)
395391
}
396392

397393
lazy val NullClass: ClassSymbol = {
398-
val parents = if (ctx.settings.YexplicitNulls.value) {
394+
val parents = if (ctx.explicitNulls) {
399395
List(AnyType, RefEqType)
400396
} else {
401397
List(ObjectType)
@@ -416,11 +412,11 @@ class Definitions {
416412
* ```
417413
*/
418414
lazy val JavaNullAlias: TypeSymbol = {
419-
assert(ctx.settings.YexplicitNulls.value)
415+
assert(ctx.explicitNulls)
420416
enterAliasType(tpnme.JavaNull, NullType)
421417
}
422418
def JavaNullAliasType: TypeRef = {
423-
assert(ctx.settings.YexplicitNulls.value)
419+
assert(ctx.explicitNulls)
424420
JavaNullAlias.typeRef
425421
}
426422

@@ -661,14 +657,14 @@ class Definitions {
661657
lazy val ClassCastExceptionClass: ClassSymbol = ctx.requiredClass("java.lang.ClassCastException")
662658
lazy val ClassCastExceptionClass_stringConstructor: TermSymbol = ClassCastExceptionClass.info.member(nme.CONSTRUCTOR).suchThat(_.info.firstParamTypes match {
663659
case List(pt) =>
664-
val pt1 = if (ctx.settings.YexplicitNulls.value) pt.stripNull else pt
660+
val pt1 = if (ctx.explicitNulls) pt.stripNull else pt
665661
pt1 isRef StringClass
666662
case _ => false
667663
}).symbol.asTerm
668664
lazy val ArithmeticExceptionClass: ClassSymbol = ctx.requiredClass("java.lang.ArithmeticException")
669665
lazy val ArithmeticExceptionClass_stringConstructor: TermSymbol = ArithmeticExceptionClass.info.member(nme.CONSTRUCTOR).suchThat(_.info.firstParamTypes match {
670666
case List(pt) =>
671-
val pt1 = if (ctx.settings.YexplicitNulls.value) pt.stripNull else pt
667+
val pt1 = if (ctx.explicitNulls) pt.stripNull else pt
672668
pt1 isRef StringClass
673669
case _ => false
674670
}).symbol.asTerm
@@ -1123,7 +1119,7 @@ class Definitions {
11231119
name.drop(prefix.length).forall(_.isDigit))
11241120

11251121
def isBottomClass(cls: Symbol): Boolean = {
1126-
if (ctx.settings.YexplicitNulls.value && !ctx.phase.erasedTypes) cls == NothingClass
1122+
if (ctx.explicitNulls && !ctx.phase.erasedTypes) cls == NothingClass
11271123
else isBottomClassAfterErasure(cls)
11281124
}
11291125

@@ -1132,7 +1128,7 @@ class Definitions {
11321128
}
11331129

11341130
def isBottomType(tp: Type): Boolean = {
1135-
if (ctx.settings.YexplicitNulls.value && !ctx.phase.erasedTypes) tp.derivesFrom(NothingClass)
1131+
if (ctx.explicitNulls && !ctx.phase.erasedTypes) tp.derivesFrom(NothingClass)
11361132
else isBottomTypeAfterErasure(tp)
11371133
}
11381134

@@ -1254,7 +1250,7 @@ class Definitions {
12541250

12551251
lazy val NotRuntimeClasses: Set[Symbol] = {
12561252
val classes: Set[Symbol] = Set(AnyClass, AnyValClass, NullClass, NothingClass)
1257-
if (ctx.settings.YexplicitNulls.value) {
1253+
if (ctx.explicitNulls) {
12581254
classes + RefEqClass
12591255
} else {
12601256
classes
@@ -1462,7 +1458,7 @@ class Definitions {
14621458
.updated(SingletonClass, ObjectClass)
14631459
.updated(TupleClass, ObjectClass)
14641460
.updated(NonEmptyTupleClass, ProductClass)
1465-
if (ctx.settings.YexplicitNulls.value) {
1461+
if (ctx.explicitNulls) {
14661462
idMap.updated(RefEqClass, ObjectClass)
14671463
} else {
14681464
idMap
@@ -1487,7 +1483,7 @@ class Definitions {
14871483
SingletonClass,
14881484
EqualsPatternClass)
14891485

1490-
if (ctx.settings.YexplicitNulls.value) synth ++ List(JavaNullAlias, RefEqClass)
1486+
if (ctx.explicitNulls) synth ++ List(JavaNullAlias, RefEqClass)
14911487
else synth
14921488
}
14931489

@@ -1498,7 +1494,7 @@ class Definitions {
14981494
/** Lists core methods that don't have underlying bytecode, but are synthesized on-the-fly in every reflection universe */
14991495
lazy val syntheticCoreMethods: List[TermSymbol] = {
15001496
val methods = AnyMethods ++ ObjectMethods ++ List(String_+, throwMethod)
1501-
if (ctx.settings.YexplicitNulls.value) {
1497+
if (ctx.explicitNulls) {
15021498
methods ++ RefEqMethods
15031499
} else {
15041500
methods

compiler/src/dotty/tools/dotc/core/FlowTyper.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ object FlowTyper {
2626
* If the precision of the type can't be improved, then returns the type unchanged.
2727
*/
2828
def refineType(tpe: Type)(implicit ctx: Context): Type = {
29-
assert(ctx.settings.YexplicitNulls.value)
29+
assert(ctx.explicitNulls)
3030
tpe match {
3131
case tref: TermRef if ctx.flowFacts.contains(tref) =>
3232
NonNullTermRef.fromTermRef(tref)
@@ -98,7 +98,7 @@ object FlowTyper {
9898
* NN(cond, _) = {} otherwise
9999
*/
100100
def inferFromCond(cond: Tree)(implicit ctx: Context): Inferred = {
101-
assert(ctx.settings.YexplicitNulls.value)
101+
assert(ctx.explicitNulls)
102102
/** Combine two sets of facts according to `op`. */
103103
def combine(lhs: Inferred, op: Name, rhs: Inferred): Inferred = {
104104
op match {
@@ -176,7 +176,7 @@ object FlowTyper {
176176
* ```
177177
*/
178178
def inferWithinCond(cond: Tree)(implicit ctx: Context): FlowFacts = {
179-
assert(ctx.settings.YexplicitNulls.value)
179+
assert(ctx.explicitNulls)
180180
cond match {
181181
case Select(lhs, op) if op == nme.ZAND || op == nme.ZOR =>
182182
val Inferred(ifTrue, ifFalse) = inferFromCond(lhs)
@@ -223,7 +223,7 @@ object FlowTyper {
223223
s.tpe.isBottomType
224224
}
225225

226-
assert(ctx.settings.YexplicitNulls.value)
226+
assert(ctx.explicitNulls)
227227
stat match {
228228
case If(cond, thenExpr, elseExpr) =>
229229
val Inferred(ifTrue, ifFalse) = inferFromCond(cond)

compiler/src/dotty/tools/dotc/core/JavaNullInterop.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ object JavaNullInterop {
4444
* But the selection can throw an NPE if the returned value is `null`.
4545
*/
4646
def nullifyMember(sym: Symbol, tp: Type)(implicit ctx: Context): Type = {
47-
assert(ctx.settings.YexplicitNulls.value)
47+
assert(ctx.explicitNulls)
4848
assert(sym.is(JavaDefined), "can only nullify java-defined members")
4949

5050
// A list of members that are special-cased.

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ object SymDenotations {
690690

691691
/** Is this symbol a class of which `null` is a value? */
692692
final def isNullableClass(implicit ctx: Context): Boolean = {
693-
if (ctx.settings.YexplicitNulls.value && !ctx.phase.erasedTypes) {
693+
if (ctx.explicitNulls && !ctx.phase.erasedTypes) {
694694
symbol == defn.NullClass || symbol == defn.AnyClass
695695
} else {
696696
isNullableClassAfterErasure

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ object Types {
353353

354354
/** Is this (after widening and dealiasing) a type of the form `T | Null`? */
355355
def isNullableUnion(implicit ctx: Context): Boolean = {
356-
assert(ctx.settings.YexplicitNulls.value)
356+
assert(ctx.explicitNulls)
357357
this.widenDealias.normNullableUnion match {
358358
case OrType(_, right) => right.isNullType
359359
case _ => false
@@ -362,7 +362,7 @@ object Types {
362362

363363
/** Is this type exactly `JavaNull` (no vars, aliases, refinements etc allowed)? */
364364
def isJavaNullType(implicit ctx: Context): Boolean = {
365-
assert(ctx.settings.YexplicitNulls.value)
365+
assert(ctx.explicitNulls)
366366
// We can't do `this == defn.JavaNull` because when trees are unpickled new references
367367
// to `JavaNull` could be created that are different from `defn.JavaNull`.
368368
// Instead, we compare the symbol.
@@ -371,7 +371,7 @@ object Types {
371371

372372
/** Is this (after widening and dealiasing) a type of the form `T | JavaNull`? */
373373
def isJavaNullableUnion(implicit ctx: Context): Boolean = {
374-
assert(ctx.settings.YexplicitNulls.value)
374+
assert(ctx.explicitNulls)
375375
def peelOff(tpe: Type): Boolean = tpe match {
376376
case OrType(left, right) =>
377377
right.isJavaNullType || right.isNullType && peelOff(left)
@@ -401,7 +401,7 @@ object Types {
401401
* e.g. `Null | (T1 | Null) | T2` => `T1 | T2 | Null | Null`
402402
*/
403403
def normNullableUnion(implicit ctx: Context): Type = {
404-
assert(ctx.settings.YexplicitNulls.value)
404+
assert(ctx.explicitNulls)
405405
def split(tp: Type, nonNull: List[Type], nll: List[Type]): (List[Type], List[Type]) = {
406406
tp match {
407407
case OrType(left, right) =>
@@ -420,7 +420,7 @@ object Types {
420420

421421
/** Strips types according to `stripPred` from a nullable union. */
422422
private def stripNullWithPred(stripPred: Type => Boolean)(implicit ctx: Context): Type = {
423-
assert(ctx.settings.YexplicitNulls.value)
423+
assert(ctx.explicitNulls)
424424
def strip(tp: Type, changed: Boolean): (Type, Boolean) = {
425425
tp match {
426426
case OrType(left, right) if right.isNullType =>
@@ -445,13 +445,13 @@ object Types {
445445
* If this type isn't (syntactically) nullable, then returns the type unchanged.
446446
*/
447447
def stripNull(implicit ctx: Context): Type = {
448-
assert(ctx.settings.YexplicitNulls.value)
448+
assert(ctx.explicitNulls)
449449
stripNullWithPred(_.isNullType)
450450
}
451451

452452
/** Like `stripNull`, but removes only the `JavaNull`s. */
453453
def stripJavaNull(implicit ctx: Context): Type = {
454-
assert(ctx.settings.YexplicitNulls.value)
454+
assert(ctx.explicitNulls)
455455
stripNullWithPred(_.isJavaNullType)
456456
}
457457

@@ -461,7 +461,7 @@ object Types {
461461
* If no `JavaNull` unions are found within the type, then returns the input type unchanged.
462462
*/
463463
def stripAllJavaNull(implicit ctx: Context): Type = {
464-
assert(ctx.settings.YexplicitNulls.value)
464+
assert(ctx.explicitNulls)
465465
var diff = false
466466
object RemoveNulls extends TypeMap {
467467
override def apply(tp: Type): Type = tp match {
@@ -477,7 +477,7 @@ object Types {
477477

478478
/** Injects this type into a union with `JavaNull`. */
479479
def toJavaNullableUnion(implicit ctx: Context): Type = {
480-
assert(ctx.settings.YexplicitNulls.value)
480+
assert(ctx.explicitNulls)
481481
if (this.isJavaNullableUnion) this
482482
else OrType(this, defn.JavaNullAliasType)
483483
}
@@ -563,7 +563,7 @@ object Types {
563563
val rsym = r.classSymbol
564564
if (lsym isSubClass rsym) rsym
565565
else if (rsym isSubClass lsym) lsym
566-
else if (ctx.settings.YexplicitNulls.value && this.isNullableUnion) {
566+
else if (ctx.explicitNulls && this.isNullableUnion) {
567567
val OrType(left, _) = this.normNullableUnion
568568
// If `left` is a reference type, then the class LUB of `left | Null` is `RefEq`.
569569
// This is another one-of case that keeps this method sound, but not complete.
@@ -728,7 +728,7 @@ object Types {
728728
case AndType(l, r) =>
729729
goAnd(l, r)
730730
case tp: OrType =>
731-
if (ctx.settings.YexplicitNulls.value && tp.isJavaNullableUnion) {
731+
if (ctx.explicitNulls && tp.isJavaNullableUnion) {
732732
// Selecting `name` from a type `T|JavaNull` is like selecting `name` from `T`.
733733
// This can throw at runtime, but we trade soundness for usability.
734734
// We need to strip `JavaNull` from both the type and the prefix so that
@@ -1192,7 +1192,7 @@ object Types {
11921192
*/
11931193
def widenUnion(implicit ctx: Context): Type = this match {
11941194
case OrType(tp1, tp2) =>
1195-
if (ctx.settings.YexplicitNulls.value && isNullableUnion) {
1195+
if (ctx.explicitNulls && isNullableUnion) {
11961196
// Don't widen `T|Null`, since otherwise we wouldn't be able to infer nullable unions.
11971197
val OrType(leftTpe, nullTpe) = normNullableUnion
11981198
OrType(leftTpe.widenUnion, nullTpe)
@@ -1981,7 +1981,7 @@ object Types {
19811981

19821982
def finish(d: Denotation): Denotation = {
19831983
if (d.exists) {
1984-
val d1 = if (ctx.settings.YexplicitNulls.value && this.isInstanceOf[NonNullTermRef]) {
1984+
val d1 = if (ctx.explicitNulls && this.isInstanceOf[NonNullTermRef]) {
19851985
// If the denotation is computed for the first time, or if it's ever updated, make sure
19861986
// that the `info` is non-null.
19871987
d.mapInfo(_.stripNull)
@@ -2467,7 +2467,7 @@ object Types {
24672467

24682468
/** Create a `TermRef` that's just like `tref`, but whose `info` is always non-null. */
24692469
def fromTermRef(tref: TermRef)(implicit ctx: Context): NonNullTermRef = {
2470-
assert(ctx.settings.YexplicitNulls.value)
2470+
assert(ctx.explicitNulls)
24712471
val denot = tref.denot.mapInfo(_.stripNull)
24722472
val nn = new NonNullTermRef(tref.prefix, denot.symbol)
24732473
// We need to set the non-null denotation directly because normally the "non-nullable" denotations

compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ class ClassfileParser(
270270
if ((denot is Flags.Method) && (jflags & JAVA_ACC_VARARGS) != 0)
271271
denot.info = arrayToRepeated(denot.info)
272272

273-
if (ctx.settings.YexplicitNulls.value) {
273+
if (ctx.explicitNulls) {
274274
denot.info = JavaNullInterop.nullifyMember(denot.symbol, denot.info)
275275
}
276276

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class Erasure extends Phase with DenotTransformer {
5959
if (!decl.isConstructor) extendedScope.enter(decl)
6060
}
6161
addDecls(defn.AnyClass)
62-
if (ctx.settings.YexplicitNulls.value) {
62+
if (ctx.explicitNulls) {
6363
addDecls(defn.RefEqClass)
6464
}
6565
ref.copySymDenotation(
@@ -75,7 +75,7 @@ class Erasure extends Phase with DenotTransformer {
7575
else oldSymbol
7676
val oldOwner = ref.owner
7777
val newOwner = {
78-
val shouldBeObject = if (ctx.settings.YexplicitNulls.value) {
78+
val shouldBeObject = if (ctx.explicitNulls) {
7979
(oldOwner eq defn.AnyClass) || (oldOwner eq defn.RefEqClass)
8080
} else {
8181
oldOwner eq defn.AnyClass

compiler/src/dotty/tools/dotc/transform/FirstTransform.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class FirstTransform extends MiniPhase with InfoTransformer { thisPhase =>
5050
override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = {
5151
tree match {
5252
case Select(qual, name) if !name.is(OuterSelectName) && tree.symbol.exists =>
53-
val qualTpe = if (ctx.settings.YexplicitNulls.value) {
53+
val qualTpe = if (ctx.explicitNulls) {
5454
// `JavaNull` is already special-cased in the Typer, but needs to be handled here as well.
5555
// We need `stripAllJavaNull` and not `stripJavaNull` because of the following case:
5656
//

0 commit comments

Comments
 (0)