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.16.1] - 2026-05-27
A patch release covering a 1.0-prep test-coverage audit (no behavioural change, just locking down behaviour that wasn't directly tested) plus a refresh of the supporting guides for content that had drifted out of date with 0.16.0.
Changed
guides/about.md— full rewrite. The previous version's feature TODO list still showed conditional compilation (shipped in 0.10/0.11) and invariants (shipped in 0.13) as unchecked items, and the framing read like marketing copy. New version is structured as "what Bond is, when to reach for it, background" — same length, every paragraph carrying information.guides/getting-started.md—@invariantsection added. The tutorial previously mentioned@invariantonly in "Next steps." A reader following it linearly would never learn there was a third contract kind. New section between "Inline checks" and "Disabling contracts in production" introduces it with aBoundedStackexample and thesubjectbinding, then points at the moduledoc for the full reference. The intro line at the top mentions@invariantalongside@pre/@post/check/1. The disabling-in-production config snippet now lists:invariants(was listing three of four keys).
Fixed
guides/faq.md— "When does Bond check invariants?" description brought current. The previous text said destructure-only function heads (def foo(%__MODULE__{f: v}, ...), no= name) emit a compile-time warning and skip the pre-check. The 0.16.0 release lifted that restriction — Bond now rewrites the override clause to capture the struct under a generated name and the pre-check fires. Multi-struct heads are also noted (weren't previously).guides/getting-started.md— dead anchor. The "Next steps" link to the Invariants section used the pre-0.16.0 anchor#module-invariants; updated to#module-invariant-for-struct-modulesmatching the renamed section.
Internal
Test coverage filled across seven gaps from a 1.0-prep audit (+16 tests, 220 total; all green). No behavioural change — each fill verifies behaviour that was already in place but lacked a direct test:
Invariant telemetry.
[:bond, :assertion, :failure]fires with:kind => :invarianton invariant violations. Documented since 0.13.0; previously only the other three kinds had assertions on the event.@invariantruntime modes. Two tests cover (a)put_env :bond, :invariants, falseskips evaluation, and (b) flipping back totruere-engages it. The runtime-toggle path was tested for@pre/@postbut not@invariant.Compound
andguards. Behavioural confirmation thatis_struct(x, __MODULE__)nested inside anandguard triggers the pre-invariant check. (Compiler-level detection was already covered.) Theorcase is deliberately not covered — it's a latent unsafe pattern worth a separate design discussion.No-struct heads. Behavioural confirmation that a function whose head doesn't expose the struct silently skips pre- invariant evaluation — passing non-struct arguments returns cleanly rather than crashing on a
subject.<field>access.Migration
CompileErrors. The legacy@invariant <name>, <expr>and the two arity-2checkshapes (removed in 0.16.0) now have direct assertions that they raiseCompileErrorwith the migration message at the call site.Bond.Test.assert_check_violation/2. The helper existed alongside itsprecondition/postcondition/invariantsiblings but had no test.old(...)runtime integration. Compiler-level extraction and precompilation were covered; the runtime path (does the snapshotted value end up correctly bound when the postcondition evaluates?) had no direct test. NewBond.OldRuntimeTestcovers success and failure paths plus the capturedbinding()at failure.
Coverage audit findings worth keeping in mind for future releases (not addressed in 0.16.1):
- Compound
orguards containingis_struct(_, __MODULE__)are a latent unsafe pattern. Bond's detection recognisesxas the struct parameter, but the pre-invariant fires unconditionally — so a runtime input matching a non-struct alternative crashes in the invariant body rather than raising a cleanFunctionClauseError. - Relatedly, the override clause doesn't reproduce the user's
function-head guard. Calling
Smoke.reverse(5)(wherereversehaswhen is_struct(stack, __MODULE__)) hits Bond's pattern-less override, fires the pre-invariant against the integer, and crashes inside the invariant body before super dispatches to the user's def for the properFunctionClauseError.
Neither issue surfaces in normal use (callers pass arguments of the right shape) — they're worth a fix pass before 1.0 but not shippable as a patch.
- Compound
Requirements
- Unchanged. Elixir
~> 1.14.
[0.16.0] - 2026-05-26
0.16.0 is the first 1.0-prep release. It tightens the public API in two
places where the surface had accumulated friction: @invariant drops its
required binding-name argument in favour of an implicit subject binding,
and check/2 drops its two string-label forms in favour of check expr
and check label: expr. Both legacy shapes now raise CompileError at the
call site with a migration message.
Breaking changes (minor)
@invariant <name>, <expr>was removed. The new form is@invariant <expr_or_kw>— no binding-name argument. Invariant expressions reference the implicitsubjectbinding, which Bond rebinds at every check site to whichever struct parameter the function head exposes (detected automatically across%__MODULE__{} = namepatterns,is_struct(name, __MODULE__)guards, and%__MODULE__{...}destructures).# Was: @invariant stack, non_negative_capacity: stack.capacity >= 0, size_within_capacity: length(stack.items) <= stack.capacity # Now: @invariant non_negative_capacity: subject.capacity >= 0, size_within_capacity: length(subject.items) <= subject.capacityFunction bodies don't change —
def push(%__MODULE__{} = stack, item)keeps its parameter namedstack; Bond detects and rebindssubjectto it automatically. The legacy 2-arg shape raises aCompileErrorwith the migration message.check/2was removed. The two string-label forms (check "label", exprandcheck expr, "label") are gone — they were redundant with the keyword-list form, which already carries a label:# Was: check "x is a number", is_number(x) check is_number(x), "x is a number" # Now: check x_is_number: is_number(x)check expr(bare) andcheck label: expr(keyword) are the two remaining forms. The legacy 2-arg shape raises aCompileErrorwith the migration message.
Added
Multi-struct heads in
@invariant.def merge(%__MODULE__{} = a, %__MODULE__{} = b)now triggers invariant checks on both struct parameters in left-to-right order, withsubjectrebinding to each in turn. Previously only the first detected struct param was checked.Destructure-only heads in
@invariant.def head(%__MODULE__{items: [first | _]})(no= name) now participates in pre-invariant checks. Bond rewrites the override clause head to add a capturing binding (%__MODULE__{items: [first | _]} = __bond_subject_0__) so the struct passes cleanly to the lifted invariants defp. Previously this shape was skipped silently with a documented (but unimplemented) warning.This also closes a latent bug in the override emission:
super(...)previously spliced raw destructure patterns as expressions, which would fail at compile time on patterns like[h | _]if a user had ever tried it with@pre/@post. The capture rewrite passes the original input through cleanly.Bond.Compiler.Invariants.detect_struct_params/2— internal helper that finds every struct-bearing parameter in a function head, returning a list of{:bound, var, idx}or{:destructure, idx}descriptors. Replaces the single-structfind_struct_arg/2removed below.
Changed
Doc-generation logic extracted into
Bond.Compiler.ContractDocs. Pure refactor — no user-visible change. Shaves ~80 lines offBond.Compiler.AnnotatedFunction, which is on the FSM's hot path. A shorterAnnotatedFunctionreduces the window for the parallel-compile race first encountered (and partially mitigated) in 0.13.0.Bond.Compiler.Assertiondrops the:binding_namefield. The invariant body now hardcodes thesubject = bond_invariant_valuerebind. The struct shrinks from 8 fields to 7.Bond.Compiler.Invariantssimplified. Removed the legacy single-struct helpersfind_struct_arg/2,struct_arg/2,pre_invariant_stmts/5, and the supporting AST walkers. New emission usesdetect_struct_params/2+all_pre_invariant_stmts/5+rewrite_call_params/2end-to-end.Moduledoc reorganised. Sections regroup as "what you write" (Usage → Assertion syntax →
@invariant→check/1→old) then "how you operate" (Documenting contracts → Conditional compilation → Telemetry → PBT). The 0.10 → 0.11 migration table is dropped, and the long Agent race-condition narrative inoldmoves to thecontracts-and-concurrencyguide.Telemetry
:kinddocumentation updated to include:invariant(the event was already emitted since 0.13.0; the docs were stale).
Requirements
- Unchanged. Elixir
~> 1.14.
[0.15.0] - 2026-05-25
0.15.0 closes a correctness gap in conditional compilation: previously
:preconditions, :postconditions, and :invariants could be toggled
independently in any combination, including combinations that produced
diagnostically-misleading errors (e.g. postconditions on while
preconditions are off — a "postcondition failure" might really mean
the caller broke their contract, not the function).
0.15.0 enforces the natural chain preconditions ≤ postconditions ≤ invariants both at compile time and at runtime. :checks remains
independent of the chain.
Breaking changes (minor)
Compile-time validation of
:purgecombinations.:purgeon a lower kind now requires:purgeon every higher kind in the chain.Bond.Compiler.resolve_config/3raisesCompileErrorwith an explanation otherwise.Migration: if you used
config :bond, preconditions: :purgewithout also purging postconditions/invariants, choose one:# Was: config :bond, preconditions: :purge # Option A — also purge the chain (preserves the original intent # if you wanted zero overhead): config :bond, preconditions: :purge, postconditions: :purge, invariants: :purge # Option B — runtime-disable instead of purge (keeps the code, # operator can flip on at runtime): config :bond, preconditions: falsefalseis unaffected — runtime-disabling a single kind is unchanged. Only:purgeparticipates in the compile-time check.
Added
Runtime chain propagation. When a lower kind is
falseat runtime (Application.put_env(:bond, :preconditions, false)), every higher kind is also skipped automatically, regardless of its own setting. Enforced inBond.Runtime.Eval.should_evaluate?/3via the new optional third argument carrying the compile-time defaults of every lower kind.One-time-per-process propagation log. The first time a higher kind is skipped because a lower one is runtime-off, Bond emits a
Logger.warningdescribing the chain constraint, the offending pair, and theApplication.put_envinvocation that would bring the higher kind back. Deduped per (higher, lower) pair via a Process-dictionary marker — long-running OTP processes get exactly one warning per pair.
Changed
Bond.Runtime.Eval.should_evaluate?/2is nowshould_evaluate?/3with an optionalchain_defaultsmap; the 2-arity call still works via default and is unchanged behaviour-wise for:preconditionsand:checks(both have no lower kinds).
Requirements
- Unchanged. Elixir
~> 1.14.
[0.14.0] - 2026-05-24
0.14.0 adds Bond.PropertyTest — a property-based testing layer that
uses Bond's contracts as the oracle. The hard part of PBT is usually
writing the predicate that distinguishes right from wrong outputs;
contracts already supply that at every call site. PBT just feeds random
inputs through already-instrumented code.
Added
Bond.PropertyTest.contract_holds/2— single macro, two forms:Form 1 (single function).
contract_holds &Mod.fn/N, args: [gen0, ...]expands to a property block that calls the function with random arguments and lets Bond's runtime contracts fail the property on any violation. StreamData shrinks to the minimal counterexample.Form 2 (module sequence).
contract_holds Module, constructors:, transformers:, observers:expands to a property block that generates random sequences of operations over a struct module and runs them. State is threaded through transformers; observers don't advance state but the pre-invariant still fires. The module's@invariants are the oracle. Supports%Mod{}and{:ok, %Mod{}}return shapes;{:error, _}terminates the sequence cleanly. Common option:nameoverrides the auto-generated property description.
The macro dispatches by first-arg AST shape (function reference vs module alias).
use Bond.PropertyTest— brings inExUnitPropertiesand imports thecontract_holdsmacro. Raises aCompileErrorat the use site with installation instructions if:stream_dataisn't available.Bond.PropertyTest.Sequence— internal helper module owning the sequence generator and runner used by Form 2.New FAQ entry: "How does Bond compose with StreamData / property-based testing?".
Changed
:stream_datamoves fromonly: [:dev, :test]to a regular dep withoptional: true. Users who want PBT now add{:stream_data, "~> 0.6"}to their own deps; users who don't pay no cost.
Requirements
- Unchanged. Elixir
~> 1.14.
[0.13.0] - 2026-05-23
0.13.0 adds @invariant declarations for struct modules — module-scoped
properties that hold across every public function in the struct's defining
module. Where @pre/@post constrain a single function call, @invariant
constrains the struct itself.
Added
@invariant <name>, <kw_or_expression>annotation. Same shape as@pre/@post: a labelled keyword-list of assertions, or a single unlabelled expression. The first argument is the variable name the expression refers to (e.g.stackin@invariant stack, length(stack.items) <= stack.capacity).Invariants are checked at the boundaries of every public function in the module:
- On entry, when the function head pattern-matches
%__MODULE__{} = nameor has anis_struct(name, __MODULE__)guard. - On exit, against the return value if it's
%__MODULE__{}or{:ok, %__MODULE__{}}. Other return shapes fall through with no check. - Never for
defp— private functions are exempt by the Eiffel convention (they often hold transiently-invalid state).
When a function destructures
%__MODULE__{...}in its head without binding the whole struct to a variable, Bond emits a compile-time warning suggesting%__MODULE__{...} = nameto enable the pre-check.- On entry, when the function head pattern-matches
Bond.InvariantError— new exception parallel toPreconditionError/PostconditionError/CheckError. Raised on invariant violation; carries the same metadata shape.Bond.Test.assert_invariant_violation/2— ExUnit helper mirroring the existing pre/post/check helpers.:invariantsconditional-compilation key. Joins:preconditions,:postconditions, and:checks. Sametrue | false | :purgevalue space; same runtime toggleability viaApplication.put_env/3; same:overridesanduse Bond, invariants: …support.Bond.Compiler.Invariants— new internal module owning the invariant emission logic (struct-arg detection, pre-/post-invariant call sites, the lifted invariants defp). Kept separate fromBond.Compiler.AnnotatedFunctionfor separation of concerns and to avoid parallel-compile scheduling issues with the larger combined file.
Changed
[:bond, :assertion, :failure]telemetry events now also fire for invariant violations, with:kind => :invariantin the metadata. No subscriber changes are needed — existing handlers attached to the event automatically pick up the new kind.The internal
Bond.Compiler.Assertionstruct gains a:binding_namefield, populated only on:invariantassertions from the declaration's first argument.Bond.Compiler.AnnotatedFunctiongains an:invariantsfield plusput_invariants/2andhas_invariants?/1helpers.override?/1widens to emit overrides for public functions in modules with@invariants, even when the function has no per-function@pre/@post.Bond.Compiler.CompileStateFSMtracks module-scoped invariants alongside the per-function preconditions/postconditions. Invariants don't transition the FSM into:contracts_pending(they don't attach to a "next function") and aren't flushed by function definitions.
Requirements
- Unchanged. Elixir
~> 1.14.
[0.12.0] - 2026-05-22
0.12.0 lands two internal-shape changes that compose on top of the
0.11.0 conditional-compilation work: contract closures move out of
override clauses into named private functions on the user's module
(reducing injected code per contract'd function), and :telemetry
events fire on assertion failures.
Added
[:bond, :assertion, :failure]telemetry event. Fires once per contract violation —@pre,@post, orcheck— immediately before the correspondingBond.PreconditionError/Bond.PostconditionError/Bond.CheckErroris raised. Single event family for all three kinds; consumers filter on the:kindmetadata. Measurements carry:system_timeand:monotonic_time; metadata carries:kind,:module,:function,:label,:expression,:assertion_id,:file,:line, and:binding. See the new "Telemetry" section in theBondmoduledoc / README.{:telemetry, "~> 1.0"}is now a regular dependency.Bond.Runtime.Eval.should_evaluate?/2— internal helper that performs theApplication.get_env/3runtime guard. Used by the emission shape (see "Internal" below) to avoid allocating the assertion-evaluation closure when the runtime guard says skip.
Changed
Per-function assertion closures are lifted into named
defps on the using module:__bond_preconditions__<fun>__<arity>and__bond_postconditions__<fun>__<arity>. The override clause itself is now a small wrapper that calls these viaBond.Runtime.Eval.evaluate_preconditions/1/evaluate_postconditions/1. The big inline assertion-evaluation AST that used to be re-emitted into every override is gone; the BEAM carries one tiny override + one defp per non-purged kind, rather than the whole eval body inlined per function.Runtime guard moved into
Bond.Runtime.Eval. The override callsshould_evaluate?(:preconditions, <compile_time_mode>)and only builds the assertion-evaluation closure when that returnstrue. TheApplication.get_env/3lookup logic lives entirely inBond.Runtimerather than being inlined at every contract'd function.Bond.check/1,2routes through the same throw/catch path as@pre/@post. All three kinds now produce{:assertion_failure, info}throws caught byBond.Runtime.Eval, which fires the telemetry event and raises. This unifies the plumbing across the three kinds; previouslycheckraised inline.Stacktrace pruning now also filters frames whose function name starts with
__bond_(the lifted defps), so failures continue to point at the user's call site rather than into Bond-generated plumbing.Benchmark on the project fixture (
bench/runtime_check_overhead.exs, trivial@pre is_number(x)in a tight loop):mode 0.11.0 0.12.0 :purge~48 ns ~34 ns true~155 ns ~143 ns false~89 ns ~91 ns The
truepath improves because the override no longer re-emits the full assertion-eval AST inline. Thefalse(runtime-skip) path is flat within noise —should_evaluate?/2short-circuits before the closure is allocated.
Fixed
Bond.CheckError'smessage/1no longer crashes when the error's:functionmetadata is missing (regression introduced and fixed internally during thecheckplumbing unification).
Requirements
- Unchanged. Elixir
~> 1.14.
[0.11.0] - 2026-05-21
0.11.0 reshapes the conditional-compilation config introduced in 0.10.0
around a new value space — true | false | :purge per kind — and adds two
new features that compose on top of it: runtime toggling without
recompilation, and per-module overrides.
Breaking changes (minor)
config :bond, <kind>: falseno longer compiles contracts out. It now means "compiled in, runtime guard defaults to off." If you usedfalsein 0.10.0 to get zero-overhead behaviour, change it to:purgeto preserve that behaviour.truecontinues to work as before (with the addition of runtime toggleability — see below).
Added
:purgemode for each contract kind. Setting any of:preconditions,:postconditions, or:checksto:purgecauses Bond to emit no code for that kind. The resulting BEAM contains no contract logic; per-call overhead is zero. Contract documentation for that kind is also suppressed.Runtime toggling. When a kind is compiled with
trueorfalse, the emitted override carries a runtime guard:Application.get_env(:bond, <kind>, <compile_time_value>). The contract is evaluated unless the runtime value is exactlyfalse. Operators can flip contracts on or off viaApplication.put_env/3from a remote console — no recompilation needed. The compile-time value sets the default for the runtime guard.Benchmark on the project fixture (
bench/runtime_check_overhead.exs, trivial@pre is_number(x)in a tight loop)::purge~48 ns/call,false~89 ns/call (~40 ns guard overhead),true~155 ns/call (guard plus assertion eval).:overridesconfig for per-module rules. A list of{Module | Regex, opts}tuples. Module-atom keys match exactly;Regexkeys match against the source-visible module name (noElixir.prefix). Use this to opt specific modules in or out of contract compilation without touching their source. Example:config :bond, preconditions: true, overrides: [ {MyApp.HotPath, preconditions: :purge, postconditions: :purge}, {~r/Workers\\./, postconditions: false} ]use Bond, optsper-module options. Pass any of:preconditions,:postconditions,:checksdirectly at theusesite to override global and:overridessettings for that module.defmodule MyApp.HotPath do use Bond, preconditions: :purge, postconditions: :purge endPrecedence:
use Bondopts > exact-atom:overridesmatch > firstRegex:overridesmatch > global config.Bond.Compiler.resolve_config/3— internal helper exposed for testing that combines global config,:overrides, anduse Bondopts into the final per-module mode map.
Changed
Bond.Compiler.AnnotatedFunction.apply_contract/2now expects each kind in the config map to betrue | false | :purgerather than a boolean. The function returnsnilwhen both kinds resolve to:purge; in all other cases it emits the override with the appropriate runtime guards.Bond.check/1,2now expands to a runtime-guarded call when the resolved:checksmode istrueorfalse, and to:ok(a compile-time no-op) when the mode is:purge.
Requirements
- Unchanged. Elixir
~> 1.14.
[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.