Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions .cargo/config.toml

This file was deleted.

3 changes: 0 additions & 3 deletions .github/workflows/build-and-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,6 @@ jobs:
bin-name: ${{ env.BIN_NAME }}
project-dir: .
manifest-path: Cargo.toml
# Preserve the Polonius requirement through nested toolchain setup
# (see docs/adr-006-adopt-polonius-nightly-toolchain.md).
rustflags: -Zpolonius=next
skip-man-page-discovery: 'true'

- name: Generate release help
Expand Down
26 changes: 13 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ jobs:
env:
CARGO_TERM_COLOR: always
BUILD_PROFILE: debug
# The tree requires -Zpolonius=next (see
# docs/adr-006-adopt-polonius-nightly-toolchain.md), so CI builds with
# the dated nightly pinned in rust-toolchain.toml.
NETSUKE_RUST_TOOLCHAIN: nightly-2026-06-25
# The tree requires the Polonius borrow checker, which nightly enables by
# default (see docs/adr-006-adopt-polonius-nightly-toolchain.md), so CI
# builds with the dated nightly pinned in rust-toolchain.toml.
NETSUKE_RUST_TOOLCHAIN: nightly-2026-08-23
WHITAKER_INSTALLER_VERSION: '0.2.7'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down Expand Up @@ -52,8 +52,8 @@ jobs:
uses: leynos/shared-actions/.github/actions/setup-rust@8add2d99854a5b77548eae98cca59202e68fefc8
with:
toolchain: ${{ env.NETSUKE_RUST_TOOLCHAIN }}
# Preserve warnings-as-errors and Polonius through toolchain setup.
rustflags: -D warnings -Zpolonius=next
# Preserve warnings-as-errors through toolchain setup.
rustflags: -D warnings
- name: Install cargo-nextest
uses: taiki-e/install-action@18b1216eba7f8039b0f8d131d5473787f0edce68 # v2.85.3
with:
Expand Down Expand Up @@ -145,10 +145,10 @@ jobs:
env:
CARGO_TERM_COLOR: always
BUILD_PROFILE: debug
# The tree requires -Zpolonius=next (see
# docs/adr-006-adopt-polonius-nightly-toolchain.md), so CI builds with
# the dated nightly pinned in rust-toolchain.toml.
NETSUKE_RUST_TOOLCHAIN: nightly-2026-06-25
# The tree requires the Polonius borrow checker, which nightly enables by
# default (see docs/adr-006-adopt-polonius-nightly-toolchain.md), so CI
# builds with the dated nightly pinned in rust-toolchain.toml.
NETSUKE_RUST_TOOLCHAIN: nightly-2026-08-23
WHITAKER_INSTALLER_VERSION: '0.2.7'
defaults:
run:
Expand All @@ -166,8 +166,8 @@ jobs:
uses: leynos/shared-actions/.github/actions/setup-rust@8add2d99854a5b77548eae98cca59202e68fefc8
with:
toolchain: ${{ env.NETSUKE_RUST_TOOLCHAIN }}
# Preserve warnings-as-errors and Polonius through toolchain setup.
rustflags: -D warnings -Zpolonius=next
# Preserve warnings-as-errors through toolchain setup.
rustflags: -D warnings
- name: Install Ninja
uses: seanmiddleditch/gha-setup-ninja@3b1f8f94a2f8254bd26914c4ab9474d4f0015f67 # v6
- name: Install cargo-nextest
Expand Down Expand Up @@ -223,7 +223,7 @@ jobs:
# the `#[cfg(windows)]` arms. A failure blocks the merge.
run: make SHELL=bash lint-whitaker
- name: Test
# cargo-nextest plus doctests under `-D warnings -Zpolonius=next`,
# cargo-nextest plus doctests under `-D warnings`,
# compiling and running the `#[cfg(windows)]` test tree. A failure
# blocks the merge.
run: make SHELL=bash test
Expand Down
9 changes: 5 additions & 4 deletions .github/workflows/coverage-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ jobs:
- name: Setup Rust
uses: leynos/shared-actions/.github/actions/setup-rust@8add2d99854a5b77548eae98cca59202e68fefc8
with:
# Match rust-toolchain.toml: the tree needs -Zpolonius=next (see
# Match rust-toolchain.toml: the tree needs the nightly-default
# Polonius borrow checker (see
# docs/adr-006-adopt-polonius-nightly-toolchain.md).
toolchain: nightly-2026-06-25
# Preserve warnings-as-errors and Polonius through toolchain setup;
toolchain: nightly-2026-08-23
# Preserve warnings-as-errors through toolchain setup;
# cargo-llvm-cov appends its instrumentation flags to this value.
rustflags: -D warnings -Zpolonius=next
rustflags: -D warnings
- name: Test and Measure Coverage
uses: leynos/shared-actions/.github/actions/generate-coverage@8add2d99854a5b77548eae98cca59202e68fefc8
with:
Expand Down
8 changes: 3 additions & 5 deletions .github/workflows/netsukefile-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ jobs:
permissions:
contents: read
env:
# Match rust-toolchain.toml: the tree needs -Zpolonius=next (see
# docs/adr-006-adopt-polonius-nightly-toolchain.md).
NETSUKE_RUST_TOOLCHAIN: nightly-2026-06-25
# Match rust-toolchain.toml: the tree needs the nightly-default Polonius
# borrow checker (see docs/adr-006-adopt-polonius-nightly-toolchain.md).
NETSUKE_RUST_TOOLCHAIN: nightly-2026-08-23
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -24,8 +24,6 @@ jobs:
uses: leynos/shared-actions/.github/actions/setup-rust@8add2d99854a5b77548eae98cca59202e68fefc8
with:
toolchain: ${{ env.NETSUKE_RUST_TOOLCHAIN }}
# Preserve the Polonius requirement through toolchain setup.
rustflags: -Zpolonius=next
- name: Show rustc version
run: |
rustup show
Expand Down
33 changes: 21 additions & 12 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,12 @@ project:

### Borrow checker: Polonius, not NLL

Netsuke compiles with the Polonius alpha analysis (`-Zpolonius=next`) on the
dated nightly pinned in `rust-toolchain.toml` (see
`docs/adr-006-adopt-polonius-nightly-toolchain.md` and `docs/polonius.md`).
Internal APIs are borrow-centric: lookups and get-or-create accessors return
references, clone keys only on insertion, and build error context lazily.
Netsuke compiles with the Polonius alpha analysis, which the dated nightly
pinned in `rust-toolchain.toml` enables by default (see
`docs/adr-006-adopt-polonius-nightly-toolchain.md` and `docs/polonius.md`). No
`-Z` directive is needed, or wanted: do not add one. Internal APIs are
borrow-centric: lookups and get-or-create accessors return references, clone
keys only on insertion, and build error context lazily.

- **Never** rewrite a site tagged `POLONIUS(...)` into a double lookup
(`contains_key` + `get_mut`), an `entry(key.clone())` call, or an id/index
Expand All @@ -152,8 +153,17 @@ references, clone keys only on insertion, and build error context lazily.
- Respect `POLONIUS-REFUSED(...)` tags: the named constraint (persistent
identity, lock boundaries, aliasing, suspension points, thread boundaries) is
permanent. Do not convert those sites to reference-returning forms.
- When adding a new borrow-centric API, verify it with and without
`-Zpolonius=next` and record the classification in `docs/polonius.md`.
- When adding a new borrow-centric API, record the classification in
`docs/polonius.md`.

### Trait solver: next-generation, enabled by the pin

The same pinned nightly enables the next-generation trait solver, and Netsuke
assumes it. Write to what the solver accepts: do not contort a design around an
old-solver limitation, and do not add explicit turbofish, redundant bounds, or
intermediate bindings to work around inference that already succeeds. As with
Polonius, the pin is the whole mechanism — do not add a `-Znext-solver`
directive anywhere.

- Run `make check-fmt`, `make lint`, `make doc-coverage`, and `make test`
before committing. These targets wrap the following commands, so contributors
Expand All @@ -168,9 +178,9 @@ references, clone keys only on insertion, and build error context lazily.
- `make lint` executes:

```sh
RUSTFLAGS="${RUSTFLAGS:+$RUSTFLAGS }-D warnings -Zpolonius=next" \
RUSTFLAGS="${RUSTFLAGS:+$RUSTFLAGS }-D warnings" \
RUSTDOCFLAGS="--cfg docsrs -D warnings" cargo doc --workspace --no-deps
RUSTFLAGS="${RUSTFLAGS:+$RUSTFLAGS }-D warnings -Zpolonius=next" \
RUSTFLAGS="${RUSTFLAGS:+$RUSTFLAGS }-D warnings" \
cargo clippy --workspace --all-targets --all-features -- -D warnings
whitaker --all -- --all-targets --all-features
```
Expand All @@ -183,9 +193,9 @@ references, clone keys only on insertion, and build error context lazily.
- `make test` executes:

```sh
RUSTFLAGS="${RUSTFLAGS:+$RUSTFLAGS }-D warnings -Zpolonius=next" \
RUSTFLAGS="${RUSTFLAGS:+$RUSTFLAGS }-D warnings" \
cargo nextest run --workspace --all-targets --all-features
RUSTFLAGS="${RUSTFLAGS:+$RUSTFLAGS }-D warnings -Zpolonius=next" \
RUSTFLAGS="${RUSTFLAGS:+$RUSTFLAGS }-D warnings" \
cargo test --workspace --doc --all-features
```

Expand All @@ -198,7 +208,6 @@ references, clone keys only on insertion, and build error context lazily.
- `make doc-coverage` executes:

```sh
RUSTFLAGS="${RUSTFLAGS:+$RUSTFLAGS }-Zpolonius=next" \
RUSTDOCFLAGS="--cfg docsrs -D warnings" \
python3 scripts/doc-coverage.py --threshold 80
```
Expand Down
49 changes: 25 additions & 24 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ CARGO ?= $(shell command -v cargo 2>/dev/null || printf '%s' "$$HOME/.cargo/bin/
# CARGO is resolved above before it is exported: `export` alone would define
# the variable empty and shadow the `?=` fallback for every recipe.
export CARGO
# The Polonius borrow-checker flag normally flows from .cargo/config.toml, but
# any recipe that sets RUSTFLAGS overrides that table and must re-state it.
POLONIUS_FLAGS ?= -Zpolonius=next
# Extra build-parallelism flags for plain Cargo invocations, e.g. `-j 4`.
BUILD_JOBS ?=
# The same concept for cargo-nextest, which spells build parallelism
Expand All @@ -38,12 +35,11 @@ KANI_FLAGS ?=
KANI_INSTALL_FLAGS ?=
KANI_CHECK_FLAGS ?=
KANI_VERSION_FILE ?= tools/kani/VERSION
# Opt-in local build acceleration. The Cargo fragment is deliberately separate
# from `.cargo/config.toml`: that file is auto-discovered and carries the
# repository-wide Polonius flag, whereas Cranelift and mold must stay opt-in so
# release, packaging, coverage, and formal-verification paths keep the
# supported LLVM backend and platform linker. The toolchain is not pinned
# separately — dev-fast uses the repository's own nightly.
# Opt-in local build acceleration. The Cargo fragment is deliberately kept out
# of an auto-discovered `.cargo/config.toml`, because Cranelift and mold must
# stay opt-in so release, packaging, coverage, and formal-verification paths
# keep the supported LLVM backend and platform linker. The toolchain is not
# pinned separately — dev-fast uses the repository's own nightly.
MOLD_VERSION_FILE ?= tools/mold/VERSION
MOLD_SHA256SUMS_FILE ?= tools/mold/SHA256SUMS
DEV_FAST_CONFIG ?= tools/dev-fast/config.toml
Expand Down Expand Up @@ -84,7 +80,7 @@ MD_FILES_FIND = find . -type f -name '*.md' \
PROVER_TOOLS_SOURCE ?= git+https://github.com/leynos/rust-prover-tools@b07ef696f8373d54ae68e517d39d47a5d27a5bd5
PROVER_TOOLS ?= uv tool run --from $(PROVER_TOOLS_SOURCE) prover-tools
RUSTDOC_FLAGS ?= --cfg docsrs -D warnings
export PYTHON POLONIUS_FLAGS RUSTDOC_FLAGS
export PYTHON RUSTDOC_FLAGS
VERUS_FLAGS ?=
VERUS_INSTALL_FLAGS ?=
WHITAKER ?= whitaker
Expand All @@ -102,40 +98,45 @@ clean: ## Remove build artefacts
test: test-nextest doctest ## Run every Rust test with warnings treated as errors

test-nextest: ## Run all non-doctest Rust tests through cargo-nextest
RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings $(POLONIUS_FLAGS)" $(CARGO) nextest run --workspace --all-targets --all-features $(NEXTEST_BUILD_JOBS)
RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings" $(CARGO) nextest run --workspace --all-targets --all-features $(NEXTEST_BUILD_JOBS)

doctest: ## Run doctests, which cargo-nextest cannot execute
RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings $(POLONIUS_FLAGS)" $(CARGO) test --workspace --doc --all-features $(BUILD_JOBS)
RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings" $(CARGO) test --workspace --doc --all-features $(BUILD_JOBS)

test-workflow-contracts: ## Validate the mutation-testing caller contract
uv run --with 'pytest>=8' --with 'pyyaml>=6' --with 'hypothesis>=6' pytest tests/workflow_contracts -q

test-typos-config: spelling-helper-test ## Verify the shared spelling-policy integration

target/%/$(APP): ## Build binary in debug or release mode
RUSTFLAGS="$${RUSTFLAGS-} $(POLONIUS_FLAGS)" $(CARGO) build $(BUILD_JOBS) $(if $(findstring release,$(@)),--release) --bin $(APP)
$(CARGO) build $(BUILD_JOBS) $(if $(findstring release,$(@)),--release) --bin $(APP)

lint: lint-clippy lint-whitaker ## Run Clippy and the Whitaker Dylint suite with warnings denied

lint-clippy: ## Run rustdoc and Clippy with warnings denied
RUSTDOCFLAGS="$(RUSTDOC_FLAGS)" RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings $(POLONIUS_FLAGS)" $(CARGO) doc --workspace --no-deps
RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings $(POLONIUS_FLAGS)" $(CARGO) clippy $(CLIPPY_FLAGS)
RUSTDOCFLAGS="$(RUSTDOC_FLAGS)" RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings" $(CARGO) doc --workspace --no-deps
RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings" $(CARGO) clippy $(CLIPPY_FLAGS)

lint-whitaker: ## Run the Whitaker Dylint suite with warnings denied
DYLINT_TOML="$$(cat dylint.toml)" RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings $(POLONIUS_FLAGS)" $(WHITAKER) --all --no-deps --package netsuke-build -- --all-targets --all-features
DYLINT_TOML="$$(cat dylint.toml)" RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings" $(WHITAKER) --all --no-deps --package netsuke-build -- --all-targets --all-features
# Run from the crate directory as well so Whitaker loads the narrow
# `test_support::fs` exemption from test_support/dylint.toml.
cd test_support && DYLINT_TOML="$$(cat dylint.toml)" RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings $(POLONIUS_FLAGS)" $(WHITAKER) --all --no-deps --package test_support -- --all-targets --all-features
cd test_support && DYLINT_TOML="$$(cat dylint.toml)" RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings" $(WHITAKER) --all --no-deps --package test_support -- --all-targets --all-features

doc-coverage: doc-coverage-test ## Verify aggregate Rustdoc doc-comment coverage meets the threshold
@RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }$${POLONIUS_FLAGS}" RUSTDOCFLAGS="$${RUSTDOC_FLAGS}" \
@RUSTDOCFLAGS="$${RUSTDOC_FLAGS}" \
"$${PYTHON}" scripts/doc-coverage.py --toolchain "$$DOC_COVERAGE_TOOLCHAIN" --threshold "$$DOC_COVERAGE_THRESHOLD"

doc-coverage-test: ## Run the pytest suite for scripts/doc-coverage.py
doc-coverage-test: ## Run documentation-coverage pytest modules
@PYTHONPATH=scripts $(UV_ENV) $(UV) run --no-project --python 3.13 \
--with pytest==9.0.2 --with pytest-cov==7.0.0 \
python -m pytest scripts/tests/test_doc_coverage.py -c /dev/null \
--rootdir=. -p no:cacheprovider --cov=doc_coverage_module
python -m pytest scripts/tests/test_doc_coverage_model.py \
scripts/tests/test_doc_coverage_cargo.py \
scripts/tests/test_doc_coverage_cargo_payload.py \
scripts/tests/test_doc_coverage_runner.py \
scripts/tests/test_doc_coverage.py -c /dev/null --rootdir=. \
-p no:cacheprovider --cov=doc_coverage_model --cov=doc_coverage_cargo \
--cov=doc_coverage_runner --cov=doc_coverage_module

fmt: ## Format Rust and Markdown sources
$(CARGO) fmt --all
Expand All @@ -145,7 +146,7 @@ check-fmt: ## Verify formatting
$(CARGO) fmt --all -- --check

typecheck: ## Typecheck all targets and features
RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings $(POLONIUS_FLAGS)" $(CARGO) check --all-targets --all-features $(BUILD_JOBS)
RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }-D warnings" $(CARGO) check --all-targets --all-features $(BUILD_JOBS)

markdownlint: spelling ## Lint Markdown and enforce en-GB-oxendict spelling
$(MDLINT) "**/*.md"
Expand Down Expand Up @@ -181,7 +182,7 @@ kani-check: ## Check the installed Kani verifier version
@$(PROVER_TOOLS) kani check-version --kani-command "$(KANI)" $(KANI_CHECK_FLAGS) || { status=$$?; printf 'prover-tools: target=kani-check failed exit=%s\n' "$$status" >&2; exit "$$status"; }

kani-full: ## Run the full Kani verification suite
RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }$(POLONIUS_FLAGS)" $(KANI) $(KANI_FLAGS)
$(KANI) $(KANI_FLAGS)

kani-ir: kani-full ## Run the IR Kani verification suite

Expand Down Expand Up @@ -223,7 +224,7 @@ bench-build: dev-fast-check ## Time clean and incremental debug builds for both
@CARGO="$(CARGO)" scripts/bench-build.sh

bench-config-load: ## Benchmark cached configuration loading without layer copies
RUSTFLAGS="$${RUSTFLAGS:+$$RUSTFLAGS }$(POLONIUS_FLAGS)" $(CARGO) bench --bench config_load_cached_merge
$(CARGO) bench --bench config_load_cached_merge

help: ## Show available targets
@grep -E '^[a-zA-Z_-]+:.*?##' $(MAKEFILE_LIST) | \
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ Netsuke currently requires:
- [Ninja](https://ninja-build.org/) on `PATH`;
- when installing from source, the dated Rust nightly toolchain pinned in
[`rust-toolchain.toml`](rust-toolchain.toml) (`rustup` installs it
automatically in a checkout). Netsuke builds with the Polonius borrow checker
(`-Zpolonius=next`), which is nightly-only until it stabilizes; see
automatically in a checkout). Netsuke builds with the Polonius borrow
checker, which nightly enables by default and which stays nightly-only until
it stabilizes; see
[ADR-006](docs/adr-006-adopt-polonius-nightly-toolchain.md).

### Installation
Expand All @@ -54,15 +55,14 @@ requirement below.
cargo binstall netsuke-build
```

Building from the registry instead runs outside a repository checkout, so
neither the pinned toolchain nor the Polonius flag is picked up automatically;
supply both explicitly:
Building from the registry instead runs outside a repository checkout, so the
pinned toolchain is not picked up automatically; select it explicitly:

<!-- tested-example: readme-crates-io-install -->

```sh
rustup toolchain install nightly-2026-06-25
RUSTFLAGS=-Zpolonius=next cargo +nightly-2026-06-25 install netsuke-build
rustup toolchain install nightly-2026-08-23
cargo +nightly-2026-08-23 install netsuke-build
```

Pre-built installers are available from the
Expand Down
25 changes: 25 additions & 0 deletions docs/adr-006-adopt-polonius-nightly-toolchain.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,28 @@ remains correct.
- `cargo +stable` invocations fail on `-Zpolonius=next`. This is intentional:
the failure is loud and immediate rather than a confusing borrowck error
later.

## Addendum — 2026-08-27: nightly-default Polonius and toolchain boundaries

The repository pin has since moved to `nightly-2026-08-23`. Nightlies dated
2026-08-04 and later enable the Polonius alpha analysis by default, so the pin
now carries the borrow-checker requirement without an explicit directive.

The explicit `-Zpolonius` plumbing from the original decision has been retired:
the `.cargo/config.toml` rustflags entry, the `POLONIUS_FLAGS` Makefile
variable, and the CI `with.rustflags` inputs were removed. The pin is now the
sole repository mechanism for this compiler behaviour.

Kani is outside that boundary. Kani 0.67.0 installs and uses its own bundled
`nightly-2025-11-21` toolchain through `cargo kani setup`. That toolchain
predates nightly-default Polonius, so Kani currently uses NLL. Moving the
repository Rust pin does not upgrade Kani. Do not claim that Kani verifies
`POLONIUS(...)` APIs with Polonius until a Kani release bundles a sufficiently
recent nightly, or Kani is rebuilt from source against that nightly.

Registry installs likewise do not inherit the checkout's toolchain file. They
must select the repository's pinned nightly explicitly, for example:

```sh
cargo +nightly-2026-08-23 install netsuke-build
```
Loading
Loading