View Source Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
[0.10.0] - 2026-05-21
The headline feature of 0.10.0 is conditional compilation of contracts. You can now compile some or all of your contracts out entirely via application config, with zero per-call overhead for disabled contracts. The release also adds an ExUnit helper module, polishes error reporting, and substantially rewrites the user-facing documentation.
Added
Conditional compilation via
:bondapplication config. Three keys, read at compile time viaApplication.compile_env/3::preconditions(defaulttrue) — whenfalse, no precondition evaluation is emitted in override clauses, and the auto-generated#### Preconditionsdoc section is omitted.:postconditions(defaulttrue) — same for postconditions.:checks(defaulttrue) — whenfalse, everycheck/1,2macro call in modules thatuse Bondexpands to:okand the wrapped expression is not evaluated. (Don't put side effects insidecheck.)
When both
:preconditionsand:postconditionsare disabled for a function, Bond emits no override at all. The function runs exactly as written, with zero per-call overhead. The function's auto-generated contract docs are also suppressed in that case.See the new "Conditional compilation" section in the
Bondmoduledoc.Bond.Testmodule withassert_precondition_violation/2,assert_postcondition_violation/2, andassert_check_violation/2macros for testing contract violations in ExUnit. Field expectations (:label,:expression, etc.) can be exact values orRegexpatterns.New
guides/faq.mdanswering the questions that come up most: why contracts when I have ExUnit, will contracts slow down prod, how does Bond compare to Norm, what does Bond do that typespecs don't, the Assertion Evaluation rule, default-arg behaviour, multi-clause handling.
Changed
Assertion failure messages pretty-print the captured
binding/0withinspect/2 ... pretty: true, limit: 20, printable_limit: 200, width: 80, so small bindings stay compact and large structs no longer dominate the failure output.Stack traces of raised assertion exceptions are pruned to omit
Bond.*frames. Failures point at the user's call site rather than intoBond.Runtime.Eval.Bondmoduledoc / README restructured. Leads with a five-lineAccount.withdrawexample and a one-paragraph elevator pitch. The Wikipedia quote moves out. Assertion syntax recommends the keyword-list form as primary. NewConditional compilationsection. TheMath.sqrtexample remains as the "showing everything" sample.guides/getting-started.mdexpanded into a step-by-step walkthrough: first@pre, postcondition withresult, labelled assertions, predicates,oldexpressions, inline checks, disabling in prod, and ExUnit integration.
Internal
- New private function in
Bond.Runtime.Evalthat prunes Bond frames from the captured stack trace before raising. Bond.Compiler.AnnotatedFunction.apply_contract/1is nowapply_contract/2taking acontract_configmap. The__before_compile__/1callback reads the config from a@__bond_contract_config__module attribute set by Bond's__using__/1.
Requirements
- Unchanged. Elixir
~> 1.14.
[0.9.1] - 2026-05-21
A patch release covering documentation cleanup left over from the 0.9.0 refactor plus a handful of usability improvements.
Added
.formatter.exsis now published with the Hex package and declareslocals_without_parensforcheck/1,check/2, andold/1. Downstream projects can pick these up withimport_deps: [:bond]in their own.formatter.exs.- Assertion-failure messages now include an
at: <file>:<line>line so the source location is clickable in editors.
Changed
binding/0captured in assertion-failure info is sorted by name so failure messages are reproducible across runs.
Fixed
- README/moduledoc no longer references the removed Bond.def/2 and
Bond.defp/2 macros, eliminating
mix docscross-reference warnings. - The
getting-startedguide installation hint now references the current version. - CHANGELOG no longer auto-links the removed
define_function_with_contract/4helper.
Internal
- Removed the vestigial
:contextfield fromBond.Compiler.Assertion. - Tightened the
Bond.Compiler.AnnotatedFunctionmoduledoc.
[0.9.0] - 2026-05-21
This release is a large internal refactor with no breaking changes to the
public API. @pre, @post, and check/1,2 all behave the same as in 0.8.x.
Changed
- Bond no longer overrides
Kernel.def/2andKernel.defp/2. Contracts are now applied via Elixir compiler hooks (@on_definition,@before_compile,@after_compile). This makes Bond more robust against changes in Elixir's macro expansion semantics, eliminates a class of macro-hygiene issues, and plays nicer with other macros that produce function definitions. - Multi-clause functions are now wrapped by a single override clause that
delegates to
super/1rather than having contract logic inlined into each clause. Elixir's normal pattern matching handles dispatch inside thesupercall. - Assertion failures are signalled by a throw / catch instead of being
raised inline. Each
@pre/@postgroup compiles to an anonymous function that throws{:assertion_failure, info}on the first failure;Bond.Runtime.Evalcatches it and raises the appropriate exception type. - Functions with contracts now get auto-generated
PreconditionsandPostconditionssections in their documentation even if the user did not attach a@docthemselves. Previously contract documentation was only emitted when a@docwas present. - Internal modules are reorganised into
Bond.Compiler.*(compile-time) andBond.Runtime.*(run-time) namespaces.
Internal
- New modules:
Bond.Compiler.AnnotatedFunction(multi-clause function model),Bond.Compiler.FunctionDefinition,Bond.Compiler.CompileStateFSM(rewritten),Bond.Runtime.Eval. - Removed internal modules
Bond.Compiler.AnnotatedFunctionClauseandBond.Compiler.LegacyCompileStateFSM, along with thedefine_function_with_contract/4helper they used. Bond.Compiler.Assertionnow carries a stable random:idfor use in error reporting and future internal tooling.
Requirements
- Unchanged. Elixir
~> 1.14.
[0.8.3] - 2024-11-08
Released before this changelog was established. See the git history for details.