Skip to content

Pain point using -Yexplicit-nulls with Regex unapply #14672

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

Open
griggt opened this issue Mar 12, 2022 · 3 comments
Open

Pain point using -Yexplicit-nulls with Regex unapply #14672

griggt opened this issue Mar 12, 2022 · 3 comments

Comments

@griggt
Copy link
Contributor

griggt commented Mar 12, 2022

Compiler version

3.2.0-RC1-bin-20220308-29073f1-NIGHTLY with -Yexplicit-nulls

Minimized code

scala> val Split = "([^#]+)?(?:#(.+)?)?".r
val Split: scala.util.matching.Regex = ([^#]+)?(?:#(.+)?)?

scala> "#foo" match 
     |   case Split(pre, _) if pre != null => println(s"pre=$pre")
     |   case _ => println("no match")
     | 
-- Error: ----------------------------------------------------------------------
2 |  case Split(pre, _) if pre != null => println(s"pre=$pre")
  |                        ^^^^^^^^^^^
  |          Values of types String and Null cannot be compared with == or !=
1 error found

but removing the guard gives:

scala> "#foo" match 
     |   case Split(pre, _) => println(s"pre=$pre")
     |   case _ => println("no match")
     | 
pre=null

Output

As shown above

Expectation

pre is typed as String | Null

Notes

I suspect this is due to #7871?

Is there anything I can do here besides locally importing language.unsafeNulls?

@noti0na1
Copy link
Member

noti0na1 commented Mar 12, 2022

Since pre can really be null, the correct type should be List[String | Null]. But I don't think we can modify the type of standard library easily.

One workaround is to cast pre to nullable and then compare:

"#foo" match {
  case Split(pre, _) if (pre: String | Null) != null => println(s"pre=$pre")
  case _ => println("no match")
}

@smarter
Copy link
Member

smarter commented Mar 12, 2022

But I don't think we can modify the type of standard library easily.

I think a PR to https://github.com/scala/scala/ that added @Nullable annotations where needed in the standard library could be accepted. Though I guess the annoying part here is that we'd need to create yet another Nullable annotation since scala-library doesn't define one and can't start depending on other jars.

@olhotak
Copy link
Contributor

olhotak commented Apr 7, 2022

We could have a @CanEqualNull annotation that allows an expression of a non-null type to be compared against null. We could use it in two places:

  1. In the Scala standard library to annotate types of methods such as scala.util.matching.Regex.unapplySeq without breaking binary compatibility.
  2. A new language.unsafeJava scope that assigns non-null return types to calls to Java-defined methods. Such a scope would allow member accesses on values returned from Java, but would normally break == null comparison for such values. A @CanEqualNull annotation would fix the latter problem.

@noti0na1 what do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants