Skip to content

pattern matcher generates illegal isInstanceOf[Null] for nullable parameter of unapply #23243

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
olhotak opened this issue May 22, 2025 · 4 comments · May be fixed by #23288
Open

pattern matcher generates illegal isInstanceOf[Null] for nullable parameter of unapply #23243

olhotak opened this issue May 22, 2025 · 4 comments · May be fixed by #23288

Comments

@olhotak
Copy link
Contributor

olhotak commented May 22, 2025

Compiler version

Scala 3.7.2-RC1-bin-20250520-baac46c-NIGHTLY, JVM (8)

Minimized code

object Extractor:
  def unapply(s: String|Null): Boolean = true
  
class A

def main =
  ("foo": (A|String)) match
    case Extractor() => println("foo matched")
    case _ => println("foo didn't match")

Output

$ scala-cli -S 3.nightly patmat.scala 
Compiling project (Scala 3.7.2-RC1-bin-20250520-baac46c-NIGHTLY, JVM (8))
[error] ./patmat.scala:9:10
[error] class Null cannot be used in runtime type tests
[error]     case Extractor() => println("foo matched")
[error]          ^^^^^^^^^^^
Error compiling project (Scala 3.7.2-RC1-bin-20250520-baac46c-NIGHTLY, JVM (8))

Expectation

Is a nullable type parameter of unapply even allowed?

If not, the error message should point out the unapply method.

If yes, the pattern matcher should not generate an illegal isInstanceOf[Null] and the example should compile.

Note: the issue happens both with and without -Yexplicit-nulls.

Note: a similar unapply appears in the compiler source in dotty.tools.backend.jvm.DottyBackendInterface.DeconstructorCommon.

@olhotak olhotak added itype:bug area:pattern-matching area:nullability stat:needs triage Every issue needs to have an "area" and "itype" label labels May 22, 2025
@olhotak
Copy link
Contributor Author

olhotak commented May 22, 2025

cc @HarrisL2 @SuperCl4sh

@Gedochao Gedochao removed the stat:needs triage Every issue needs to have an "area" and "itype" label label May 23, 2025
@Gedochao
Copy link
Contributor

cc @noti0na1

@SuperCl4sh
Copy link

Hi, would it possible for me to get assigned to this? I believe I've located the cause, but I haven't produced a fix yet.

@som-snytt
Copy link
Contributor

An extractor pattern cannot match the value null. The implementation ensures that the unapply/unapplySeq method is not applied to null.

per spec.

The extractor is fine, but patmat should always do a null check or correct instanceof:

    def f[T <: String | Null](x: T): Unit =
      matchResult2[Unit]:
        {
          case val x3: (x : T) = x
          if (x3 ne null) && X.unapply(x3) then
            return[matchResult2]
              {
                println("foo matched")
              }
           else ()
          return[matchResult2]
            {
              println("foo didn\'t match")
            }
        }
    def g[T <: String | A](x: T): Unit =
      matchResult3[Unit]:
        {
          case val x4: (x : T) = x
          if x4.$isInstanceOf[String] && X.unapply(x4.$asInstanceOf[String])
             then
            return[matchResult3]
              {
                println("foo matched")
              }
           else ()
          return[matchResult3]
            {
              println("foo didn\'t match")
            }
        }

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