Skip to content

Improve filter for Kotlin 1.6.20 when-expressions with String #1295

@Godin

Description

@Godin

Currently execution of

mvn clean package -Dkotlin.version=1.6.20-RC2

leads to

Failed tests:
  execute_assertions_in_comments(org.jacoco.core.test.validation.kotlin.KotlinWhenExpressionTest): Instructions (KotlinWhenExpressionTarget.kt:67) expected:<[FUL]LY_COVERED> but was:<[PART]LY_COVERED>

For the following Example.kt (test case that was added in #1156)

private fun example(p: String): Int = when (p) {
    "c" -> 1 // first case has biggest hashCode value and there is no other cases with the same hashCode
    "b" -> 2
    "\u0000b" -> 3
    "a" -> 4
    "\u0000a" -> 5
    else -> 6
}

execution of

kotlin/bin/kotlinc Example.kt -d classes
javap -v -p classes/ExampleKt.class

using Kotlin compiler version 1.6.10 produces

  private static final int example(java.lang.String);
    descriptor: (Ljava/lang/String;)I
    flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL
    Code:
      stack=2, locals=2, args_size=1
         0: aload_0
         1: astore_1
         2: aload_1
         3: invokevirtual #12                 // Method java/lang/String.hashCode:()I
         6: tableswitch   { // 97 to 99
                      97: 32
                      98: 53
                      99: 74
                 default: 106
            }
        32: aload_1
        33: ldc           #14                 // String a
        35: invokevirtual #18                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        38: ifne          98
        41: aload_1
        42: ldc           #20                 // String \u0000a
        44: invokevirtual #18                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        47: ifne          102
        50: goto          106
        53: aload_1
        54: ldc           #22                 // String b
        56: invokevirtual #18                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        59: ifne          90
        62: aload_1
        63: ldc           #24                 // String \u0000b
        65: invokevirtual #18                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        68: ifne          94
        71: goto          106
        74: aload_1
        75: ldc           #26                 // String c
        77: invokevirtual #18                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        80: ifne          86
        83: goto          106
        86: iconst_1
        87: goto          108
        90: iconst_2
        91: goto          108
        94: iconst_3
        95: goto          108
        98: iconst_4
        99: goto          108
       102: iconst_5
       103: goto          108
       106: bipush        6
       108: ireturn

and this bytecode is recognized by https://github.com/jacoco/jacoco/blob/v0.8.7/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilter.java#L32

whereas using Kotlin compiler versions 1.6.20-M1, 1.6.20-RC and 1.6.20-RC2 produces

  private static final int example(java.lang.String);
    descriptor: (Ljava/lang/String;)I
    flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL
    Code:
      stack=2, locals=2, args_size=1
         0: aload_0
         1: astore_1
         2: aload_1
         3: invokevirtual #12                 // Method java/lang/String.hashCode:()I
         6: tableswitch   { // 97 to 99
                      97: 32
                      98: 53
                      99: 74
                 default: 103
            }
        32: aload_1
        33: ldc           #14                 // String a
        35: invokevirtual #18                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        38: ifne          95
        41: aload_1
        42: ldc           #20                 // String \u0000a
        44: invokevirtual #18                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        47: ifne          99
        50: goto          103
        53: aload_1
        54: ldc           #22                 // String b
        56: invokevirtual #18                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        59: ifne          87
        62: aload_1
        63: ldc           #24                 // String \u0000b
        65: invokevirtual #18                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        68: ifne          91
        71: goto          103
        74: aload_1
        75: ldc           #26                 // String c
        77: invokevirtual #18                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        80: ifeq          103
        83: iconst_1
        84: goto          105
        87: iconst_2
        88: goto          105
        91: iconst_3
        92: goto          105
        95: iconst_4
        96: goto          105
        99: iconst_5
       100: goto          105
       103: bipush        6
       105: ireturn

Here is most significant part of diff

-        80: ifne          86
-        83: goto          106
-        86: iconst_1
+        80: ifeq          103
+        83: iconst_1

This relates to the following change in Kotlin compiler - JetBrains/kotlin@1c1b954

Metadata

Metadata

Assignees

Type

No type

Projects

Status

To Do

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions