skip icon indicating copy to clipboard operation
skip copied to clipboard

Unwrapped inout parameter is treated as optional in Kotlin

Open marcprux opened this issue 2 years ago • 0 comments

When an inout parameter holds an optional value, accessing the value in an if let statement doesn't treat it as being unwrapped on the Kotlin side:

    /// Prepares the given SQL statement, caching and re-using it into the given statement handle.
    func prepare(sql: String, into statement: inout SQLStatement?) throws -> SQLStatement {
        if let stmnt = statement {
            return stmnt // already cached
        } else {
            let stmnt = try ctx.prepare(sql: sql)
            statement = stmnt // save to the cache
            return stmnt
        }
    }

The Kotlin compile error is:

Type mismatch: inferred type is SQLStatement? but SQLStatement was expected

The generated Kotlin looks like this:

    internal open fun prepare(sql: String, into: InOut<SQLStatement?>): SQLStatement {
        val statement = into
        if (statement.value != null) {
            val stmnt = statement.value
            return stmnt // already cached
        } else {
            val stmnt = ctx.prepare(sql = sql)
            statement.value = stmnt // save to the cache
            return stmnt
        }
    }

The workaround is to force-unwrap the inout on the Kotlin side:

    /// Prepares the given SQL statement, caching and re-using it into the given statement handle.
    func prepare(sql: String, into statement: inout SQLStatement?) throws -> SQLStatement {
        if let stmnt = statement {
            #if SKIP
            return stmnt! // Skip treats this as an optional
            #else
            return stmnt // already cached
            #endif
        } else {
            let stmnt = try ctx.prepare(sql: sql)
            statement = stmnt // save to the cache
            return stmnt
        }
    }
Screenshot 2023-11-19 at 17 31 42

marcprux avatar Nov 19 '23 22:11 marcprux