Skip to content

Commit d6edcc1

Browse files
committed
Add comments
1 parent 169ef9c commit d6edcc1

File tree

4 files changed

+17
-1
lines changed

4 files changed

+17
-1
lines changed

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,8 @@ trait Applications extends Compatibility {
911911
case funRef: TermRef =>
912912
var app = ApplyTo(tree, fun1, funRef, proto, pt)
913913
if ctx.mode.is(Mode.UnsafeJavaReturn) then
914+
// When UnsafeJavaReturn is enabled and the applied function is Java defined,
915+
// we replece `| Null` with `@CanEqualNull` in the return type.
914916
val funSym = fun1.symbol
915917
if funSym.is(JavaDefined)
916918
&& funSym.isTerm

compiler/src/dotty/tools/dotc/typer/Synthesizer.scala

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,17 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
164164
cmpWithBoxed(cls2, cls1)
165165
else if ctx.mode.is(Mode.SafeNulls) then
166166
// If explicit nulls is enabled, and unsafeNulls is not enabled,
167+
// and the types don't have `@CanEqualNull` annotation,
167168
// we want to disallow comparison between Object and Null.
168169
// If we have to check whether a variable with a non-nullable type has null value
169170
// (for example, a NotNull java method returns null for some reasons),
170-
// we can still cast it to a nullable type then compare its value.
171+
// we can still use `eq/ne null` or cast it to a nullable type then compare its value.
171172
//
172173
// Example:
173174
// val x: String = null.asInstanceOf[String]
174175
// if (x == null) {} // error: x is non-nullable
175176
// if (x.asInstanceOf[String|Null] == null) {} // ok
177+
// if (x eq null) {} // ok
176178
cls1 == defn.NullClass && cls1 == cls2
177179
else if cls1 == defn.NullClass then
178180
cls1 == cls2 || cls2.derivesFrom(defn.ObjectClass)
@@ -187,6 +189,14 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
187189
* interpret.
188190
*/
189191
def canComparePredefined(tp1: Type, tp2: Type) =
192+
// In explicit nulls, when one of type has `@CanEqualNull` annotation,
193+
// we use unsafe nulls semantic to check, which allows reference types
194+
// to be compared with `Null`.
195+
// Example:
196+
// val s1: String = ???
197+
// s1 == null // error
198+
// val s2: String @CanEqualNull = ???
199+
// s2 == null // ok
190200
val checkCtx = if ctx.explicitNulls
191201
&& (tp1.hasAnnotation(defn.CanEqualNullAnnot) || tp2.hasAnnotation(defn.CanEqualNullAnnot))
192202
then ctx.retractMode(Mode.SafeNulls) else ctx

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
647647
val qual = typedExpr(tree.qualifier, shallowSelectionProto(tree.name, pt, this))
648648
var sel = typedSelect(tree, pt, qual).withSpan(tree.span).computeNullable()
649649
if ctx.mode.is(Mode.UnsafeJavaReturn) && pt != AssignProto then
650+
// When UnsafeJavaReturn is enabled and the selected member is Java defined,
651+
// we replece `| Null` with `@CanEqualNull` in its type
652+
// if it is not at left hand side of assignments.
650653
val sym = sel.symbol
651654
if sym.is(JavaDefined) && sym.isTerm && !sym.is(Method) then
652655
val stp1 = sel.tpe.widen

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ class CompilationTests {
249249
compileFilesInDir("tests/explicit-nulls/pos-separate", explicitNullsOptions),
250250
compileFilesInDir("tests/explicit-nulls/pos-patmat", explicitNullsOptions and "-Xfatal-warnings"),
251251
compileFilesInDir("tests/explicit-nulls/unsafe-common", explicitNullsOptions and "-language:unsafeNulls"),
252+
compileFilesInDir("tests/explicit-nulls/unsafe-java", explicitNullsOptions),
252253
compileFile("tests/explicit-nulls/pos-special/i14682.scala", explicitNullsOptions and "-Ysafe-init"),
253254
compileFile("tests/explicit-nulls/pos-special/i14947.scala", explicitNullsOptions and "-Ytest-pickler" and "-Xprint-types"),
254255
)

0 commit comments

Comments
 (0)