View Source Bond.AssertionEvaluationError exception (Bond v1.14.0)

Exception raised when an assertion expression itself raises, rather than returning a truthy or falsy value.

This is distinct from a contract violation, and deliberately so: a violation means the assertion was evaluated and found false, while this means it could not be evaluated at all. Conflating the two would mask genuine bugs in a predicate — an assertion that raises is not evidence that the contract holds or fails, it is evidence the assertion is not total over its inputs.

@pre valid: String.contains?(email, "@")
def normalize(email), do: String.downcase(email)

normalize(nil)
** (Bond.AssertionEvaluationError) precondition could not be evaluated for
   call to MyApp.normalize/1
|   label: :valid
|   assertion: String.contains?(email, "@")
|   binding: [email: nil]
|   raised: ** (FunctionClauseError) no function clause matching in String.contains?/2

:exception is the original exception and :original_stacktrace its stacktrace, so the underlying failure is never lost. The rest of the fields carry the same contract metadata a violation would.

See the "Assertions must be total" section of the Writing sound assertions guide for how to avoid this — usually by leading with a type check.

Summary

Types

@type t() :: %Bond.AssertionEvaluationError{
  __exception__: term(),
  binding: keyword(),
  exception: Exception.t() | nil,
  expression: Bond.assertion_expression(),
  file: Path.t(),
  function: {String.t(), non_neg_integer()},
  impl: module() | nil,
  kind: atom(),
  label: Bond.assertion_label(),
  line: integer(),
  module: module(),
  original_stacktrace: Exception.stacktrace() | nil,
  quantifier: map() | nil,
  source_behaviour: module() | nil,
  source_contract: {module(), atom()} | nil,
  source_protocol: module() | nil
}

The Bond.AssertionEvaluationError exception type.

:kind is the assertion kind (:precondition, :postcondition, :invariant, :state_invariant, :transition_invariant, or :check). For Bond.InvariantError it distinguishes a struct @invariant from a Bond.Server @state_invariant / @transition_invariant; for the others it is redundant with the struct type.

:source_behaviour is the behaviour module an inherited contract came from (see Bond.Behaviour), or nil for a contract declared directly on the function.

:source_contract is the {module, name} of an applied named contract the failing assertion came from (see defcontract/@apply_contract), or nil otherwise.

:source_protocol is the protocol module a contract was declared on (see Bond.Protocol), or nil; when set, :impl is the implementation module the failing call resolved to (or nil if none could be resolved).

:quantifier carries element-level failure detail when the assertion used forall/exists (see Bond.Predicates), or nil otherwise.