Skip to content

Pattern matching creates array types that end up with needless indirection through ScalaRuntime #528

Closed
scala/scala
#6876
@retronym

Description

@retronym
scala> class ArrayLength { def test[T](a: Array[T]) = a match { case x: Array[AnyRef] => x.length }}
defined class ArrayLength

scala> :javap -c ArrayLength#test
  public <T> int test(java.lang.Object);
    Code:
       0: aload_1
       1: astore_3
       2: aload_3
       3: instanceof    #18                 // class "[Ljava/lang/Object;"
       6: ifeq          27
       9: aload_3
      10: checkcast     #18                 // class "[Ljava/lang/Object;"
      13: astore        4
      15: getstatic     #24                 // Field scala/runtime/ScalaRunTime$.MODULE$:Lscala/runtime/ScalaRunTime$;
      18: aload         4
      20: invokevirtual #27                 // Method scala/runtime/ScalaRunTime$.array_length:(Ljava/lang/Object;)I
      23: istore_2
      24: goto          39
      27: goto          30
      30: new           #29                 // class scala/MatchError
      33: dup
      34: aload_3
      35: invokespecial #33                 // Method scala/MatchError."<init>":(Ljava/lang/Object;)V
      38: athrow
      39: iload_2
      40: ireturn

Workaround is to upcast:


scala> class ArrayLength1 { def test[T](a: Array[T]) = a match { case x: Array[AnyRef] => (x: Array[AnyRef]).length }}
defined class ArrayLength1

scala> :javap -c ArrayLength1#test
  public <T> int test(java.lang.Object);
    Code:
       0: aload_1
       1: astore_3
       2: aload_3
       3: instanceof    #18                 // class "[Ljava/lang/Object;"
       6: ifeq          22
       9: aload_3
      10: checkcast     #18                 // class "[Ljava/lang/Object;"
      13: astore        4
      15: aload         4
      17: arraylength
      18: istore_2
      19: goto          34
      22: goto          25
      25: new           #20                 // class scala/MatchError
      28: dup
      29: aload_3
      30: invokespecial #24                 // Method scala/MatchError."<init>":(Ljava/lang/Object;)V
      33: athrow
      34: iload_2
      35: ireturn

The proper fix would be in https://github.com/scala/scala/blob/179f9a97f29319b29f74a61e02d0a6e87114bac0/src/reflect/scala/reflect/internal/transform/Erasure.scala#L61

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions