You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/docs/internals/explicit-nulls.md
+12-4Lines changed: 12 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,7 @@ with union types: e.g. `val x: String | Null = null`.
9
9
10
10
The implementation of the feature in dotty can be conceptually divided in several parts:
11
11
1. changes to the type hierarchy so that `Null` is only a subtype of `Any`
12
-
2. a "translation layer" for Java interop that exposes the nullability in Java APIs
12
+
2. a "translation layer" for Java interoperability that exposes the nullability in Java APIs
13
13
3. a `unsafeNulls` language feature which enables implicit unsafe conversion between `T` and `T | Null`
14
14
15
15
## Explicit-Nulls Flag
@@ -21,7 +21,7 @@ The explicit-nulls flag is currently disabled by default. It can be enabled via
21
21
22
22
We change the type hierarchy so that `Null` is only a subtype of `Any` by:
23
23
- modifying the notion of what is a nullable class (`isNullableClass`) in `SymDenotations`
24
-
to include _only_`Null` and `Any`
24
+
to include _only_`Null` and `Any`, which is used by `TypeComparer`
25
25
- changing the parent of `Null` in `Definitions` to point to `Any` and not `AnyRef`
26
26
- changing `isBottomType` and `isBottomClass` in `Definitions`
27
27
@@ -31,7 +31,7 @@ There are some utility functions for nullable types in `NullOpsDecorator.scala`.
31
31
They are extension methods for `Type`; hence we can use them in this way: `tp.f(...)`.
32
32
33
33
-`stripNullWhenExplicit` syntactically strips all `Null` types in the union:
34
-
e.g. `String|Null => String`.
34
+
e.g. `T | Null => T`. This should only be used if we can guarantee `T` is a reference type.
35
35
-`isNullableUnion` determines whether `this` is a nullable union.
36
36
-`isNullableAfterErasure` determines whether `this` type can have `null` value after erasure.
37
37
@@ -43,7 +43,7 @@ Within `Types.scala`, we also defined an extractor `OrNull` to extract the non-n
43
43
case _ =>// otherwise
44
44
```
45
45
46
-
## Java Interop
46
+
## Java Interoperability
47
47
48
48
The problem we're trying to solve here is: if we see a Java method `String foo(String)`,
49
49
what should that method look like to Scala?
@@ -79,6 +79,14 @@ The `matches` function in `Types.scala` is used to select condidated for overrid
79
79
80
80
The `compatibleTypes` in `RefCheck.scala` determines whether the overriding types are compatible.
81
81
82
+
## Nullified Upper Bound
83
+
84
+
Suppose we have a type bound `class C[T >: Null <: String]`, it becomes unapplicable in explicit nulls, since
85
+
we don't have a type that is a supertype of `Null` and a subtype of `String`.
86
+
87
+
Hence, when we read a type bound from Scala 2 Tasty or Scala 3 Tasty, the upper bound is nullified if the lower
88
+
bound is exactly `Null`. The example above would become `class C[T >: Null <: String | Null]`.
89
+
82
90
## Unsafe Nulls
83
91
84
92
The `unsafeNulls` language feature is currently disabled by default. It can be enabled by importing `scala.language.unsafeNulls` or using `-language:unsafeNulls`. The feature object is defined in `library/src/scalaShadowing/language.scala`. We can use `config.Feature.enabled(nme.unsafeNulls)` to check if this feature is enabled.
0 commit comments