Skip to content

API Reference

Macros

TypeContracts.@contract Macro
julia
@contract AbstractType begin
    method1(::Self, ::ArgType)
    method2(::Self) :: ReturnType
    :optional
    method3(::Self)
end

@contract AbstractType{T,N} begin
    method1(::Self, ::Int) :: T
    method2(::Self, ::T, ::Int)
end

Register a method contract for a type. Type parameters (T, N, …) declared in the header can be used anywhere in the method signatures — they are resolved at check time from the concrete type's supertype chain.

Methods before :optional are mandatory (enforced by @verify). Methods after :optional are recorded but not enforced at compile time.

Auto-generation: if the abstract type or any unqualified function name is not yet defined in the calling module, @contract defines it automatically. This means the common boilerplate (abstract type T end, function f end) is no longer required. Define the abstract type explicitly beforehand only when you need a supertype constraint (e.g. abstract type Animal <: LivingThing end).

Documentation

An optional interface description and per-method descriptions are folded into the type's ?-visible documentation (and describe). They work for owned types and for retroactive contracts on foreign types (e.g. Base.AbstractArray):

julia
@contract AbstractShape "A 2-D geometric shape." begin
    area(::Self)::Float64      => "area enclosed by the shape"
    perimeter(::Self)::Float64 => "length of the boundary"
    :optional
    name(::Self)::String       => "human-readable name"
end

?AbstractShape then shows the contract section alongside any existing docstring.

TypeContracts.@verify Macro
julia
@verify ConcreteType
@verify ConcreteType trim_compat=true
@verify AbstractType subtypes=true
@verify AbstractType subtypes=true trim_compat=true
@verify ConcreteType for_contract=InterfaceType
@verify ConcreteType for_contract=InterfaceType trim_compat=true

Assert at module-load / precompile time that a type satisfies all mandatory contracts for its supertype chain. Checks both method existence and declared return types (via Base.return_types).

juliac / trim binaries: @verify at module top level is safe. It runs during Julia's precompilation step (before the native binary is produced) and is not re-executed at binary runtime. The trimmer eliminates it automatically because it is unreachable from any entry point. Do not call @verify (or check_contract) inside a function that runs at binary runtime — that would embed a Base.return_types call in the runtime call graph.

With trim_compat=true, also runs check_trim_compat to scan the typed IR of each mandatory method for known trim-unsafe calls (Base.return_types, invokelatest, etc.) and emits @warn for any found. This is a shallow, heuristic check — use TrimCheck.@validate for exhaustive verification.

With subtypes=true, verifies every concrete subtype of the given abstract type rather than the type itself. Equivalent to calling @verify on each concrete subtype individually, and self-maintaining as new subtypes are added.

With for_contract=I, performs a structural check against the contract registered for I without requiring T <: I. Useful for Holy Trait / structural protocols where user types satisfy a contract's method signatures but do not and cannot subtype the interface type. Combining with trim_compat=true also checks that T's implementations of I's methods are juliac --trim compatible.

Must be placed after all type and method definitions.

TypeContracts.@verify_all Macro
julia
@verify_all
@verify_all trim_compat=true

Assert at module-load / precompile time that every concrete subtype of a registered contract type, defined in the calling module, satisfies its mandatory contracts.

Place once at the end of your module, after all type and method definitions. Replaces the need for individual @verify T calls.

With trim_compat=true, also runs check_trim_compat on each type (see @verify for details on what is checked).

Example

julia
module Shapes
using TypeContracts

abstract type AbstractShape end
@contract AbstractShape begin
    area(::Self)
end

struct Circle <: AbstractShape ... end
area(c::Circle) = ...

struct Square <: AbstractShape ... end
area(s::Square) = ...

@verify_all   # checks Circle AND Square
end
TypeContracts.@invariants Macro
julia
@invariants AbstractType begin
    "description" => x -> predicate(x)
    :optional
    "optional check" => x -> other_check(x)
end

Register behavioral invariants for a type. These are tested at test time via test_behavior, not at compile time. The :optional separator works the same as in @contract.

TypeContracts.@delegate Macro
julia
@delegate WrapperType :field InterfaceType

Generate forwarding methods for every mandatory method in InterfaceType's contract, routing calls to getfield(wrapper, :field). Equivalent to writing each forwarding method manually, but driven by the registered @contract.

After emitting the forwarders, satisfies(WrapperType, InterfaceType) is called automatically and throws InterfaceError on failure.

The generated forwarding methods are plain concrete method definitions — no closures, no runtime dispatch on abstract types. They are fully trim-safe and pass juliac --trim.

Example

julia
using TypeContracts, BaseTypeContracts

struct LoggedArray{T} <: AbstractArray{T,1}
    data::Vector{T}
    n_reads::Ref{Int}
end
LoggedArray(v::Vector{T}) where T = LoggedArray{T}(v, Ref(0))

# Replaces explicit size/getindex/setindex! forwarding:
@delegate LoggedArray :data AbstractArray

LoggedArray([1, 2, 3])[2]                    # 2
satisfies(LoggedArray{Int}, AbstractArray)   # (satisfied = true, ...)

Limitations

  • Only methods in @contract InterfaceType are forwarded. Add to the contract first.

  • @contract (or using the package that registers it) must precede @delegate.

  • Arguments typed as interface type parameters are forwarded untyped (Any dispatch).

Structural checks

TypeContracts.check_contract Method
julia
check_contract(T::Type) -> NamedTuple{(:type, :contracts, :passed)}

Verify that T satisfies all mandatory contracts for its supertype chain. Checks both method existence and declared return types (via Julia's type inferencer). Optional methods are skipped. Throws InterfaceError on failure.

Uses Base.return_types internally. Do not call from functions that run at binary runtime — use @verify / @verify_all at module top level instead, where the trimmer eliminates it before the binary is produced.

TypeContracts.check_contract Method
julia
check_contract(T::Type, I::Type) -> NamedTuple{(:type, :contracts, :passed)}

Structural variant: verify that T satisfies the mandatory contract for I without requiring T <: I. Useful for structural (Holy Trait) protocols where the implementing type does not and cannot subtype the interface type.

Throws InterfaceError on failure. Uses Base.return_types — precompile-time only.

TypeContracts.check_trim_compat Method
julia
check_trim_compat(T::Type) -> NamedTuple{(:type, :contracts, :issues, :passed)}

Precompile-time check that inspects the typed IR of each mandatory contract method for T and warns if any known trim-unsafe functions are called directly in the method body (e.g. Base.return_types, invokelatest, Base.which).

This is a shallow, heuristic scan — it detects obvious reflection in the top-level method body but does not recurse into callees. Use TrimCheck.@validate for exhaustive trim verification.

Emits @warn for each finding; does not throw. Call after check_contract or @verify so method existence is already guaranteed.

TypeContracts.check_trim_compat Method
julia
check_trim_compat(T::Type, I::Type) -> NamedTuple{(:type, :contracts, :issues, :passed)}

Structural variant of check_trim_compat: scan the typed IR of each mandatory method of contract I implemented by T, without requiring T <: I. Useful for structural (Holy Trait) protocols where user types never subtype the interface type — check_trim_compat(T) is a no-op in that case because I is absent from supertypes(T).

Emits @warn for each finding; does not throw. Call after check_contract(T, I) so method existence is already guaranteed.

TypeContracts.satisfies Function
julia
satisfies(T::Type, S::Type) -> NamedTuple

Non-throwing check. Returns (satisfied, missing_methods, missing_optional). satisfied is true when all mandatory methods are present and return types match.

Uses Base.return_types — do not call from functions that run at binary runtime.

TypeContracts.list_contract Method
julia
list_contract(T::Type) -> Vector{MethodSpec}

Return method specs registered directly for type T.

TypeContracts.list_contract Method
julia
list_contract(T::Type, Val(:all)) -> Dict{Type, Vector{MethodSpec}}

Return all contracts applicable to T via its supertype chain.

TypeContracts.registered_contracts Function
julia
registered_contracts() -> Dict{Type, Vector{MethodSpec}}

Return every abstract type that has a registered @contract, mapped to its Vector{MethodSpec}. Implemented via method introspection; intended for interactive use.

Testing helpers

TypeContracts.implements Method
julia
implements(T::Type, S::Type; include_optional::Bool=false) -> Bool

Return true if T satisfies the structural contract for S (method existence and return types). Errors if S has no registered contract. Designed for direct use with @test:

julia
@test implements(Circle, AbstractShape)
@test implements(Circle, AbstractShape; include_optional=true)

Pass include_optional=true to also require all optional methods.

See also: satisfies for the full diagnostic result, implements(T) to check all applicable contracts at once.

TypeContracts.implements Method
julia
implements(T::Type; include_optional::Bool=false) -> Bool

Return true if T satisfies all contracts in its supertype chain. Errors if no contracts are found (likely a wrong type or a missing @contract call):

julia
@test implements(Circle)
@test implements(Circle; include_optional=true)

Pass include_optional=true to also require all optional methods across every applicable contract.

See also: implements(T, S) for a single contract, check_contract for the compile-time throwing version.

TypeContracts.behavior_passes Function
julia
behavior_passes(T::Type, objects; S=nothing, include_optional=false) -> Bool

Return true if all mandatory behavioral invariants for T's supertype chain pass against objects. Designed for direct use with @test:

julia
@test behavior_passes(Counter, [Counter(0), Counter(5)])
@test behavior_passes(Counter, [Counter(0)]; S=AbstractCounter)
@test behavior_passes(Counter, [Counter(0)]; include_optional=true)

Pass S to test only the invariants registered for a specific interface. Pass include_optional=true to require optional invariants as well.

TypeContracts.@test_implements Macro
julia
@test_implements T S

Assert that T satisfies the structural contract for S, integrating with the active Test.@testset. On failure, prints the list of missing methods before recording the test failure. Requires using Test at the call site.

julia
using Test, TypeContracts
@test_implements Circle AbstractShape
TypeContracts.@test_behavior_passes Macro
julia
@test_behavior_passes T objects

Assert that all mandatory behavioral invariants for T's supertype chain pass against objects, integrating with the active Test.@testset. On failure, prints which invariants failed before recording the test failure. Requires using Test at the call site.

julia
using Test, TypeContracts
@test_behavior_passes Counter [Counter(0), Counter(5)]

Behavioral testing

TypeContracts.test_behavior Method
julia
test_behavior(T::Type, objects) -> NamedTuple

Run all behavioral invariants registered for T's supertype chain against deepcopy'd test objects. Returns (passed, results, mandatory_failures).

passed is true when all mandatory invariants hold for all objects.

TypeContracts.test_behavior Method
julia
test_behavior(T::Type, S::Type, objects) -> NamedTuple

Run behavioral invariants registered for S specifically against objects of type T.

TypeContracts.list_behaviors Function
julia
list_behaviors(T::Type) -> Vector{BehaviorSpec}

Return behavioral invariants registered directly for type T.

TypeContracts.registered_behaviors Function
julia
registered_behaviors() -> Dict{Type, Vector{BehaviorSpec}}

Return every type that has registered @invariants, mapped to its Vector{BehaviorSpec}. Implemented via method introspection; intended for interactive use.

Trait dispatch

TypeContracts.interface_trait Function
julia
interface_trait(::Type{I}, ::Type{T}) -> Implemented{I} | NotImplemented{I}

Check if T satisfies the mandatory contract for I (method existence only). Returns a singleton trait type suitable for dispatch.

Trim/juliac-compatible. @contract I generates a concrete method interface_trait(::Type{I}, ::Type{T}) where {T} whose body is a fixed conjunction of concrete hasmethod(f, Tuple{…}) calls — no runtime registry lookup, no abstractly-typed Function, no dynamically-built signature. Because the method is emitted by @contract (ordinary method definition, not a Dict mutation), it is serialized into the registering package's precompile cache and survives precompilation and package reloads. hasmethod is a method-table lookup that runs without the JIT or type inferencer, so the result is statically resolvable and passes juliac --trim.

Interfaces with no registered contract fall through to the method below and return NotImplemented{I}().

Example

julia
process(x) = _process(interface_trait(AbstractShape, typeof(x)), x)
_process(::Implemented{AbstractShape}, x) = area(x)
_process(::NotImplemented{AbstractShape}, x) = error("not a shape")
TypeContracts.verified_trait Function
julia
verified_trait(::Type{I}, ::Type{T}) -> Implemented{I} | NotImplemented{I}

Check whether T has been verified against the full contract for I — method existence and declared return types — via @verify, @verify_all, or @delegate. Unlike interface_trait, which checks method existence only, verified_trait reflects the complete check_contract/satisfies result at the moment verification succeeded.

Returns NotImplemented{I}() for any (I, T) pair that has not been explicitly verified — even if T would in fact satisfy the contract structurally. This is a nominal, opt-in guarantee (like Rust's impl Trait for T), not a structural one: @verify/@verify_all/@delegate are what seal it in.

Trim/juliac-compatible: sealing emits one concrete, singleton-returning method per verified (I, T) pair at verification time (module load / precompile) — strictly more specific than the generic fallback below, so dispatch resolves it statically. No runtime check, no allocation, no registry lookup, same as interface_trait.

Revise caveat: redefining an implementation method after @verify leaves the sealed method in place until T is re-verified; the Revise extension's live re-check warns on a contract violation but does not automatically unseal verified_trait.

Example

julia
@verify Circle    # after this succeeds, verified_trait(Shape, Circle) === Implemented{Shape}()

process(x) = _process(verified_trait(Shape, typeof(x)), x)
_process(::Implemented{Shape}, x)    = area(x)
_process(::NotImplemented{Shape}, x) = error("not a verified shape")
TypeContracts.Implemented Type
julia
Implemented{I}

Singleton trait type returned by interface_trait when a type satisfies all mandatory methods of interface I. Used as a dispatch key.

julia
_process(::Implemented{AbstractShape}, x) = area(x)
TypeContracts.NotImplemented Type
julia
NotImplemented{I}

Singleton trait type returned by interface_trait when a type does not satisfy all mandatory methods of interface I. Used as a dispatch key.

julia
_process(::NotImplemented{AbstractShape}, x) = error("not a shape")

Introspection

TypeContracts.describe Method
julia
describe(T::Type; io::IO=stdout, all::Bool=!isabstracttype(T))

Pretty-print the contract for T.

  • all=true — walks the full supertype chain and shows every inherited contract (equivalent to describe(T, Val(:all))).

  • all=false — shows only what T itself registers: the methods and invariants declared directly in @contract T and @invariants T.

The default is true for concrete types (since contracts live on abstract supertypes, not on the concrete type itself) and false for abstract types (showing only what that level adds). Pass all=true on an abstract type to see the full chain:

julia
describe(AbstractFloat)             # own invariants only
describe(AbstractFloat; all=true)   # + Real + Number
describe(Float64)                   # full chain (default for concrete)
describe(Float64; all=false)        # (no contract registered)
TypeContracts.describe Method
julia
describe(T::Type, Val(:all); io::IO=stdout)

Pretty-print contracts for T's full supertype chain. Equivalent to describe(T; all=true).

Note

describe(T) on a concrete type automatically shows the full supertype chain. describe(T, Val(:all)) on an abstract type additionally walks upward through its own supertypes.

Documenter integration

TypeContracts.contract_md_string Function
julia
contract_md_string(T::Type) -> String

Return a Markdown-formatted string describing the contract and behavioral invariants registered for T. Suitable for Documenter @eval blocks — a String return value is rendered as Markdown by Documenter.

Returns an empty string when no contract or invariants are registered for T.

TypeContracts.contract_md Function
julia
contract_md(T::Type)

Return a Markdown.MD object for the contract registered on T. Requires the TypeContractsDocumenterExt extension, which loads automatically when using Documenter is in scope. Returns nothing when the extension is absent.

Trim diagnostics

Proactive pre-build scan and reactive juliac output translation. See the trim diagnostics guide for examples.

TypeContracts.trim_report Function
julia
trim_report(f, sig::Type{<:Tuple}) -> TrimReport

Statically scan the optimized, type-inferred IR of f called with argument tuple-type sig for patterns juliac --trim=safe rejects — dynamic dispatch (a call whose result infers to Any) and reflection (return_types, invokelatest, which, methods).

This is a fast, advisory pre-build check, not a substitute for juliac's verifier: it inspects one function's IR (after inlining, so many transitive issues surface) but does not run the whole-program trim analysis. Treat findings as warnings.

julia
trim_report(myfunc, Tuple{Int64})          # → TrimReport(...; passed=true/false)
TypeContracts.TrimReport Type
julia
TrimReport(entry, findings, passed)

Result of trim_report: entry describes the scanned function, findings are human-readable likely-trim-unsafe sites (empty when clean), and passed is their absence. TrimReport <: Exception so it can be thrown with a styled showerror when desired.

TypeContracts.TrimDiagnostics.explain_trim_failure Function
julia
explain_trim_failure(output; entry_path="", source_files=String[]) -> TrimFailure

Parse juliac --trim verifier output into a TrimFailure with a readable, source-mapped showerror. entry_path and source_files let the parser map findings to the user's own code (vs. generated wrappers). If the output is not in the recognised verifier format, the result still carries raw and renders a trimmed dump.

TypeContracts.TrimDiagnostics.TrimFailure Type
julia
TrimFailure(sites, raw; recognized, entry_path, source_files)

A parsed juliac --trim failure. sites are the deduplicated findings; raw is the original verifier output; recognized is false when the output did not match the known format (then showerror falls back to a trimmed raw dump so nothing is hidden). entry_path/source_files identify generated vs. user code for frame selection.

Types

TypeContracts.Self Type
julia
Self

Sentinel type used in @contract declarations as a placeholder for the concrete implementing type. At verification time, Self is substituted with the actual type being checked.

TypeContracts.TypeParamRef Type
julia
TypeParamRef

Reference to a type parameter of a parametric abstract type. Used in @contract AbstractType{T,N} blocks to refer to T or N in method signatures and return types.

At check time, resolved by extracting the corresponding parameter from the concrete type's supertype chain.

Juliac-compatible: plain data struct, no closures.

TypeContracts.InterfaceError Type
julia
InterfaceError <: Exception

Thrown when a type does not satisfy its registered interface contract.

TypeContracts.MethodSpec Type
julia
MethodSpec

A single method requirement within an interface contract.

Fields

  • f::Function — the function object

  • arg_types::Vector{Any} — argument types (Self, TypeParamRef, or concrete Type)

  • return_type::Type — annotated return type for display (Any if unspecified or parametric)

  • return_type_spec::Union{Type,TypeParamRef} — used for actual return type checking

  • description::String — human-readable signature for error messages

  • optional::Bool — whether this method is optional

  • doc::String — optional prose description ("" if none); shown in ?-docs and describe

TypeContracts.BehaviorSpec Type
julia
BehaviorSpec

A behavioral invariant tested against real objects at test time.

Fields

  • description::String — human-readable description

  • predicate::Functionx -> Bool, takes a test object

  • optional::Bool — whether this invariant is optional