Module std.debug

Additions to the core debug module.

The module table returned by `std.debug` also contains all of the entries from the core debug table. An hygienic way to import this module, then, is simply to override the core `debug` locally:

local debug = require "std.debug"

The behaviour of the functions in this module are controlled by the value of the global `_DEBUG`. Not setting `_DEBUG` prior to requiring **any** of stdlib's modules is equivalent to having `_DEBUG = true`.

The first line of Lua code in production quality projects that use stdlib should be either:

_DEBUG = false

or alternatively, if you need to be careful not to damage the global environment:

local init = require "std.debug_init" init._DEBUG = false

This mitigates almost all of the overhead of argument typechecking in stdlib API functions.

Functions

DEPRECATED (version, name[, extramsg], fn) Provide a deprecated function definition according to _DEBUG.deprecate.
DEPRECATIONMSG (version, name[, extramsg], level) Format a deprecation warning message.
argcheck (name, i, expected, actual[, level=2]) Check the type of an argument against expected types.
argerror (name, i[, extramsg[, level=1]]) Raise a bad argument error.
argscheck (decl, inner) Wrap a function definition with argument type and arity checking.
debug () Equivalent to calling `debug.say (1, ...)`
extramsg_mismatch (expected, actual[, index]) Format a type mismatch error.
parsetypes (types) Compact permutation list into a list of valid types at each argument.
say ([n=1], ...) Print a debugging message to `io.stderr`.
trace (event) Trace function calls.

Tables

_DEBUG Control std.debug function behaviour.

Fields

extramsg_toomany Format a too many things error.
getfenv Extend `debug.getfenv` to unwrap functables correctly.
resulterror Raise a bad result error.
setfenv Extend `debug.setfenv` to unwrap functables correctly.
typesplit Split a typespec string into a table of normalized type names.


Functions

Methods
DEPRECATED (version, name[, extramsg], fn)
Provide a deprecated function definition according to _DEBUG.deprecate. You can check whether your covered code uses deprecated functions by setting `_DEBUG.deprecate` to `true` before loading any stdlib modules, or silence deprecation warnings by setting `_DEBUG.deprecate = false`.

Parameters:

  • version string first deprecation release version
  • name string function name for automatic warning message
  • extramsg string additional warning text (optional)
  • fn string deprecated function

Returns:

    a function to show the warning on first call, and hand off to *fn*

Usage:

    M.op = DEPRECATED ("41", "'std.functional.op'", std.operator)
DEPRECATIONMSG (version, name[, extramsg], level)
Format a deprecation warning message.

Parameters:

  • version string first deprecation release version
  • name string function name for automatic warning message
  • extramsg string additional warning text (optional)
  • level string call stack level to blame for the error

Returns:

    string deprecation warning message, or empty string

Usage:

    io.stderr:write (DEPRECATIONMSG ("42", "multi-argument 'module.fname'", 2))
argcheck (name, i, expected, actual[, level=2])
Check the type of an argument against expected types. Equivalent to luaL_argcheck in the Lua C API.

Call `argerror` if there is a type mismatch.

Argument `actual` must match one of the types from in `expected`, each of which can be the name of a primitive Lua type, a stdlib object type, or one of the special options below:

#table accept any non-empty table any accept any non-nil argument type file accept an open file object function accept a function, or object with a __call metamethod int accept an integer valued number list accept a table where all keys are a contiguous 1-based integer range #list accept any non-empty list object accept any std.Object derived type :foo accept only the exact string ":foo", works for any :-prefixed string

The `:foo` format allows for type-checking of self-documenting boolean-like constant string parameters predicated on `nil` versus `:option` instead of `false` versus `true`. Or you could support both:

argcheck ("table.copy", 2, "boolean|:nometa|nil", nometa)

A very common pattern is to have a list of possible types including "nil" when the argument is optional. Rather than writing long-hand as above, prepend a question mark to the list of types and omit the explicit "nil" entry:

argcheck ("table.copy", 2, "?boolean|:nometa", predicate)

Normally, you should not need to use the `level` parameter, as the default is to blame the caller of the function using `argcheck` in error messages; which is almost certainly what you want.

Parameters:

  • name string function to blame in error message
  • i string argument number to blame in error message
  • expected string specification for acceptable argument types
  • actual argument passed
  • level string call stack level to blame for the error (default 2)

Usage:

    local function case (with, branches)
      argcheck ("std.functional.case", 2, "#table", branches)
      ...
argerror (name, i[, extramsg[, level=1]])
Raise a bad argument error. Equivalent to luaL_argerror in the Lua C API. This function does not return. The `level` argument behaves just like the core `error` function.

Parameters:

  • name string function to callout in error message
  • i string argument number
  • extramsg string additional text to append to message inside parentheses (optional)
  • level string call stack level to blame for the error (default 1)

See also:

Usage:

    local function slurp (file)
      local h, err = input_handle (file)
      if h == nil then argerror ("std.io.slurp", 1, err, 2) end
      ...
argscheck (decl, inner)
Wrap a function definition with argument type and arity checking. In addition to checking that each argument type matches the corresponding element in the *types* table with `argcheck`, if the final element of *types* ends with an ellipsis, remaining unchecked arguments are checked against that type:

format = argscheck ("string.format (string, ?any...)", string.format)

A colon in the function name indicates that the argument type list does not have a type for `self`:

format = argscheck ("string:format (?any...)", string.format)

If an argument can be omitted entirely, then put its type specification in square brackets:

insert = argscheck ("table.insert (table, [int], ?any)", table.insert)

Similarly return types can be checked with the same list syntax as arguments:

len = argscheck ("string.len (string) => int", string.len)

Additionally, variant return type lists can be listed like this:

open = argscheck ("io.open (string, ?string) => file or nil, string", io.open)

Parameters:

  • decl string function type declaration string
  • inner string function to wrap with argument checking

Usage:

    local case = argscheck ("std.functional.case (?any, #table) => [any...]",
      function (with, branches)
        ...
    end)
debug ()
Equivalent to calling `debug.say (1, ...)`

See also:

Usage:

    local debug = require "std.debug"
    debug "oh noes!"
extramsg_mismatch (expected, actual[, index])
Format a type mismatch error.

Parameters:

  • expected string a pipe delimited list of matchable types
  • actual the actual argument to match with
  • index string erroring container element index (optional)

Returns:

    string formatted *extramsg* for this mismatch for argerror

See also:

Usage:

    if fmt ~= nil and type (fmt) ~= "string" then
      argerror ("format", 1, extramsg_mismatch ("?string", fmt))
    end
parsetypes (types)
Compact permutation list into a list of valid types at each argument. Eliminate bracketed types by combining all valid types at each position for all permutations of *typelist*.

Parameters:

  • types list a normalized list of type names

Returns:

    list valid types for each positional parameter
say ([n=1], ...)
Print a debugging message to `io.stderr`. Display arguments passed through `std.tostring` and separated by tab characters when `_DEBUG` is `true` and *n* is 1 or less; or `_DEBUG.level` is a number greater than or equal to *n*. If `_DEBUG` is false or nil, nothing is written.

Parameters:

  • n list debugging level, smaller is higher priority (default 1)
  • ... objects to print (as for print)

Usage:

    local _DEBUG = require "std.debug_init"._DEBUG
    _DEBUG.level = 3
    say (2, "_DEBUG table contents:", _DEBUG)
trace (event)
Trace function calls. Use as debug.sethook (trace, "cr"), which is done automatically when `_DEBUG.call` is set. Based on test/trace-calls.lua from the Lua distribution.

Parameters:

  • event string event causing the call

Usage:

    _DEBUG = { call = true }
    local debug = require "std.debug"

Tables

_DEBUG
Control std.debug function behaviour. To declare debugging state, set _DEBUG either to `false` to disable all runtime debugging; to any "truthy" value (equivalent to enabling everything except *call*, or as documented below.

Fields:

  • argcheck string honor argcheck and argscheck calls (default true)
  • call string do call trace debugging (default false)
  • deprecate if `false`, deprecated APIs are defined, and do not issue deprecation warnings when used; if `nil` issue a deprecation warning each time a deprecated api is used; any other value causes deprecated APIs not to be defined at all (default nil)
  • level string debugging level (default 1)

Usage:

    _DEBUG = { argcheck = false, level = 9 }

Fields

extramsg_toomany
Format a too many things error.
  • bad string the thing there are too many of
  • expected string maximum number of *bad* things expected
  • actual string actual number of *bad* things that triggered the error

See also:

Usage:

    if maxn (argt) > 7 then
      argerror ("sevenses", 8, extramsg_toomany ("argument", 7, maxn (argt)))
    end
getfenv
Extend `debug.getfenv` to unwrap functables correctly.
  • fn string, string or string target function, or stack level
resulterror
Raise a bad result error. Like argerror for bad results. This function does not return. The `level` argument behaves just like the core `error` function.
  • name string function to callout in error message
  • i string argument number
  • extramsg string additional text to append to message inside parentheses (optional)
  • level string call stack level to blame for the error (default 1)

Usage:

    local function slurp (file)
      local h, err = input_handle (file)
      if h == nil then argerror ("std.io.slurp", 1, err, 2) end
      ...
setfenv
Extend `debug.setfenv` to unwrap functables correctly.
  • fn string or string target function
  • env table new function environment
typesplit
Split a typespec string into a table of normalized type names.
  • either string or table `"?bool|:nometa"` or `{"boolean", ":nometa"}`
generated by LDoc 1.5.0 Last updated 2026-07-25 13:31:42