rer

r.e.r stands for the French phrase "Rez En Rust" — a pun on the Parisian suburban train, the réseau express régional d'Île-de-France.
What it is
rer is a Rust reimplementation of the solver hotpath of
rez, the VFX/animation
package manager.
The solver is a faithful port of rez's own phase-based backtracking solver
(rez/src/rez/solver.py) — not a different algorithm dressed up to look
similar. It reproduces rez's mechanics exactly: weak (~) and conflict (!)
requirement semantics, variant selection order, the extract / intersect /
reduce / split cycle, and implicit backtracking. The goal is output that
matches rez 1:1, not merely "a valid resolve".
The end goal is a hybrid integration: a Rust library callable from Python via PyO3 that accelerates rez resolves while leaving the rest of rez untouched.
Status
- ✅ Solver — complete and rez-faithful.
- ✅ Validated 1:1 — against rez's bundled 188-case benchmark dataset, every resolve matches rez's own recorded result exactly (same status, same package set).
- ✅ Fast — on that benchmark, on one machine,
rerresolves all 188 requests in ~44 s versus ~206 s for rez 3.3.0 (rez benchmark). Correctness is version-independent; the timing is same-machine context, not a lab claim. - ✅ Python bridge —
pyrer.solve(...)runs the ported solver (therer-pythoncrate ships to PyPI aspyrer—reris taken;pip install pyrer,import pyrer).
Workspace
A virtual Cargo workspace — use -p <crate> for crate-specific commands.
| Crate | Role |
|---|---|
rer-version |
RerVersion (rez token ordering) and VersionRange (rez range semantics over version-ranges). |
rer-resolver |
The solver. rez_solver is the rez port — Solver, ResolvePhase, PackageScope, the variant structures, Requirement/RequirementList. PackageData is the in-memory unit of the package repository. |
rer-python |
PyO3 bridge (Python import name pyrer, PyPI distribution pyrer), built into wheels by maturin. |
examples |
rez_benchmark_dataset — a timing report. |
rer works on an in-memory package repository (family → version → {requires, variants}); it does not read the filesystem itself — the host
(rez) hands the loaded data in.
Using it from Rust
use Rc;
use ;
use PackageData;
let mut repo = new;
// app-1.0.0 requires lib-2; lib has 1.0.0 and 2.0.0
repo.insert;
repo.insert;
let reqs = vec!;
let mut solver = new.unwrap;
solver.solve;
assert_eq!;
// resolves to app-1.0.0 + lib-2.0.0
Using it from Python
&&
&&
=
=
# "solved"
# [("app", "1.0.0", None), ("lib", "2.0.0", None)]
solve() reports failures and bad input via result.status
("solved" / "failed" / "error"), never as a Python exception.
Building & testing
The rez benchmark
The 1:1 differential test against rez's bundled benchmark is #[ignore]d (the
full release run takes several minutes). It needs the rez git submodule:
The benchmark CI workflow runs this on every PR touching the resolver.
License
See LICENSE.