Skip to content

errors: unify public runtime exceptions around Lua.RuntimeException#390

Merged
davydog187 merged 2 commits into
mainfrom
exceptions/unify-runtime-exception
Jul 15, 2026
Merged

errors: unify public runtime exceptions around Lua.RuntimeException#390
davydog187 merged 2 commits into
mainfrom
exceptions/unify-runtime-exception

Conversation

@davydog187

Copy link
Copy Markdown
Contributor

Context

The public exception surface was inconsistent and leaked VM internals. Lua.call_function/3 returned raw Lua.VM.RuntimeError / Lua.VM.TypeError / Lua.VM.ArgumentError / … structs — inconsistently suffixed *Error and namespaced under the implementation detail Lua.VM. Since we're pre-1.0 (1.0.0-rc), this is the moment to settle the surface before it freezes.

What changed

The public exception surface is now exactly two types, both *Exception, neither under Lua.VM:

  • Lua.CompilerException — compile/parse failures
  • Lua.RuntimeException — every runtime failure

The five Lua.VM.*Error structs are now internal (@moduledoc false): they're wrapped into Lua.RuntimeException before crossing any API boundary, so they never surface raw. They stay under Lua.VM — the correct home for internal VM error types once they're not user-facing — which leaves the ~219 stdlib raise sites untouched (a low-risk change concentrated at the boundary).

Lua.RuntimeException grows two fields so callers can still discriminate:

  • :kind:error | :type | :argument | :assertion | :internal
  • :value — the raised Lua value, exactly as pcall hands it back (§6.1)
  • (:original still carries the internal VM struct for deep inspection)

Lua.call_function/3 now returns {:error, %Lua.RuntimeException{}, lua} uniformly. A side benefit: its :value now matches in-Lua pcall for string errors (both give "<eval>:1: boom"); previously it returned the un-prefixed "boom".

Files

  • lib/lua/runtime_exception.ex — new :kind/:value; wrap clause derives them (value via existing ProtectedCall.error_value/1)
  • lib/lua.exfinish_call/2 wraps VM exceptions; updated call_function/3 docs
  • lib/lua/vm/*_error.ex (×5) — @moduledoc false, prose preserved as comments
  • CHANGELOG.md — public surface + call_function/3 return-type entries
  • tests — rewrote the boundary pin, fixed one pcall-state test, added :kind/:value coverage

Verification

  • mix test2598 passed (67 doctests, 56 properties), 7 skipped
  • mix compile --warnings-as-errors clean; mix format clean
  • End-to-end: call_function/3 returns %Lua.RuntimeException{kind:, value:, original:}; in-Lua pcall recovery unchanged ({false, "<eval>:1: boom"})

Note for review

Internal structs kept their *Error names (idiomatic Elixir for internal building blocks, and no longer user-facing). Renaming them to *Exception too is a mechanical follow-up if preferred.

The public exception surface leaked VM internals: Lua.call_function/3
returned raw Lua.VM.{RuntimeError,TypeError,ArgumentError,...} structs,
inconsistently suffixed `*Error` and namespaced under the implementation
detail Lua.VM.

Make the public surface exactly two exceptions, both `*Exception`:

  * Lua.CompilerException — compile/parse failures
  * Lua.RuntimeException  — every runtime failure

The five Lua.VM.*Error structs are now internal (@moduledoc false): they
are wrapped into Lua.RuntimeException before crossing any API boundary,
so they never surface raw and are no longer documented as public. They
stay under Lua.VM (the correct home for internal VM error types), which
leaves the ~219 stdlib raise sites untouched.

Lua.RuntimeException grows two fields so callers can still discriminate:

  * :kind  — :error | :type | :argument | :assertion | :internal
  * :value — the raised Lua value, exactly as pcall hands it back (§6.1)

(:original still carries the internal VM struct for deep inspection.)

call_function/3 now returns {:error, %Lua.RuntimeException{}, lua}
uniformly. Its :value now matches in-Lua pcall for string errors (both
give "<eval>:1: boom"); previously it returned the un-prefixed "boom".
Marking the VM error structs @moduledoc false hid them from ExDoc, so
the CHANGELOG's backtick references to them tripped "references a hidden
module" under `mix docs --warnings-as-errors`.

Align the docs config with the new stance: the VM structs are internal,
so remove them from @public_modules and the "Errors" group (leaving only
Lua.RuntimeException and Lua.CompilerException, plus the public
Lua.Parser.Error), drop their now-unused aliases, and add them to
skip_code_autolink_to so prose references render as plain code.
@davydog187 davydog187 merged commit 27f2f69 into main Jul 15, 2026
5 checks passed
@davydog187 davydog187 deleted the exceptions/unify-runtime-exception branch July 15, 2026 16:22
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