Stream: bugs

Topic: Segfault and a few missing functions


view this post on Zulip Aurélien Geron (Dec 04 2025 at 00:19):

Hi there,
I'm still trying to get AoC 2025 Day 01 to work.
I was missing List.split_on and List.map_try so I tried to implement them.
It took me a while but I managed to have zero compilation error or warning. However, I'm getting a segfault now:

Here's my full program:

app [main!] { pf: platform "https://github.com/lukewilliamboswell/roc-platform-template-zig/releases/download/0.3/98T93wthPgoBRLYtPTT4RBBsQunrfDG94gihPf1zYYmE.tar.zst" }

import pf.Stdout

data =
    \\L50
    \\L12
    \\R13
    \\L1
    \\L5
    \\R5


parse_instruction: List(U8) -> Try(I32, _)
parse_instruction = |chars| {
    match chars {
        [] => Err(ParsingError)
        [c, ..rest] => {
            num_str = Str.from_utf8(rest)?
            num = I32.from_str(num_str)?
            if c == 'L' { Ok(-num) } else { Ok(num) }
        }
    }
}

count_zeroes: List(I32), I32, U32 -> U32
count_zeroes = |instructions, pos, count| {
    match instructions {
        [] => count
        [inst, ..rest] => {
            new_pos = pos + inst
            new_count =
                if new_pos % 100 == 0
                    count + 1
                else
                    count
            rest->count_zeroes(new_pos, new_count)
        }
    }
}

split_on: List(a), a -> List(List(a)) where [a.is_eq : a, a -> Bool]
split_on = |elements, delimiter| {
    help = |remaining, chunks, current_chunk| {
        match remaining {
            [] => chunks.append(current_chunk)
            [x, ..rest] => {
                if x == delimiter {
                    help(rest, chunks.append(current_chunk), [])
                } else {
                    help(rest, chunks, current_chunk.append(x))
                }
            }
        }
    }
    help(elements, [], [])
}

map_try: List(a), (a -> Try(b, c)) -> Try(List(b), c)
map_try = |list, to_result_fun| {
    list->walk_try(
        [],
        |state, elem| {
            match to_result_fun(elem) {
                Ok(ok) => Ok(state->List.append(ok))
                Err(b) => Err(b)
            }
        }
    )
}

walk_try: List(a), s, (s, a -> Try(s, c)) -> Try(s, c)
walk_try = |list, init, func| {
    match list {
        [] => { Ok(init) }
        [val, ..rest] => {
            maybe_state = func(init, val)
            match maybe_state {
                Ok(state) => walk_try(rest, state, func)
                Err(b) => Err(b)
            }
        }
    }
}

main!: List Str -> Try({}, Exit)
main! = |_args| {
    maybe_instructions = data.to_utf8()->split_on('\n')->map_try(parse_instruction)
    match maybe_instructions {
        Ok(instructions) => {
            result1 = instructions->count_zeroes(50, 0)
            Stdout.line!(result1.to_str())
            Ok({})
        }
        _ => Err(Exit(1))
    }
}

Here's the segfault:

error: Child process /Users/ageron/Library/Caches/roc/e59c636351ad64c25ba81dca340f7248/temp/roc-tmp-9Tj9smFRS15c5UvOO30epYt9BZ2CYQ9G/roc_run_994723065 killed by signal: 11
error: Child process crashed with segmentation fault (SIGSEGV)

I'm running the latest code compiled from source (Roc compiler version debug-b578eea3).

Thanks for your help!

view this post on Zulip Luke Boswell (Dec 04 2025 at 00:24):

Is that type annotation on main correct? main!: List Str -> Try({}, Exit)

view this post on Zulip Luke Boswell (Dec 04 2025 at 00:24):

I think it should be

main! : List(Str) => Try({}, [Exit(I32)])

view this post on Zulip Aurélien Geron (Dec 04 2025 at 00:25):

Oh good point, thanks. I commented it out and still got the segfault

view this post on Zulip Luke Boswell (Dec 04 2025 at 00:25):

Are you able to post a copy of your cli running roc check roc test and roc ...

view this post on Zulip Aurélien Geron (Dec 04 2025 at 00:26):

Sure. Here's roc check:

-- BAD LIST REST PATTERN SYNTAX ------------------

List rest patterns should use the `.. as name` syntax, not `..name`.
For example, use `[first, .. as rest]` instead of `[first, ..rest]`.

   ┌─ /Users/ageron/dev/roc/aoc2025-roc/day01.roc:18:13
   │
18 │         [c, ..rest] => {
   │             ^^^^^^

-- BAD LIST REST PATTERN SYNTAX ------------------

List rest patterns should use the `.. as name` syntax, not `..name`.
For example, use `[first, .. as rest]` instead of `[first, ..rest]`.

   ┌─ /Users/ageron/dev/roc/aoc2025-roc/day01.roc:30:16
   │
30 │         [inst, ..rest] => {
   │                ^^^^^^

-- BAD LIST REST PATTERN SYNTAX ------------------

List rest patterns should use the `.. as name` syntax, not `..name`.
For example, use `[first, .. as rest]` instead of `[first, ..rest]`.

   ┌─ /Users/ageron/dev/roc/aoc2025-roc/day01.roc:47:17
   │
47 │             [x, ..rest] => {
   │                 ^^^^^^

-- BAD LIST REST PATTERN SYNTAX ------------------

List rest patterns should use the `.. as name` syntax, not `..name`.
For example, use `[first, .. as rest]` instead of `[first, ..rest]`.

   ┌─ /Users/ageron/dev/roc/aoc2025-roc/day01.roc:76:15
   │
76 │         [val, ..rest] => {
   │               ^^^^^^

view this post on Zulip Aurélien Geron (Dec 04 2025 at 00:28):

roc test gives a segfault:

zsh: segmentation fault  roc2 test day01.roc

Not sure whether it matters but I'm using a symlink named roc2.

view this post on Zulip Aurélien Geron (Dec 04 2025 at 00:29):

I tried replacing ..rest with .. as rest, and now roc check gives no error, but I still get the segfault.

view this post on Zulip Luke Boswell (Dec 04 2025 at 00:30):

My guess is the segfault is refcounting related... shouldn't be too hard to find.

view this post on Zulip Luke Boswell (Dec 04 2025 at 00:32):

If you're interested to explore yourself, you can build roc with refcount tracing zig build roc -Dtrace-refcount and if you build a debug version of the zig platform template it also has refcount tracing... then when you run you will get a detailed trace of every allocation (incref/decref)

view this post on Zulip Aurélien Geron (Dec 04 2025 at 00:32):

Cool, thanks Luke

view this post on Zulip Luke Boswell (Dec 04 2025 at 00:32):

I normally feed that trace into claude and a few moment later have narrowed down which builtin isn't following the correct ownership semantics

view this post on Zulip Luke Boswell (Dec 04 2025 at 00:33):

Write a test to reproduce, then fix, then verify etc... :smiley:

view this post on Zulip Aurélien Geron (Dec 04 2025 at 00:33):

A couple questions:

view this post on Zulip Luke Boswell (Dec 04 2025 at 00:35):

builtins currently implemented https://github.com/roc-lang/roc/blob/bb17e26f7bd1aa51ce8e18a2a795eab9d07369a9/src/build/roc/Builtin.roc#L4

view this post on Zulip Luke Boswell (Dec 04 2025 at 00:35):

about the rest thing... I'm not sure -- the discussions are many and so these things get blurry. I would look into the code, or maybe try it out on a smaller test program.

view this post on Zulip Aurélien Geron (Dec 04 2025 at 00:38):

I ran zig build roc -Dtrace-refcount and now when I run roc day01.roc I get:

[REFCOUNT] INCREF list (copyToPtr) ptr=0x101460018 len=1 rc=1 slice=0 elems_rc=1
error: Child process /Users/ageron/Library/Caches/roc/e59c636351ad64c25ba81dca340f7248/temp/roc-tmp-2q9ZB7TrXASkuFMITQ3Xqvx7AXG5qNWK/roc_run_994723065 killed by signal: 11
error: Child process crashed with segmentation fault (SIGSEGV)

and if you build a debug version of the zig platform template

How can I do that?

view this post on Zulip Luke Boswell (Dec 04 2025 at 00:40):

Clone the template repository, then zig build you can also do zig build native which is quicker because it only builds the libraries for your current system and doesn't cross-compile for all the supported os/arches

view this post on Zulip Luke Boswell (Dec 04 2025 at 00:40):

Use a relative path to the ../roc-platform-template-zig/platform/main.roc in your test app

view this post on Zulip Aurélien Geron (Dec 04 2025 at 00:41):

I'll try that after lunch, thanks Luke.


Last updated: Dec 21 2025 at 12:15 UTC