-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Relax comparison between Null and reference types in explicit nulls #23308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
04432cb
to
c909ba2
Compare
def f6(s: String | Null): String = s match { | ||
case s2 => s2 // error | ||
case null => "other" // error | ||
case null => "other" | ||
case s3 => s3 | ||
} | ||
|
||
def f7(s: String | Null): String = s match { | ||
case null => "other" | ||
case null => "other" // error | ||
case null => "other" | ||
case s3 => s3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about this test. If we matched null value, then it is clear the following null cases are unreachable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this is caused by the change here:
https://github.com/scala/scala3/pull/23308/files#diff-9678fa10ff9f7a2cdf71755535b6ef49afd31880e9d159ed4c40a39921d43454R972
That change was in the original PR #19258 . I wonder if it has been subsumed by other changes since then and might no longer be necessary. Without that change, what would break?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running scalac tests/explicit-nulls/neg/flow-match.scala -Yexplicit-nulls
with checkReachability(m)
produces the same compiler output as withoutMode(Mode.safeNulls) { checkReachability(m) }
:
-- [E007] Type Mismatch Error: tests\explicit-nulls\neg\flow-match.scala:5:15 --
5 | case s2 => s2 // error
| ^^
| Found: (s2 : String | Null)
| Required: String
|
| longer explanation available when compiling with `-explain`
1 error found
Deleting f6
and re-running causes both changes to warn about unreachability in f7
:
-- [E030] Match case Unreachable Warning: tests\explicit-nulls\neg\flow-match.scala:7:9
7 | case null => "other"
| ^^^^
| Unreachable case
1 warning found
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not an error, just a warning. We can change the test case to remove f7 entirely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, or keep it in as a positive part of the test. (No need to make it a separate pos test file.)
#23308 (comment)
Before this PR, all three errors in
After this PR, the two errors on lines 6 and 12 understandably go away. The error on line 5 prevents the compiler from getting past typer, so match reachability checking never happens. The test was not intended for match reachability checking but to test for the flow-sensitive analysis in typer. We should split the test into two, one that errors only in typer, and one that tests only match reachability checking. |
Here are the proposed two tests. Note that the second one needs to go in // Test flow-typing when NotNullInfos are from cases
object MatchTest {
def f6(s: String | Null): String = s match {
case s2 => s2 // error
case s3 => s3 // OK since not null
}
def f7(s: String | Null): String = s match {
case null => "other"
case s3 => s3 // OK since not null
}
} // Test unreachable matches in presence of nulls
object MatchTest2 {
def f6(s: String | Null): String = s match {
case s2 => s2.nn
case null => "other" // warn
case s3 => s3 // warn
}
def f7(s: String | Null): String = s match {
case null => "other"
case null => "other" // warn
case s3: String => s3
case s4 => s4.nn // warn
}
} |
@@ -969,5 +969,11 @@ object SpaceEngine { | |||
|
|||
def checkMatch(m: Match)(using Context): Unit = | |||
if exhaustivityCheckable(m.selector) then checkExhaustivity(m) | |||
if reachabilityCheckable(m.selector) then checkReachability(m) | |||
if reachabilityCheckable(m.selector) then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We discussed with @noti0na1 and agreed that this change should be removed. It is outdated and should no longer be necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -0,0 +1,54 @@ | |||
//> using options -Xfatal-warnings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should go in warn
instead of enabling fatal warnings.
An up-to-date version of #19258 with merge conflicts resolved.