Skip to content

fix: upgrade to Fable 5.13 and Fable.Beam rc.34, emit real atoms - #38

Merged
dbrattli merged 1 commit into
mainfrom
fix/fable-5.13-beam-rc34
Aug 2, 2026
Merged

fix: upgrade to Fable 5.13 and Fable.Beam rc.34, emit real atoms#38
dbrattli merged 1 commit into
mainfrom
fix/fable-5.13-beam-rc34

Conversation

@dbrattli

@dbrattli dbrattli commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

Upgrades to Fable 5.13.0 and Fable.Beam 5.0.0-rc.34, and fixes a silent runtime bug the upgrade surfaced.

rc.34 makes the Atom union constructor private, on purpose: because Atom is [<Erase>]d, Atom "debug" compiled to the binary <<"debug"/utf8>>, not to an atom. So this call was passing binaries where OTP expects atoms:

logger:set_primary_config(<<"level"/utf8>>, <<"debug"/utf8>>)

The result is |> ignored, so the primary log level was silently never set. All 7 call sites now use Atom.ofString, which emits erlang:binary_to_atom(<<"debug"/utf8>>).

Fable 5.13 also landed fix(beam): compile [<StringEnum>] cases to atoms instead of binaries — same class of bug. This repo has no [<StringEnum>] usage, so nothing to change there.

Why it went unnoticed

TestBeamLogger.fs is guarded by #if FABLE_COMPILER_BEAM. Under just test (.NET) that define is off, so all five Beam tests compiled down to () and passed without exercising anything. The BEAM tests could not run at all: the paket Test group only declared FSharp.Core and Fable.Core, so dotnet fable test --lang beam failed with 14 × namespace 'Beam' is not defined.

So this PR also makes them runnable:

  • Fable.Beam added to the paket Test group and test/paket.references
  • just build-beam / just test-beam — fable --lang beamrebar3 compileerl, following the same shape as Fable.Beam's own justfile
  • CI now runs both suites; it previously only built

Fable.Logging.Structlog is excluded from the BEAM transpile via --exclude. Its [<Emit>] bodies contain literal Python ($0.debug($1, **$2)) which Fable emits verbatim into Erlang that does not parse. TestStructlog.fs is already #if FABLE_COMPILER_PYTHON-guarded, so nothing references the excluded module.

Verification

  • just test — 49/49 on .NET
  • just test-beam — 49/49 on the BEAM (locally OTP 25; CI pins OTP 27 to match Fable.Beam)
  • just format-check clean
  • Generated Erlang inspected to confirm erlang:binary_to_atom(...) at all call sites
  • Runtime output confirms correct level mapping — =INFO REPORT=, =WARNING REPORT=, =ERROR REPORT=, =CRITICAL REPORT= — which only works with genuine atoms

Not addressed

Structlog.fs has no target guards, so referencing Fable.Logging.Structlog from a JS or BEAM Fable project produces invalid output for consumers too. Guarding it with #if !FABLE_COMPILER || FABLE_COMPILER_PYTHON would fix that at the source and make the --exclude unnecessary. Left out as a separate concern.

🤖 Generated with Claude Code

Fable.Beam rc.34 makes the `Atom` union constructor private. Because `Atom`
is `[<Erase>]`d, the previous `Atom "debug"` compiled to the *binary*
`<<"debug"/utf8>>` rather than to an atom, so
`logger:set_primary_config(<<"level">>, <<"debug">>)` was passing binaries
where OTP expects atoms and the primary log level was never actually set
(the result is `|> ignore`d, so it failed silently).

All 7 call sites now use `Atom.ofString`, which emits
`erlang:binary_to_atom(<<"debug"/utf8>>)`.

Also wires up BEAM test execution, which is what allowed this to go
unnoticed: `TestBeamLogger.fs` is guarded by `#if FABLE_COMPILER_BEAM`, so
under `just test` (.NET) all five Beam tests compiled to `()` and passed
without exercising anything.

- Add `Fable.Beam` to the paket `Test` group so `test/` can transpile to
  Erlang at all
- Add `just build-beam` / `just test-beam` (fable --lang beam -> rebar3 ->
  erl), following the same shape as Fable.Beam's own justfile
- Run both suites in CI, which previously only built

`Fable.Logging.Structlog` is excluded from the BEAM transpile: its
`[<Emit>]` bodies contain literal Python (`$0.debug($1, **$2)`) which Fable
emits verbatim, producing Erlang that does not parse.

Verified: 49/49 on .NET, 49/49 on the BEAM under OTP 25.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dbrattli
dbrattli merged commit 4eecc78 into main Aug 2, 2026
2 checks passed
@dbrattli
dbrattli deleted the fix/fable-5.13-beam-rc34 branch August 2, 2026 18:48
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