roc-lang / roc

A fast, friendly, functional language.
https://roc-lang.org
Universal Permissive License v1.0
4.46k stars 313 forks source link

Compiler bug: `An internal compiler expectation was broken. This is definitely a compiler bug.` #6372

Open imclerran opened 10 months ago

imclerran commented 10 months ago

When building my roc code, (see below) I receive an error message as in the issue title:

An internal compiler expectation was broken.
This is definitely a compiler bug.
Please file an issue here: https://github.com/roc-lang/roc/issues/new/choose
thread '<unnamed>' panicked at 'Alias `4.IdentId(83)` not registered in delayed aliases! [(`40.IdentId(0)`, Index(196), DelayedAliasVariables { start: 0, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 5 }, Structural), (`40.IdentId(3)`, Index(224), DelayedAliasVariables { start: 5, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`40.IdentId(8)`, Index(228), DelayedAliasVariables { start: 6, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`40.IdentId(7)`, Index(233), DelayedAliasVariables { start: 7, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`12.IdentId(0)`, Index(244), DelayedAliasVariables { start: 8, type_variables_len: 1, lambda_set_variables_len: 1, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Opaque), (`40.IdentId(2)`, Index(251), DelayedAliasVariables { start: 10, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`41.IdentId(0)`, Index(253), DelayedAliasVariables { start: 11, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`40.IdentId(4)`, Index(257), DelayedAliasVariables { start: 12, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`15.IdentId(1)`, Index(260), DelayedAliasVariables { start: 13, type_variables_len: 1, lambda_set_variables_len: 1, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Opaque), (`13.IdentId(0)`, Index(264), DelayedAliasVariables { start: 15, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`42.IdentId(0)`, Index(266), DelayedAliasVariables { start: 16, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`43.IdentId(0)`, Index(268), DelayedAliasVariables { start: 17, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Opaque), (`15.IdentId(3)`, Index(269), DelayedAliasVariables { start: 17, type_variables_len: 3, lambda_set_variables_len: 2, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Structural), (`43.IdentId(6)`, Index(279), DelayedAliasVariables { start: 22, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 2 }, Structural), (`13.IdentId(1)`, Index(289), DelayedAliasVariables { start: 24, type_variables_len: 1, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 2 }, Structural), (`17.IdentId(1)`, Index(299), DelayedAliasVariables { start: 27, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 1, infer_ext_in_output_variables_len: 1 }, Structural), (`41.IdentId(1)`, Index(306), DelayedAliasVariables { start: 29, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`46.IdentId(1)`, Index(310), DelayedAliasVariables { start: 30, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`10.IdentId(0)`, Index(314), DelayedAliasVariables { start: 31, type_variables_len: 1, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Opaque), (`40.IdentId(5)`, Index(317), DelayedAliasVariables { start: 32, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`39.IdentId(0)`, Index(322), DelayedAliasVariables { start: 33, type_variables_len: 2, lambda_set_variables_len: 1, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Opaque), (`44.IdentId(1)`, Index(328), DelayedAliasVariables { start: 36, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 2 }, Structural), (`44.IdentId(2)`, Index(342), DelayedAliasVariables { start: 38, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`37.IdentId(0)`, Index(346), DelayedAliasVariables { start: 39, type_variables_len: 2, lambda_set_variables_len: 1, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Structural), (`9.IdentId(32)`, Index(350), DelayedAliasVariables { start: 42, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Opaque), (`15.IdentId(35)`, Index(351), DelayedAliasVariables { start: 42, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Opaque), (`47.IdentId(1)`, Index(353), DelayedAliasVariables { start: 42, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`9.IdentId(0)`, Index(360), DelayedAliasVariables { start: 43, type_variables_len: 2, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Opaque), (`42.IdentId(1)`, Index(373), DelayedAliasVariables { start: 45, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 2 }, Structural), (`38.IdentId(0)`, Index(379), DelayedAliasVariables { start: 47, type_variables_len: 1, lambda_set_variables_len: 1, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Opaque), (`44.IdentId(0)`, Index(383), DelayedAliasVariables { start: 49, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Structural), (`15.IdentId(4)`, Index(390), DelayedAliasVariables { start: 49, type_variables_len: 4, lambda_set_variables_len: 2, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Structural), (`46.IdentId(0)`, Index(401), DelayedAliasVariables { start: 55, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`40.IdentId(1)`, Index(403), DelayedAliasVariables { start: 56, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 3 }, Structural), (`43.IdentId(1)`, Index(436), DelayedAliasVariables { start: 59, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`43.IdentId(4)`, Index(440), DelayedAliasVariables { start: 60, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 2 }, Structural), (`40.IdentId(6)`, Index(448), DelayedAliasVariables { start: 62, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 2 }, Structural), (`17.IdentId(2)`, Index(455), DelayedAliasVariables { start: 64, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 2 }, Structural), (`9.IdentId(31)`, Index(456), DelayedAliasVariables { start: 66, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Structural), (`43.IdentId(3)`, Index(459), DelayedAliasVariables { start: 66, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 2 }, Structural), (`43.IdentId(2)`, Index(469), DelayedAliasVariables { start: 68, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural), (`13.IdentId(2)`, Index(473), DelayedAliasVariables { start: 69, type_variables_len: 2, lambda_set_variables_len: 1, recursion_variables_len: 0, infer_ext_in_output_variables_len: 2 }, Opaque), (`47.IdentId(0)`, Index(492), DelayedAliasVariables { start: 74, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Opaque), (`9.IdentId(33)`, Index(501), DelayedAliasVariables { start: 75, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Opaque), (`45.IdentId(0)`, Index(504), DelayedAliasVariables { start: 75, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Opaque), (`46.IdentId(2)`, Index(510), DelayedAliasVariables { start: 75, type_variables_len: 1, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 0 }, Structural), (`43.IdentId(5)`, Index(513), DelayedAliasVariables { start: 76, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 2 }, Structural), (`46.IdentId(3)`, Index(523), DelayedAliasVariables { start: 78, type_variables_len: 0, lambda_set_variables_len: 0, recursion_variables_len: 0, infer_ext_in_output_variables_len: 1 }, Structural)]', crates/compiler/solve/src/aliases.rs:250:25

My stack trace is as follows:

stack backtrace:
   0:        0x105793c00 - __mh_execute_header
   1:        0x104d4bc2c - __mh_execute_header
   2:        0x10578fa28 - __mh_execute_header
   3:        0x105793a18 - __mh_execute_header
   4:        0x105797754 - __mh_execute_header
   5:        0x105797500 - __mh_execute_header
   6:        0x105797d38 - __mh_execute_header
   7:        0x105797b24 - __mh_execute_header
   8:        0x1057966c0 - __mh_execute_header
   9:        0x1057978d8 - __mh_execute_header
  10:        0x1081a9570 - __ZN4llvm15SmallVectorBaseIyE8grow_podEPvmm
  11:        0x105693284 - __mh_execute_header
  12:        0x10569b0e0 - __mh_execute_header
  13:        0x105696a40 - __mh_execute_header
  14:        0x10568d4d0 - __mh_execute_header
  15:        0x1056814ec - __mh_execute_header
  16:        0x1056806f0 - __mh_execute_header
  17:        0x10567f4d8 - __mh_execute_header
  18:        0x105320984 - __mh_execute_header
  19:        0x105324158 - __mh_execute_header
  20:        0x1052bece0 - __mh_execute_header
  21:        0x1052baf58 - __mh_execute_header
  22:        0x1052bdfc8 - __mh_execute_header
  23:        0x10579cb2c - __mh_execute_header
  24:        0x183ec2034 - __pthread_joiner_wake

The roc code I am building is below. I know that it has some errors in the code, which previously prevented compiling. I made a one word change to the code to fix one of my errors, specifically changing the type of listToTreeRecur from listToTreeRecur : List Str, I32 -> NodeOrNull to listToTreeRecur : List Str, Natural -> NodeOrNull, after which I received the error above. Here is my full code:

app "leafsimilar"
    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" }
    imports [pf.Stdout]
    provides [main] to pf

# Type alias for a binary tree node
# NodeOrNull is a tag which may have a payload which is another node
# If the NodeOrNull does not have a node payload, the child is considered null
NodeOrNull: [Child Node, Null]
Node : {val : I64, lhs : NodeOrNull, rhs : NodeOrNull}

## Convert a boolean value to a string representation
boolToStr : Bool -> Str
boolToStr = \val ->
    if val == Bool.true then "true"
    else "false"

## Check if a node has a child on the right hand side
hasRhs : Node -> Bool
hasRhs = \ node ->
    when node.rhs is
        Child _ -> Bool.true
        Null -> Bool.false

## Check if a node has a child on the left hand side
hasLhs : Node -> Bool
hasLhs = \ node ->
    when node.lhs is
        Child _ -> Bool.true
        Null -> Bool.false

## Convert a list of string represented values (ordered by level) into a binary tree
## values may be a string represented integer, or "null"
listToTree : List Str -> NodeOrNull
listToTree = \lst -> listToTreeRecur lst 0

listToTreeRecur : List Str, Natural -> NodeOrNull
listToTreeRecur = \lst, index -> 
    if (List.len lst) <= index then Null
    else
        strVal = List.get lst index
        if strVal == "null" then
            Null
        else
            val = Str.toI64 (List.get lst index)
            rhs = listToTreeRecur lst (index * 2 + 1)
            lhs = listToTreeRecur lst (index * 2 + 2)
            {val, rhs, lhs}

root = {val: 0, lhs: Null, rhs: Null}

treeList = ["0", "1", "null"]

tree = listToTree treeList

# root has no children, so hasRhs should return false
main = Stdout.line "\(boolToStr (hasRhs root))"

Prior to changing the I32 to Natural, this was the output from roc run LeafSimilar.roc (note that thread main still panics):

── CYCLIC ALIAS ────────────────────────────────────────────── LeafSimilar.roc ─

The Node alias is self-recursive in an invalid way:

10│  Node : {val : I64, lhs : NodeOrNull, rhs : NodeOrNull}
     ^^^^

Recursion in aliases is only allowed if recursion happens behind a
tagged union, at least one variant of which is not recursive.

── TYPE MISMATCH ───────────────────────────────────────────── LeafSimilar.roc ─

This 2nd argument to <= has an unexpected type:

43│      if (List.len lst) <= index then Null
                              ^^^^^

This index value is a:

    I32

But <= needs its 2nd argument to be:

    Int Natural

── TYPE MISMATCH ───────────────────────────────────────────── LeafSimilar.roc ─

This 2nd argument to == has an unexpected type:

46│          if strVal == "null" then
                          ^^^^^^

The argument is a string of type:

    Str

But == needs its 2nd argument to be:

    [
        Err [OutOfBounds],
        Ok Str,
    ]

── TYPE MISMATCH ───────────────────────────────────────────── LeafSimilar.roc ─

This 1st argument to toI64 has an unexpected type:

49│              val = Str.toI64 (List.get lst index)
                                  ^^^^^^^^^^^^^^^^^^

This get call produces:

    Result Str [OutOfBounds]

But toI64 needs its 1st argument to be:

    Str

── TYPE MISMATCH ───────────────────────────────────────────── LeafSimilar.roc ─

This if has an else branch with a different type from its then branch:

52│>              {val, rhs, lhs}

The else branch is a record of type:

    {
        lhs : NodeOrNull,
        rhs : NodeOrNull,
        val : Result (Int Signed64) [InvalidNumStr],
    }

but the then branch has the type:

    [
        Child Node,
        Null,
    ] as a

All branches in an if must have the same type!

────────────────────────────────────────────────────────────────────────────────

thread 'main' panicked at 'Error in alias analysis: error in module ModName("UserApp"), function definition FuncName("mainForHost"), definition of value binding ValueId(4): could not find func in module ModName("UserApp") with name FuncName("$\x00\x00\x00\x00\x00\x00\x00z\x87\xceV\x11\xaaYs")', crates/compiler/gen_llvm/src/llvm/build.rs:5743:19

with the following backtrace:

stack backtrace:
   0:        0x100d8fc00 - __mh_execute_header
   1:        0x100347c2c - __mh_execute_header
   2:        0x100d8ba28 - __mh_execute_header
   3:        0x100d8fa18 - __mh_execute_header
   4:        0x100d93754 - __mh_execute_header
   5:        0x100d93500 - __mh_execute_header
   6:        0x100d93d38 - __mh_execute_header
   7:        0x100d93b24 - __mh_execute_header
   8:        0x100d926c0 - __mh_execute_header
   9:        0x100d938d8 - __mh_execute_header
  10:        0x1037a5570 - __ZN4llvm15SmallVectorBaseIyE8grow_podEPvmm
  11:        0x1007ae270 - __mh_execute_header
  12:        0x1007a8b60 - __mh_execute_header
  13:        0x1004feb34 - __mh_execute_header
  14:        0x100502564 - __mh_execute_header
  15:        0x100500fd0 - __mh_execute_header
  16:        0x1005c6abc - __mh_execute_header
  17:        0x1004d4060 - __mh_execute_header
  18:        0x1004ca2b4 - __mh_execute_header
  19:        0x1004ca2d8 - __mh_execute_header
  20:        0x100d84880 - __mh_execute_header
  21:        0x1004d7404 - __mh_execute_header
imclerran commented 10 months ago

Oh, and my Roc version:

roc nightly pre-release, built from commit 4569770c82c on Fri Dec 29 09:12:45 UTC 2023
imclerran commented 10 months ago

I cleaned up my code to resolve other compile blocking errors in my own code, and reduced my errors down to two: 1) CYCLIC ALIAS - Node : {val : I64, lhs : NodeOrNull, rhs : NodeOrNull} 2) TYPE MISMATCH - if (List.len lst) <= index then Null - This index value is a: U32 But <= needs its 2nd argument to be: Int Natural

My understanding from this conversation is that the cyclic alias error is a long standing bug with recursive types #5119, so I am unable to resolve it.

The compiler error produced above continues to occur if I change the type of index from U32 to Int Natural.

My updated code to reduce the errors in my code is below:

app "leafsimilar"
    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" }
    imports [pf.Stdout]
    provides [main] to pf

## Type Aliases to define binary tree nodes
NodeOrNull: [Child Node, Null]
Node : {val : I64, lhs : NodeOrNull, rhs : NodeOrNull}

## Convert a boolean value to a string representation
boolToStr : Bool -> Str
boolToStr = \val ->
    if val == Bool.true then "true"
    else "false"

## Check if a node has a child on the right hand side
hasRhs : Node -> Bool
hasRhs = \ node ->
    when node.rhs is
        Child _ -> Bool.true
        Null -> Bool.false

## Check if a node has a child on the left hand side
hasLhs : Node -> Bool
hasLhs = \ node ->
    when node.lhs is
        Child _ -> Bool.true
        Null -> Bool.false

## Convert a list of string represented values (ordered by level) into a binary tree
## values may be a string represented integer, or "null"
listToTree : List Str -> NodeOrNull
listToTree = \lst -> listToTreeRecur lst 0

listToTreeRecur : List Str, Int Natural -> NodeOrNull
listToTreeRecur = \lst, index -> 
    if (List.len lst) <= index then Null
    else
        strVal = 
            when List.get lst index is
                Ok str -> str
                Err _ -> ""
        if strVal == "null" then Null
        else

            val = 
                when Str.toI64 (strVal) is
                    Ok num -> num
                    Err InvalidNumStr -> 0
            rhs = listToTreeRecur lst (index * 2 + 1)
            lhs = listToTreeRecur lst (index * 2 + 2)
            Child {val, rhs, lhs}

root = {val: 0, lhs: Null, rhs: Null}

treeList = ["0", "1", "null"]

tree = listToTree treeList

# root has no children, so hasRhs should return false
main = Stdout.line "\(boolToStr (hasRhs root))"