Skip to content

Commit 35344fe

Browse files
committed
Add comments
1 parent f4632c7 commit 35344fe

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
@@ -161,15 +161,17 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
161161
cmpWithBoxed(cls2, cls1)
162162
else if ctx.mode.is(Mode.SafeNulls) then
163163
// If explicit nulls is enabled, and unsafeNulls is not enabled,
164+
// and the types don't have `@CanEqualNull` annotation,
164165
// we want to disallow comparison between Object and Null.
165166
// If we have to check whether a variable with a non-nullable type has null value
166167
// (for example, a NotNull java method returns null for some reasons),
167-
// we can still cast it to a nullable type then compare its value.
168+
// we can still use `eq/ne null` or cast it to a nullable type then compare its value.
168169
//
169170
// Example:
170171
// val x: String = null.asInstanceOf[String]
171172
// if (x == null) {} // error: x is non-nullable
172173
// if (x.asInstanceOf[String|Null] == null) {} // ok
174+
// if (x eq null) {} // ok
173175
cls1 == defn.NullClass && cls1 == cls2
174176
else if cls1 == defn.NullClass then
175177
cls1 == cls2 || cls2.derivesFrom(defn.ObjectClass)
@@ -184,6 +186,14 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
184186
* interpret.
185187
*/
186188
def canComparePredefined(tp1: Type, tp2: Type) =
189+
// In explicit nulls, when one of type has `@CanEqualNull` annotation,
190+
// we use unsafe nulls semantic to check, which allows reference types
191+
// to be compared with `Null`.
192+
// Example:
193+
// val s1: String = ???
194+
// s1 == null // error
195+
// val s2: String @CanEqualNull = ???
196+
// s2 == null // ok
187197
val checkCtx = if ctx.explicitNulls
188198
&& (tp1.hasAnnotation(defn.CanEqualNullAnnot) || tp2.hasAnnotation(defn.CanEqualNullAnnot))
189199
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
@@ -645,6 +645,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
645645
val qual = typedExpr(tree.qualifier, shallowSelectionProto(tree.name, pt, this))
646646
var sel = typedSelect(tree, pt, qual).withSpan(tree.span).computeNullable()
647647
if ctx.mode.is(Mode.UnsafeJavaReturn) && pt != AssignProto then
648+
// When UnsafeJavaReturn is enabled and the selected member is Java defined,
649+
// we replece `| Null` with `@CanEqualNull` in its type
650+
// if it is not at left hand side of assignments.
648651
val sym = sel.symbol
649652
if sym.is(JavaDefined) && sym.isTerm && !sym.is(Method) then
650653
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)