question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Missed match on Array(1L) in Scala 3.1.1

See original GitHub issue

Observation

Consider the following code:

object MatchTest { 
  val a: Array[Long] = Array(1L)

  def test(x: Any) = x match { 
    case Array(i: Long) => println("Success!")
    case _              => println("Failure!") }

  def main(args: Array[String]): Unit = test(a) }

When run under Scala 2.13.8 this produces Success whereas under Scala 3.1.1 it produces Failure. For the latter it does not matter if the compiler option -source:3.0-migration is used.

Expectation

Same behaviour under both versions or (at least) a warning that the match will fail. Current situation significantly changes runtime behaviour after migrating projects from Scala 2 to Scala 3.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:3
  • Comments:9 (6 by maintainers)

github_iconTop GitHub Comments

4reactions
som-snyttcommented, Mar 15, 2022
Welcome to Scala 3.1.3-RC1-bin-SNAPSHOT-git-5fcfeec (17.0.2, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.

scala> (Array(42L): Any) match { case Array(x: Long) => x }
scala.MatchError: [J@75add13c (of class [J)
  ... 33 elided

scala> Array(42L) match { case Array(x: Long) => x }
val res1: Long = 42
1reaction
smartercommented, Mar 18, 2022

I think the problem is with the definition of Array.unapplySeq, if I tweak it like this:

diff --git src/library/scala/Array.scala src/library/scala/Array.scala
index 14cdabd385..a64ae3cb8c 100644
--- src/library/scala/Array.scala
+++ src/library/scala/Array.scala
@@ -574,9 +574,9 @@ object Array {
    *  @param x the selector value
    *  @return  sequence wrapped in a [[scala.Some]], if `x` is an Array, otherwise `None`
    */
-  def unapplySeq[T](x: Array[T]): UnapplySeqWrapper[T] = new UnapplySeqWrapper(x)
+  def unapplySeq[T](x: Array[? <: T]): UnapplySeqWrapper[T] = new UnapplySeqWrapper(x)

-  final class UnapplySeqWrapper[T](private val a: Array[T]) extends AnyVal {
+  final class UnapplySeqWrapper[T](private val a: Array[? <: T]) extends AnyVal {
     def isEmpty: false = false
     def get: UnapplySeqWrapper[T] = this
     def lengthCompare(len: Int): Int = a.lengthCompare(len)

Then the pattern match succeeds. Otherwise, depending on how unapplySeq is instantiated, we’ll end up matching either all arrays or only arrays of objects, because Array[Any] erases to Object[]. Note that the behavior of Scala 2 here seems to be a straight-up bug: if I look at the generated tree it tries to do an isInstanceOf check on Array[T] but there is no T in scope (as pointed out by -Ycheck:pat), but luckily for Scala 2, it happens to erase this malformed type to Object so the check succeeds.

I believe this would be a binary-compatible change, so there’s a chance we could just apply this diff in the Scala 2 standard library.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Breaking match change from Scala 2 to 3 that is too silent
Consider the following code: object MatchTest { val a: Array[Long] = Array(1L) def test(x: Any) = x match { case Array(i: Long) ...
Read more >
Pattern matching on arrays doesn't warn for missing cases
The match in this case is exhaustive because unapplying a NonEmptySeq will always produce at least one value, but the compiler can't see...
Read more >
Spark 3.1.1 ScalaDoc - org.apache.spark.sql.functions
Merge two given arrays, element-wise, into a single array using a function.
Read more >
Querydsl Reference Guide
3.1.1. Complex predicates; 3.1.2. Dynamic expressions; 3.1.3. ... imports, Array of java imports added to generated query classes: com.bar for package ...
Read more >
org.apache.spark.sql.execution.ui.SQLAppStatusListener ...
SQLAppStatusListener.scala maven / gradle build tool code. ... Group: com.github.immuta.hadoop ➦ Artifact: spark-sql_2.12 ➦ Version: 3.1.1-hadoop-2.7.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found