No description
Find a file
andi fc6b0033f8 feat(eval/compiler): hand back an owning handle for a lambda context
`new_context` pushed a `LambdaCtx` and `compile_lambda_or_thunk` popped it
again thirty-seven lines later with `contexts.pop().unwrap()`, the pairing
held together by a comment. That is the shape of the scope leak I2b92b5c9
fixed, so give it the same treatment `ScopeGuard` gives scopes:
`new_context` returns a `#[must_use]` `ContextGuard` that only
`end_context` consumes, carrying the depth it was opened at so that
closing out of order is caught rather than silently rebalancing, and
whose `Drop` panics in debug builds.

This is a smaller guarantee than `ScopeGuard` gives, and the commit says
so rather than implying otherwise. There is exactly one `new_context`
call site, and the value `end_context` returns is needed by its caller,
so a context could not quietly be left open the way a scope could. What
the handle adds is the depth check, a `pop` that cannot be reached with
an empty stack of contexts, and a contract expressed in the type instead
of in prose.

The toplevel context is deliberately left out: `Compiler::new` creates it
directly, before there is a compiler to hand a guard to, and `compile`
closes it. Both ends now say so, and its `unwrap` becomes an `expect`
naming the invariant. Worth noting while here: that is also the one chunk
`expect_depth` never checks, because it is not built through
`compile_lambda_or_thunk`.

Six tests cover both guards, and writing them was worth it: the first
version of `ContextGuard::drop` panicked unconditionally, unlike
`ScopeGuard::drop` which checks `std:🧵:panicking()`. The
out-of-order test caught it immediately -- the assertion fired, the guard
dropped while unwinding, panicked again, and the process aborted with the
message it was supposed to report replaced by a double-panic. `Drop`
checking `panicking()` is what makes the ordering diagnostic survive, and
there is now a test that fails if either guard loses it.

Emitted bytecode is byte-for-byte identical across all 462 `.nix` files
under `eval/src/tests`, and `verify.sh` is unchanged on all three
benchmarks. Both guards are zero-sized in release.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPuy8HprhRG9nHvXzvgmWr
Change-Id: Ifc1a341fa8d491301cf06ef829a0ffa36b2c3da4
2026-08-30 16:09:24 +00:00
.gcroots feat(.envrc): gcroot third_party.sources 2022-09-15 11:27:53 +00:00
contrib chore(contrib/crunch-v2): regenerate Cargo.{lock,nix} 2026-08-28 12:37:17 +00:00
fun/snix-solves-this chore(snix.systems): drop tvix.systems 2026-04-29 12:08:42 +00:00
nix feat(readTree): allow use in imports with addMarkers = false; 2026-06-16 17:31:34 +00:00
ops chore(3p/nixpkgs): bump channels (2026-08-23) 2026-08-28 10:18:41 +00:00
snix feat(eval/compiler): hand back an owning handle for a lambda context 2026-08-30 16:09:24 +00:00
third_party chore(3p/nixpkgs): bump channels (2026-08-23) 2026-08-28 10:18:41 +00:00
tools chore(snix/shell): build evans lazily via depot-deps 2026-08-01 13:43:46 +00:00
web fix(web/content/binary-cache): drop footnote to nix path-info --json 2026-08-28 10:20:14 +00:00
.editorconfig feat(editorconfig): add global editorconfig 2025-03-19 11:35:35 +00:00
.envrc chore: fix unreleased direnv bug 2025-04-09 22:39:01 +00:00
.git-blame-ignore-revs chore: Update .git-blame-ignore-revs 2025-08-11 10:51:28 +00:00
.gitignore chore: add .direnv to gitignore 2025-04-12 18:12:35 +00:00
.gitreview chore: Introduce .gitreview file 2024-08-31 13:05:23 +00:00
.hgignore chore(hgignore): ignore .git for hg 2020-06-14 18:23:13 +00:00
.mailmap chore(mailmap): add edef 2025-04-01 18:47:29 +00:00
buf.gen.yaml fix(treewide): add missing final newlines 2025-03-21 13:33:32 +00:00
buf.yaml chore(buf): Use nixpkgs-provided buf 2022-10-21 18:39:03 +00:00
default.nix feat(ops): Add a fast checks buildkite pipeline 2026-05-24 18:19:32 +00:00
OWNERS chore: update OWNERS 2025-03-20 12:21:43 +00:00
prek.toml refactor(tools/treefmt): replace depotfmt with pkgs.treefmt.withConfig 2026-06-22 22:20:16 +00:00
README.md fix(docs): Fix more typos Nix and REAMDE 2026-05-12 07:35:36 +00:00
RULES feat(whitby): Let sterni bear the wheel 2021-05-23 19:06:15 +00:00
rustfmt.toml refactor(tools/treefmt): replace depotfmt with pkgs.treefmt.withConfig 2026-06-22 22:20:16 +00:00

Snix is a modern Rust re-implementation of the components of the Nix package manager.

For more information, checkout the website, hosted at snix.dev, which also is available in the web/ subdirectory of this repository.

It documents the status of this project, usage/development instructions, contact details and much more than what would fit in here. Seriously, check it out!

License structure

All Snix crates in this repository are licensed under GPL-3.0, with the exception of the protocol buffer definitions used for communication between services which are available under a more permissive license (MIT).

The idea behind this structure is that any direct usage of our code (e.g. linking to it, embedding the evaluator, etc.) will fall under the terms of the GPL3, but users are free to implement their own components speaking these protocols under the terms of the MIT license.

Other tooling in this repository might be licensed differently, and is usually described in the code itself, via some auxiliary metadata (Cargo.toml etc), or a LICENSE file in the same or parent folder(s). If this is not the case, please open a bug!