skiptools / skiptools/skip

Unwrapped inout parameter is treated as optional in Kotlin

Open
#50 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug transpilation
Dominant language
Swift
Stars
3.2k
Forks
106
Avg merge
6d 13h
Merged PRs (30d)
1

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start from the inout parameter handling that produces the shown Kotlin and compare it with the Swift if-let example. Verify the generated Kotlin treats the bound value as non-null, while preserving the optional behavior in the else branch; done when the workaround is no longer needed and the example compiles.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin, swift
Domain
compilers, mobile-dev
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.