skiptools / skiptools/skip

Skip Lite: Transpiling error on `guard case` (same with `let case`)

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

Nobody has claimed this yet.

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

Description

Skip Lite has a problem with guard case under specific circumastances, the transpiler producing errornous code (without notice)

import Foundation

enum Types {
    case string(String)
    case int(Int)
}

extension Types: Decodable {
    init (from decoder: Decoder) throws {
        // just so that SKIP does not complain about not being able to synthesize
        self = .string("some string")
    }
}

func run () throws {
    let succeeding1: Types = .string("I'm a string")
    guard case .string(let str) = succeeding1 else { fatalError("not a string") }
    
    let succeeding2: Types = try JSONDecoder().decode(Types.self, from: "\"I'm a string\"".data(using: .utf8)!)
    guard case .string(let str) = succeeding2 else { fatalError("not a string") }
    
    let failing = try JSONDecoder().decode(Types.self, from: "\"I'm a string\"".data(using: .utf8)!)
    guard case Types.string(let str) = failing else { fatalError("not a string") }
}

run transpiles to

internal fun run() {
    val succeeding1: Types = Types.string("I'm a string")
    if (succeeding1 !is Types.StringCase) {
        fatalError("not a string")
    }
    val str_0 = succeeding1.associated0

    val succeeding2: Types = JSONDecoder().decode(Types::class, from = "\"I'm a string\"".data(using = StringEncoding.utf8)!!)
    if (succeeding2 !is Types.StringCase) {
        fatalError("not a string")
    }
    val str_1 = succeeding2.associated0

    // the following does not work: Skip is unable to determine the owning type for member \'string\'
    // guard case .string(let string) = failing else { fatalError("not a string") }
    val failing = JSONDecoder().decode(Types::class, from = "\"I'm a string\"".data(using = StringEncoding.utf8)!!)
    if (failing != Types.string) {
        fatalError("not a string")
    }
    val str_2 = failing.associated0
}

note: succeeding !is Types.StringCase while failing != Types.string which produces the (first) error

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

The issue provides no file or test path; start by running the shown guard-case reproducer through Skip Lite and inspecting the generated Kotlin. Compare the qualified and unqualified enum-case output, then add or update coverage so both forms transpile without the erroneous comparison and associated-value handling shown.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin, swift
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 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.