Open Manual

<!-- nytrix-doc: {"audience":"user","featured":false,"group":"learn","order":105,"summary":"Establish compile-time facts and use witnesses where a checked boundary requires proof."} -->

Proofs

Proofs turn a compile-time fact into an explicit program boundary. Use an

assertion when a fact belongs to one file. Pass a proof<P> witness when an

API requires that fact from its caller.

Start with compile-time checks

use std.core

static_assert(3 * 7 == 21, "arithmetic")
assert_compile(4 * 11 == 44, "compile-time expression")

def xs = [10, 20, 30]
def i = 1
assert_compile_range(i, 0, 2, "index range")
assert_compile_index(xs, i, "index bounds")
assert(xs[i] == 20, "indexed value")

static_assert and assert_compile reject a source unit when their condition

is not proven. assert_compile_range checks inclusive bounds.

assert_compile_index checks the static bounds of a list access.

Carry a witness

use std.core

fn require_positive(proof<5 > 0> witness) int { 5 }

def proof positive = prove(5 > 0, "positive literal")
assert(require_positive(positive) == 5, "witness accepted")

prove(P) creates a witness only when P is established during compilation.

The proof<P> parameter makes the required fact visible in the API signature.

Name a reusable proposition

use std.core

fn lemma positive_sum(int x, int y) {
  x > 0 && y > 0 → x + y > 0
}

def proof positive = prove(positive_sum(3, 4))
assert(proof_matches(positive, positive_sum(3, 4)), "lemma witness")

fn lemma declares a proposition with named parameters. Its body is a single

proposition; A → B means !A || B. Applying a lemma supplies its

proposition to prove, so the same checked fact can be shared without copying

the expression into every caller.

Lemma applications are compile-time proof obligations. A call whose full

proposition is false or unknown is rejected; a successful proof remains erased

at runtime.

Use inferred facts

range_proven(value, low, high) and index_proven(list, index) query facts

already established by the compiler. Keep proof checks close to the layout,

index, or pointer use they protect.

What the kernel proves

The proof kernel normalizes equality symmetry (a == b and b == a) and

reversed ordered comparisons (n > 0 and 0 < n). It proves folded

constants, conservative integer ranges, and recursively checked calls to

previously proved lemmas. For proven non-negative ranges, division and modulo

by a positive constant are range-checked; products whose operand ranges fit

the checked integer domain are also supported. Unsupported arithmetic is

delegated to the configured external prover when available and is never

accepted merely because it is unknown. It does not turn a runtime boolean

into a proof and does not attempt general theorem proving.

Current limits:

known integer ranges; it is not a general theorem prover.

numerator range. Other division forms require the external prover.

unsupported compositions are rejected as unknown.

When the kernel cannot prove a needed fact, restructure the check: bind the

value the compiler can see, keep the index narrow and loop-invariant, or move

the assertion closer to the layout or pointer use.

Safe native boundaries

ny --safe-mode file.ny
ny --borrow-check --ownership-strict file.ny

In safe mode, raw memory loads and stores against a compiler-tracked allocation

require a proven byte range. Do not replace a failed proof with a dynamic

fallback.

Related