Is there a reason the following code gives warning?


#1

I get the following warning in Intellij Idea (build: 173.3727.127, Kotlin plugin: latest): Kotlin: Unreachable Code for the code (in line 4: return when (a) {):

fun pow(a: Number, b: Int): Number {
    if (b == 0) return 1
    if (b == 1) return a
    return when (a) {
        is Long -> {
            return if (b  % 2 == 0) pow(a * a, b / 2)
            else a * pow(a * a, b / 2) as Long
        }
        is Int -> {
            return if (b  % 2 == 0) pow(a * a, b / 2)
            else a * pow(a * a, b / 2) as Int
        }
        is BigInteger -> {
            return if (b  % 2 == 0) pow(a * a, b / 2)
            else a * pow(a * a, b / 2) as BigInteger
        }
        else -> throw IllegalArgumentException("only Long, Int, BigInteger are supported")
    }
}

The code works fine for Long, Int, and BigInteger as expected.


#2

Problem was solved by removing the redundant return keyword from the cases in the when expression.


#3

This tail recursive implementation will perform better and does not blow up the stack and does not keep repeatedly keep checking the type of the value (hopefully I got the math correct):

fun pow(a: Number, b: Int): Number
{
    tailrec fun pow(a: Int, b: Int, product: Int = 1) : Int
            = when
            {
                b == 0 -> product
                b == 1 -> a * product
                b % 2 == 0 -> pow(a * a, b / 2, product)
                else -> pow(a * a, b / 2, a * product)
            }

    tailrec fun pow(a: Long, b: Int, product: Long = 1L) : Long
            = when
            {
                b == 0 -> product
                b == 1 -> a * product
                b % 2 == 0 -> pow(a * a, b / 2, product)
                else -> pow(a * a, b / 2, a * product)
            }

    tailrec fun pow(a: BigInteger, b: Int, product: BigInteger = BigInteger.ONE) : BigInteger
            = when
            {
                b == 0 -> product
                b == 1 -> a * product
                b % 2 == 0 -> pow(a * a, b / 2, product)
                else -> pow(a * a, b / 2, a * product)
            }

    return when
    {
        b < 0 -> throw IllegalArgumentException("negative exponent not supported")
        a is Long -> pow(a, b)
        a is Int -> pow(a, b)
        a is BigInteger -> pow(a, b)
        else -> throw IllegalArgumentException("only Long, Int, BigInteger are supported")
    }
}