roc icon indicating copy to clipboard operation
roc copied to clipboard

Compile Panic While Building

Open peacememories opened this issue 3 years ago • 1 comments

While doing advent of code day 4 I ran into a case where the code typechecks, but compiling/running it results in a lengthy panic.

I'm sorry for the lenth of the example, but I do not know enough about the error to be able to properly reduce it.

Code
app "problem4"
    packages { pf: "../roc/examples/cli/cli-platform/main.roc" }
    imports [pf.Stdout, pf.Stderr, pf.Path.{ Path }, pf.Program, pf.File, pf.Task.{ Task, await }, Helpers]
    provides [main] to pf

updateDict : Dict k v, k, (v -> v) -> Dict k v | k has Eq
updateDict = \dict, key, updateFn ->
    dict
    |> Dict.get key
    |> Result.map (\value -> Dict.insert dict key (updateFn value))
    |> Result.withDefault dict

boardSize = 5

Board : Dict U8 { row : Nat, col : Nat }
DrawnNumbers : List U8

parseBoard : Str -> Result Board [InvalidBoard Str]*
parseBoard = \boardStr ->
    lines =
        boardStr
        |> Str.split "\n"

    numbers <- lines
        |> List.mapTry
            (\line ->
                line
                |> Str.split " "
                |> List.dropIf (\elem -> elem == "")
                |> List.mapTry Str.toU8
            )
        |> Result.mapErr (\InvalidNumStr -> InvalidBoard boardStr)
        |> Result.try

    numbers
    |> List.mapWithIndex
        (\list, row ->
            list
            |> List.mapWithIndex
                (\value, col ->
                    { row, col, value })
        )
    |> List.join
    |> List.walk
        Dict.empty
        (\dict, { row, col, value } ->
            dict
            |> Dict.insert value { row, col }
        )
    |> Ok

playBoard : Board, DrawnNumbers -> Result Nat [BoardDidNotFinish]*
playBoard = \board, drawnNumbers ->
    emptyCoords =
        List.range 1 boardSize
        |> List.walk Dict.empty (\state, index -> Dict.insert state index 0)

    initialState = {
        cols: emptyCoords,
        rows: emptyCoords,
        round: 0,
        won: Bool.false
    }

    finalState = drawnNumbers
        |> List.walkUntil
            initialState
            (\state, number ->
                newState =
                    when Dict.get board number is
                        Ok { row, col } ->
                            { state &
                                cols: updateDict state.cols col (\val -> val + 1),
                                rows: updateDict state.rows row (\val -> val + 1),
                                round: state.round + 1,
                            }

                        Err _ ->
                            { state & round: state.round + 1 }

                maxLength =
                    List.join [Dict.values newState.rows, Dict.values newState.cols]
                    |> List.max
                    |> Result.withDefault 0

                if maxLength == boardSize then
                    Break { newState & won: Bool.true }
                else
                    Continue newState
            )

    if finalState.won then
        Ok finalState.round
    else
        Err BoardDidNotFinish

boardScore : Board, DrawnNumbers -> U16
boardScore = \board, drawnNumbers ->
    unchecked =
        board
        |> Dict.keys
        |> List.keepIf (\number -> !(List.contains drawnNumbers number))
        |> List.map Num.toU16
        |> List.sum

    lastDrawn =
        List.last drawnNumbers
        |> Result.withDefault 0
        |> Num.toU16

    unchecked * lastDrawn

getResults : List Board, DrawnNumbers -> List {board: Board, turns: Nat}
getResults = \boards, drawnNumbers ->
    boards
    |> List.keepOks (\board ->
        board
        |> playBoard drawnNumbers
        |> Result.map (\turns -> { board, turns})
        )
    |> List.sortWith
        (\left, right ->
            Num.compare left.turns right.turns  
        )

getWinner : List Board, DrawnNumbers -> Result {board: Board, turns: Nat} [NoBoardsFinished]*
getWinner = \boards, drawnNumbers ->
    getResults boards drawnNumbers
    |> List.first
    |> Result.mapErr (\ListWasEmpty -> NoBoardsFinished)

getLoser : List Board, DrawnNumbers -> Result {board: Board, turns: Nat} [NoBoardsFinished]*
getLoser = \boards, drawnNumbers ->
    getResults boards drawnNumbers
    |> List.last
    |> Result.mapErr (\ListWasEmpty -> NoBoardsFinished)

parseFile : Str -> Result { drawnNumbers : DrawnNumbers, boards : List Board } [InvalidBoard Str, InvalidDrawnNumbers Str, NoDrawnNumbers]*
parseFile = \fileContent ->
    blocks =
        fileContent
        |> Str.split "\n\n"

    firstLine <- List.get blocks 0
        |> Result.mapErr (\OutOfBounds -> NoDrawnNumbers)
        |> Result.try

    drawnNumbers <-
        Str.split firstLine ","
        |> List.mapTry Str.toU8
        |> Result.mapErr (\InvalidNumStr -> InvalidDrawnNumbers firstLine)
        |> Result.try

    boards <-
        List.dropFirst blocks
        |> List.mapTry parseBoard
        |> Result.try

    Ok { drawnNumbers, boards }

main =
    path = Path.fromStr "./problem4.input"

    getWinnerScore = \boards, drawnNumbers ->
        {board: winner, turns} <- Result.try (getWinner boards drawnNumbers)
        numbers = drawnNumbers
            |> List.sublist {start: 0, len: turns}
        Ok (boardScore winner numbers)
    
    getLoserScore = \boards, drawnNumbers ->
        {board: winner, turns} <- Result.try (getLoser boards drawnNumbers)
        numbers = drawnNumbers
            |> List.sublist {start: 0, len: turns}
        Ok (boardScore winner numbers)

    mainTask =
        fileContents <- await (File.readUtf8 path)

        {boards, drawnNumbers} <- parseFile fileContents
            |> Helpers.resultToTask
            |> await

        winnerScore <- getWinnerScore boards drawnNumbers
            |> Result.map Num.toStr
            |> Helpers.resultToTask
            |> await

        loserScore <- getLoserScore boards drawnNumbers
            |> Result.map Num.toStr
            |> Helpers.resultToTask
            |> await

        Stdout.line "Winner: \(winnerScore), Loser: \(loserScore)"

    errorHandling =
        result <- Task.attempt mainTask
        when result is
            Ok {} ->
                Task.succeed {}

            Err (InvalidBoard boardStr) ->
                Stderr.line "Could not read board:\n\(boardStr)"

            Err (InvalidDrawnNumbers numberStr) ->
                Stderr.line "Could not read drawn numbers:\n\(numberStr)"

            Err NoDrawnNumbers ->
                Stderr.line "You need to draw numbers for anyone to win"

            Err NoBoardsFinished ->
                Stderr.line "No boards finished the bingo"

            Err (FileReadErr _ _) | Err (FileReadUtf8Err _ _) ->
                Stderr.line "Could not read file"

    Program.quick errorHandling
Error
thread 'main' panicked at 'internal error: entered unreachable code: symbol/layout `16.IdentId(53)` ProcLayout {
    arguments: [
        Struct {
            field_order_hash: FieldOrderHash(
                11715282875446243786,
            ),
            field_layouts: [
                Builtin(
                    List(
                        Struct {
                            field_order_hash: FieldOrderHash(
                                1,
                            ),
                            field_layouts: [
                                Builtin(
                                    Int(
                                        U64,
                                    ),
                                ),
                                Builtin(
                                    Int(
                                        I64,
                                    ),
                                ),
                            ],
                        },
                    ),
                ),
                Builtin(
                    Int(
                        I64,
                    ),
                ),
                Builtin(
                    List(
                        Struct {
                            field_order_hash: FieldOrderHash(
                                1,
                            ),
                            field_layouts: [
                                Builtin(
                                    Int(
                                        U64,
                                    ),
                                ),
                                Builtin(
                                    Int(
                                        I64,
                                    ),
                                ),
                            ],
                        },
                    ),
                ),
                Builtin(
                    Bool,
                ),
            ],
        },
        Builtin(
            Int(
                U8,
            ),
        ),
        LambdaSet(
            LambdaSet {
                set: [
                    ( 16.53, [Builtin(List(Struct { field_order_hash: FieldOrderHash(1), field_layouts: [Struct { field_order_hash: FieldOrderHash(12820037997967260529), field_layouts: [Builtin(Int(U64)), Builtin(Int(U64))] }, Builtin(Int(U8))] }))]),
                ],
                representation: Interned(
                    21,
                    PhantomData,
                ),
            },
        ),
    ],
    result: Union(
        NonRecursive(
            [
                [
                    Struct {
                        field_order_hash: FieldOrderHash(
                            11715282875446243786,
                        ),
                        field_layouts: [
                            Builtin(
                                List(
                                    Struct {
                                        field_order_hash: FieldOrderHash(
                                            1,
                                        ),
                                        field_layouts: [
                                            Builtin(
                                                Int(
                                                    U64,
                                                ),
                                            ),
                                            Builtin(
                                                Int(
                                                    I64,
                                                ),
                                            ),
                                        ],
                                    },
                                ),
                            ),
                            Builtin(
                                Int(
                                    I64,
                                ),
                            ),
                            Builtin(
                                List(
                                    Struct {
                                        field_order_hash: FieldOrderHash(
                                            1,
                                        ),
                                        field_layouts: [
                                            Builtin(
                                                Int(
                                                    U64,
                                                ),
                                            ),
                                            Builtin(
                                                Int(
                                                    I64,
                                                ),
                                            ),
                                        ],
                                    },
                                ),
                            ),
                            Builtin(
                                Bool,
                            ),
                        ],
                    },
                ],
                [
                    Struct {
                        field_order_hash: FieldOrderHash(
                            11715282875446243786,
                        ),
                        field_layouts: [
                            Builtin(
                                List(
                                    Struct {
                                        field_order_hash: FieldOrderHash(
                                            1,
                                        ),
                                        field_layouts: [
                                            Builtin(
                                                Int(
                                                    U64,
                                                ),
                                            ),
                                            Builtin(
                                                Int(
                                                    I64,
                                                ),
                                            ),
                                        ],
                                    },
                                ),
                            ),
                            Builtin(
                                Int(
                                    I64,
                                ),
                            ),
                            Builtin(
                                List(
                                    Struct {
                                        field_order_hash: FieldOrderHash(
                                            1,
                                        ),
                                        field_layouts: [
                                            Builtin(
                                                Int(
                                                    U64,
                                                ),
                                            ),
                                            Builtin(
                                                Int(
                                                    I64,
                                                ),
                                            ),
                                        ],
                                    },
                                ),
                            ),
                            Builtin(
                                Bool,
                            ),
                        ],
                    },
                ],
            ],
        ),
    ),
    captures_niche: CapturesNiche(
        [
            Builtin(
                List(
                    Struct {
                        field_order_hash: FieldOrderHash(
                            1,
                        ),
                        field_layouts: [
                            Struct {
                                field_order_hash: FieldOrderHash(
                                    12820037997967260529,
                                ),
                                field_layouts: [
                                    Builtin(
                                        Int(
                                            U64,
                                        ),
                                    ),
                                    Builtin(
                                        Int(
                                            U64,
                                        ),
                                    ),
                                ],
                            },
                            Builtin(
                                Int(
                                    U8,
                                ),
                            ),
                        ],
                    },
                ),
            ),
        ],
    ),
} combo must be in DeclarationToIndex', crates/compiler/mono/src/borrow.rs:165:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Side note: the | k has Eq is a new addition that I had to add after I downloaded the latest nightly, so that's probably not the culprit.

peacememories avatar Oct 16 '22 00:10 peacememories

Let's cut this down to a minimal reproduction before attempting to fix the compiler.

ayazhafiz avatar Oct 17 '22 15:10 ayazhafiz

@peacememories do you have the source code to Helpers.roc? I think we need that to reproduce this.

Or, if possible, could you check if this still panics on the latest roc?

ayazhafiz avatar Dec 12 '22 23:12 ayazhafiz

Candidate for closing because not able to reproduce and no minimal failure case?

Ivo-Balbaert avatar Aug 06 '23 15:08 Ivo-Balbaert

Closing as unable to reproduce without Helpers.roc.

lukewilliamboswell avatar Aug 06 '23 21:08 lukewilliamboswell