View Source Public API surface (1.0)
This page enumerates every callable, attribute, and configuration value Bond considers part of its public surface under the stability guarantees. If something Bond exposes isn't on this list, it's implementation detail — Bond reserves the right to change it without a deprecation cycle. If you depend on something here, you can expect it to stay backwards-compatible until the next major.
The full set of modules in published API docs is the source-of-truth for "public module":
BondBond.PredicatesBond.TestBond.PropertyTestBond.PreconditionErrorBond.PostconditionErrorBond.InvariantErrorBond.CheckError
Everything under Bond.Compiler.* and Bond.Runtime.* is internal (marked
@moduledoc internal: true and filtered out of hexdocs by filter_modules
in mix.exs). Code that calls into those namespaces is using a private API
and may break on a patch release.
Module-attribute syntax (in use Bond scope)
Bond overrides Kernel.@/1 while use Bond is in scope to intercept four
attribute names; everything else forwards through to Kernel.@/1 unchanged
(verified by test/bond/attr_compat_test.exs). The accepted forms for the
intercepted attributes are:
@pre and @post
@pre expr— bare expression. Recognised forms are documented in theBond.Predicatesmoduledoc.@pre label: expr, other_label: other_expr— keyword list oflabel: expressionpairs.@pre label, exprand@pre expr, label— labelled-bare form (label as atom or binary either before or after the expression).@postaccepts all the same forms. In addition,resultis bound to the function's return value, andold(...)(see below) is recognised inside a postcondition expression.
Mixing a bare assertion with a labelled assertion in a single annotation
(e.g. @pre is_binary(x), positive: x > 0) raises a CompileError with a
specific diagnostic.
@invariant
@invariant expr— single expression. Implicit bindingsubjectreferences the value being checked.@invariant label: expr, other_label: other_expr— keyword list of labelled invariants. Bare-form unlabelled, single-expression syntax also works.
The 2-argument legacy form @invariant name, expr was removed in 0.16.0 and
raises a CompileError pointing at the migration.
@doc
@docis intercepted to append#### Preconditionsand#### Postconditionssections (if any) to the user-authored docstring. The intercepted behaviour is part of the public surface; the exact rendering of those sections is documented underBondand is part of the public surface as well.
Macros and operators (after use Bond)
check/1— runtime assertion of an expression or a keyword list of labelled expressions. Behaviour under the four:checksmodes (true | false | :purge) is documented in the mainBondmoduledoc.old/1— captures a value at function-entry for use in a@postexpression. Only valid inside@post.subject— implicit binding inside@invariantexpressions, bound to the struct being checked at each check site.~>/2,<~/2— pattern-matching operators imported fromBond.Predicates. Precedence and associativity are documented in theBond.Predicatesmoduledoc.|||/2,xor/2,implies?/2— boolean operators imported fromBond.Predicates. See "Bond.Predicates" below for direct calls outside a Bond module.
use Bond options
Each option is one of true, false, or :purge unless noted. Options
passed to use Bond override both the global :bond application config and
any :overrides entry that matches the module:
:preconditions— mode for the module's@preannotations.:postconditions— mode for the module's@postannotations.:checks— mode for the module'scheck/1calls.:invariants— mode for the module's@invariantannotations.:warn_skipped_invariants— boolean (defaulttrue). Controls the compile-time warning Bond emits when a public function in an invariant-declaring module has no clause that pattern-matches the struct or returns one. See the FAQ entry "Why is Bond warning about skipped invariants?"
Per-function module attribute
@bond_warn_skipped_invariants— tri-state (omit /true/false), consumed by Bond's__on_definition__handler and scoped to the nextdefonly. Omitting the attribute inherits the module/global setting;falsesuppresses the warning for that single function;truere- enables the warning for that single function even under a module-wide or globalfalse.
Bond.Predicates
When called directly (i.e. not through use Bond), Bond.Predicates
provides:
xor/2,implies?/2,|||/2—defs. Takes twoas_boolean(term())arguments, returnsboolean().~>/2,<~/2—defmacros. See theBond.Predicatesmoduledoc for the precedence/associativity rules and the canonical example.
__opaque__/1 and __truthy__/1 in Bond.Predicates are infrastructure
called by Bond-generated code. They are not a direct-use API and are
excluded from hexdocs (@doc false). Their stability is guaranteed only
insofar as Bond's generated code depends on them — user code should not
call them directly.
Bond.Test
Brought into ExUnit modules via use Bond.Test. Provides:
assert_precondition_violation/2assert_postcondition_violation/2assert_check_violation/2assert_invariant_violation/2
Each accepts an expression and a keyword list of optional fields to verify on
the raised error struct (:label, :module, :function, etc.). The full
keyword shape is documented in the Bond.Test moduledoc.
Bond.PropertyTest
Brought into ExUnit modules via use Bond.PropertyTest. Provides:
contract_holds/2— runs StreamData-generated input through a function (or every contract-bearing function in a module) and asserts every call satisfies its contracts.
Requires the optional :stream_data dependency in the consumer's mix.exs.
Telemetry
Bond emits exactly one telemetry event:
- Event name:
[:bond, :assertion, :failure]. - Measurements:
%{}(no numeric measurements; emitted purely for observation). Metadata: map with keys
:kind(:precondition|:postcondition|:invariant|:check),:label,:module,:function({name, arity}tuple),:expression(string source),:file,:line,:binding(keyword list of variables in scope at the assertion site).
The event is published before the corresponding error struct is raised, so
telemetry handlers see every assertion failure even when an upstream
rescue swallows the exception.
Error structs
All four are raised by Bond, all four are catchable, all four share the same
shape (defined by the internal Bond.AssertionError __using__ macro):
Public fields on every error struct:
:label—Bond.assertion_label/0(atom() | binary() | nil).:expression—Bond.assertion_expression/0(the AST of the asserted expression).:file—Path.t().:line—integer().:module—module().:function—{name :: atom(), arity :: non_neg_integer()}tuple.:binding—keyword()of in-scope variables at the assertion site.
The Exception.message/1 format is rendered by Bond.AssertionError.message/2
and is human-readable — the exact text is not part of the public surface
(see the stability doc).
Application config keys
All under the :bond application:
:preconditions— mode (true | false | :purge).:postconditions— mode.:checks— mode.:invariants— mode.:overrides— list of{module() | Regex.t(), keyword()}tuples. The keyword list uses the same per-kind keys above (:preconditions,:postconditions,:checks,:invariants,:warn_skipped_invariants). First exact-match module wins over regex matches; regex matches are tried in list order.:warn_skipped_invariants— boolean (defaulttrue).
The contract-checking chain preconditions ≤ postconditions ≤ invariants is
enforced at compile time and at runtime. Compile-time: if a lower kind is
:purge, every higher kind must also be :purge (this raises a
CompileError with a specific diagnostic). Runtime: if a lower kind is
false, every higher kind is also skipped, and Bond logs a one-time
Logger.warning per process per (higher, lower) pair. :checks is
orthogonal to the chain.
Types
Two public types referenced from public specs:
Bond.assertion_label/0—binary() | atom().Bond.assertion_expression/0— a quoted expression AST tuple ({atom(), Macro.metadata(), list()}).
An internal assertion_kind type also exists in Bond (@typedoc false —
the union :precondition | :postcondition | :check | :invariant), but it's
referenced only from internal-to-internal sites. Direct use is not supported.
What is not part of the public surface
The following exist in Bond's source tree but are explicitly not covered by the stability guarantees:
- Every module under
Bond.Compiler.*andBond.Runtime.*(all marked@moduledoc internal: true, all filtered out of hexdocs). This includes the FSM, the lifted-defp shapes, every helper inBond.Compiler.Assertion/AnnotatedFunction/ClauseWrapper/Clauses/Invariants/OldExpression/ContractDocs, and the entireBond.Runtime.Evalsurface. Direct use of any of these is unsupported and may break on a patch release. - The
__opaque__/1and__truthy__/1helpers inBond.Predicates— called by Bond-generated code, not by users. Their existence is stable insofar as the generated code relies on them, but the interface contract (what they accept, return, or do internally) is not. - The shape of compiled wrapper functions / lifted defps that Bond emits
into the user's module. The names (
__bond_preconditions__<fun>__<arity>,__bond_postconditions__...,__bond_invariants__...) are not stable. - The text of compile-error diagnostics raised by Bond's macros. These are user-facing prose that may be reworded for clarity; the fact of a diagnostic firing (e.g. "labelled @invariant 2-arg form is removed") is stable, but the exact wording is not.
- The text of runtime error messages emitted by
Exception.message/1onBond.PreconditionErroret al. The error struct fields are stable (see above); the rendered message is not. - Telemetry handler invocation order (Bond emits a single event; if multiple handlers are attached, the OTP-defined order applies — not Bond's concern).
If you need any of the above to remain stable for a use case, open an issue describing the use case; we'll consider promoting the specific piece into the public surface in a future minor.