Skip to content

feat(error): name the callee/target in attempt to call/index errors#228

Merged
davydog187 merged 2 commits into
mainfrom
error-named-call-index
May 22, 2026
Merged

feat(error): name the callee/target in attempt to call/index errors#228
davydog187 merged 2 commits into
mainfrom
error-named-call-index

Conversation

@davydog187
Copy link
Copy Markdown
Contributor

Summary

  • Annotates :call, :get_field, :set_field, :get_table, :set_table, and :self instructions with a compile-time name_hint derived from the AST ({:global, name} / {:local, name} / {:upvalue, name} / {:field, name} / {:method, name}).
  • Executor formats the hint into the runtime error message, mirroring PUC-Lua.
  • Fixes :set_field / :set_table to raise :index_non_table instead of MatchError when the target isn't a table.

Before

> Lua.eval!("return foo()")
attempt to call a nil value

> Lua.eval!("foo.bar()")
attempt to index a nil value

After

> Lua.eval!("return foo()")
attempt to call a nil value (global 'foo')

> Lua.eval!("foo.bar()")
attempt to index a nil value (global 'foo')

> Lua.eval!("local t = {}; t.bar()")
attempt to call a nil value (field 'bar')

> Lua.eval!("local t = {}; t:baz()")
attempt to call a nil value (method 'baz')

> Lua.eval!("local n = 5; return n.x")
attempt to index a number value (local 'n')

PUC-Lua recovers the same names via debug info threaded through bytecode; doing it at compile time is simpler here because the AST is still in scope when we emit the instruction.

Test plan

  • mix test test/lua/error_messages_test.exs — 36 tests including 10 new cases covering global/local/upvalue/field/method calls, set-side index, non-function/non-table targets, and the anonymous-callee (no-hint) case.
  • mix test — full suite (1778 tests, 30 skipped) passes.
  • Manual iex -S mix smoke test for each error path.

Mirrors PUC-Lua by annotating :call, :get_field, :set_field, :get_table,
:set_table, and :self with a compile-time name_hint derived from the AST
(`{:global, name}`, `{:local, name}`, `{:upvalue, name}`, `{:field, name}`,
`{:method, name}`). The executor formats the hint into the runtime error
so messages now report the source name:

    attempt to call a nil value (global 'foo')
    attempt to index a nil value (local 't')
    attempt to call a nil value (field 'bar')

Also fixes :set_field / :set_table to raise :index_non_table instead of
MatchError when the target isn't a table.
Comment thread test/lua/error_messages_test.exs Outdated

test "call-nil error names a field" do
assert error_message("local t = {}\nt.bar()") =~
"attempt to call a nil value (field 'bar')"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the case where we're invoking functions and methods, it would be nice it if provided this information, i.e. I want to see that it was the t.bar() that failed (the 't' symbol is not mentioned in the current). Its definitely important to note which is nil as well (bar is nil, not t)

`t.bar()` where `bar` is nil now reports the receiver too:

    attempt to call a nil value (field 'bar' on local 't')
    attempt to call a nil value (method 'baz' on local 't')

Previously only the field/method name was named, leaving the receiver
symbol invisible -- so a user couldn't tell which `t` the failure
referred to in a script with several. Property and Index name_hints
now recurse into the table expression and tag a third element onto
`{:field, name, receiver}` / `{:method, name, receiver}`. The executor
formats the receiver with its own `local`/`global`/`upvalue` qualifier.
Anonymous receivers (e.g. `f().bar()`) emit the original 2-tuple form
and render with no receiver clause.

Also runs `mix format` over the rest of the prior commit's edits.
@davydog187 davydog187 merged commit c410640 into main May 22, 2026
4 checks passed
@davydog187 davydog187 deleted the error-named-call-index branch May 22, 2026 01:26
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