Smart cast and java.lang.VerifyError


#1

In Fragment.onActivityCreated() I update the UI with calling this method:

    private fun updateBackground(goalName: String, backgroundId: Int) {
    val backgroundType = defaultSharedPreferences.getString("${goalName}_$BACKGROUND_TYPE", null)
    val background: Any? = when (backgroundType) {
        BackgroundType.IMAGE -> ContextCompat.getDrawable(context!!, backgroundId)
        BackgroundType.COLOR -> ContextCompat.getColor(context!!, backgroundId)
        else -> ContextCompat.getColor(context!!, R.color.default_goal_background)
    }

    val statusBarColor: Int?

    if (background is Drawable) {
        goal_goal_picture_imageview.image = background
        val dominantColor = background.computeDominantColor()
        statusBarColor = if (dominantColor != null) setBrightness(dominantColor, STATUS_BAR_COLOR_COEF) else null
    } else {
        goal_goal_picture_imageview.setColorFilter(background as Int)
        statusBarColor = setBrightness(background, STATUS_BAR_COLOR_COEF)
    }
    
    ...
}

After a successful build my application crashes with error:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.antondokusov.myapp, PID: 21883
java.lang.VerifyError: Verifier rejected class com.antondokusov.myapp.screen.goal.GoalFragment: void com.antondokusov.myapp.screen.goal.GoalFragment.updateBackground(java.lang.String, int) failed to verify: void com.antondokusov.myapp.screen.goal.GoalFragment.updateBackground(java.lang.String, int): [0xB3] register v3 has type Precise Reference: java.lang.Integer but expected Reference: android.graphics.drawable.Drawable (declaration of 'com.antondokusov.myapp.screen.goal.GoalFragment' appears in /data/app/com.antondokusov.myapp-5m29PkDspqZUiHFK-5ZtvA==/split_lib_slice_0_apk.apk)
    at com.antondokusov.myapp.util.MainActivity.onCreate(MainActivity.kt:30)

In MainActivity.onCreate() I just call the FragmentManager for adding the GoalFragment to the container.

So none of the fragment’s code executed.
I tried to rebuild the project (didn’t help), remove calls of the method (nope), remove the method itself (it helps, of course) and remove the method’s body only (it helps too). I commented and uncommented lines of code for a while and found the reason:

goal_goal_picture_imageview.image = background

needs to be replaced by

goal_goal_picture_imageview.image = background as Drawable

Android Studio tells that “no cast needed” and background is smart cast to Drawable but without the explicit denote the app doesn’t run properly. Is it Kotlin compiler’s problem or my mistake?

Kotlin Bytecode (there is no helpful info for me at all but you might be interested in it):

goal_goal_picture_imageview.image = background

L18
 LINENUMBER 97 L18
 ALOAD 0
 GETSTATIC com/antondokusov/myapp/R$id.goal_goal_picture_imageview : I
 INVOKEVIRTUAL com/antondokusov/myapp/screen/goal/GoalFragment._$_findCachedViewById (I)Landroid/view/View;
 CHECKCAST android/widget/ImageView
 DUP
 LDC "goal_goal_picture_imageview"
 INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkExpressionValueIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
 ASTORE 6
L19
 LINENUMBER 162 L19
 ALOAD 6
 ALOAD 4
 INVOKEVIRTUAL android/widget/ImageView.setImageDrawable (Landroid/graphics/drawable/Drawable;)V


goal_goal_picture_imageview.image = background as Drawable

L18
 LINENUMBER 97 L18
 ALOAD 0
 GETSTATIC com/antondokusov/myapp/R$id.goal_goal_picture_imageview : I
 INVOKEVIRTUAL com/antondokusov/myapp/screen/goal/GoalFragment._$_findCachedViewById (I)Landroid/view/View;
 CHECKCAST android/widget/ImageView
 DUP
 LDC "goal_goal_picture_imageview"
 INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkExpressionValueIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
 ALOAD 4
L19
 CHECKCAST android/graphics/drawable/Drawable
 ASTORE 7
 ASTORE 6
L20
 LINENUMBER 162 L20
 ALOAD 6
 ALOAD 7
 INVOKEVIRTUAL android/widget/ImageView.setImageDrawable (Landroid/graphics/drawable/Drawable;)V

I used for build Kotlin 1.2.31, 1.2.40 and 1.2.41.
Thanks in advance!