Skip to content

fix(beam): handle string binaries in Seq enumerator#4591

Merged
dbrattli merged 1 commit intomainfrom
fix/beam-seq-over-string
May 4, 2026
Merged

fix(beam): handle string binaries in Seq enumerator#4591
dbrattli merged 1 commit intomainfrom
fix/beam-seq-over-string

Conversation

@dbrattli
Copy link
Copy Markdown
Collaborator

@dbrattli dbrattli commented May 4, 2026

Summary

  • Fix badarg crash when applying Seq.X operations (e.g. Seq.mapi, Seq.map, Seq.toList) to a string on the BEAM target.
  • F# strings are seq<char> by language definition, but Fable.Beam lowers them to Erlang binaries. fable_utils:get_enumerator/1 had no clause for binaries, so the fallback path (lists:flatten([Other])) wrapped the binary into a single-element list — the enumerator then handed the whole binary back as one "char", crashing later code paths (e.g. <<C/utf8>> from string c).
  • Add a binary clause that converts to a Unicode codepoint list, matching the existing to_list/1 handling.

Minimal repro

"Hello" |> Seq.mapi (fun _ c -> string c) |> String.concat ""
// CLR/JS/Python: "Hello"
// BEAM (before): error:badarg in seq:enumerator_generate_while_some
// BEAM (after):  "Hello"

Stack trace before fix

seq:enumerator_generate_while_some/3-fun-2-     (seq.erl:372)
fable_utils:enumerate_to_list_loop/2            (fable_utils.erl:274)
fable_utils:enumerate_to_list/1                 (fable_utils.erl:268)
fable_string:join/2                             (fable_string.erl:171)

Test plan

  • Quicktest reproduces the original crash before the fix; returns "Hello" after.
  • Non-ASCII handled correctly: "über" enumerates as 4 codepoints (verified raw output <<"ü-b-e-r">>, 8 bytes), not 5 bytes.
  • New regression tests in tests/Beam/StringTests.fs covering Seq.mapi, Seq.map, Seq.toList, Seq.length over strings.
  • Full BEAM suite green: 2441 passed, 0 failed.

🤖 Generated with Claude Code

F# strings are seq<char> by language definition, but Fable.Beam lowers
them to Erlang binaries. fable_utils:get_enumerator/1 had no clause for
binaries, so the fallback path wrapped the binary into a single-element
list — the enumerator then handed the whole binary back as one "char",
crashing later code paths (e.g. <<C/utf8>> in `string c`).

Add a binary clause that converts to a Unicode codepoint list, matching
the existing to_list/1 handling.

Repro: "Hello" |> Seq.mapi (fun _ c -> string c) |> String.concat ""

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dbrattli dbrattli merged commit 6e78058 into main May 4, 2026
31 checks passed
@dbrattli dbrattli deleted the fix/beam-seq-over-string branch May 4, 2026 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant