From 2e75610c9123c29b477c53b72f2c875bc30469a6 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 7 Nov 2026 21:45:13 +0100 Subject: [PATCH] Rewrite the READMEs around the website documentation The website hosts the main documentation, but the READMEs linked it once and buried it. They now open with a link row and a table that routes each reader to the page answering their question, and the crate READMEs gain badges, a title that states what each crate is, and a license section. The crate README that crates.io and docs.rs show recommended the CGP Patterns book, which teaches v0.4.0 syntax and which the website rules exclude, so it now links the website instead. Three feature claims overstated what the library guarantees: provider selection adds nothing at runtime, wiring is checked when a check or a use forces it, and the `no_std` core holds when the chosen implementations support it. --- README.md | 165 +++++++++++++----- crates/macros/cgp-macro-test-util/README.md | 24 +-- crates/main/cgp/README.md | 42 ++++- .../error/cgp-error-anyhow/README.md | 12 +- .../standalone/error/cgp-error-eyre/README.md | 12 +- .../standalone/error/cgp-error-std/README.md | 12 +- crates/tests/README.md | 16 +- sibling-projects.md | 3 + 8 files changed, 213 insertions(+), 73 deletions(-) diff --git a/README.md b/README.md index cf4d6d2bc..ece5f6934 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,46 @@ -# Context-Generic Programming (CGP) +# Context-Generic Programming (CGP) for Rust [![Apache 2.0 Licensed](https://img.shields.io/badge/license-Apache_2.0-blue.svg)](https://github.com/contextgeneric/cgp/blob/main/LICENSE) [![Crates.io](https://img.shields.io/crates/v/cgp.svg)](https://crates.io/crates/cgp) +[![Docs.rs](https://docs.rs/cgp/badge.svg)](https://docs.rs/cgp) [![Tests](https://github.com/contextgeneric/cgp/actions/workflows/tests.yml/badge.svg)](https://github.com/contextgeneric/cgp/actions/workflows/tests.yml) ![Rust Stable](https://img.shields.io/badge/rustc-stable-blue.svg) ![Rust 1.89+](https://img.shields.io/badge/rustc-1.89+-blue.svg) **A language extension for Rust, with pluggable trait implementations at compile-time.** -Context-Generic Programming (CGP) is a library on stable Rust that lifts the language's one-implementation-per-type limit off your traits: it lets one interface have many interchangeable implementations and lets each *context* — an application, a test, a deployment — plug in the one it uses. The choice is written in one readable place and resolved entirely during compilation, so it compiles down to direct calls: there is no runtime container, no reflection, and nothing left in the binary for an implementation a context does not use. +Still ordinary Rust: a library on the stable toolchain, with provider selection resolved at compile +time, adopted one trait at a time. Beyond interchangeable implementations, CGP adds abstract types +chosen by each context, so error and runtime types need not be separate parameters through every +layer. It also supports extensible records and variants, and composable handlers. + +**[Website](https://contextgeneric.dev/) · [Quickstart](https://contextgeneric.dev/docs/quickstart) · [Tutorials](https://contextgeneric.dev/docs/tutorials/hello) · [Reference](https://contextgeneric.dev/docs/reference/) · [crates.io](https://crates.io/crates/cgp) · [API docs](https://docs.rs/cgp)** > [!IMPORTANT] -> This repository describes **v0.8.0**, which is **not compatible** with v0.7.0 — v0.8.0 changes and removes syntax that v0.7.0 used. **All documentation in this repository describes v0.8.0 only.** For v0.7.0, refer to its published crate documentation instead. +> This repository describes **v0.8.0**, which is **not compatible** with v0.7.0, because v0.8.0 changes and removes syntax that v0.7.0 used. **All documentation in this repository describes v0.8.0 only.** For v0.7.0, refer to its published crate documentation instead. -**[Website](https://contextgeneric.dev/) · [crates.io](https://crates.io/crates/cgp)** +## Install -## Key features +```bash +cargo add cgp +``` -CGP's headline promises are few and deliberately concrete. +Then bring everything into scope with a single import: -- **One interface, many implementations.** Write many interchangeable implementations of the same interface and choose between them per context — including the overlapping and orphan implementations Rust normally forbids, made safe because every choice is explicit and local. -- **Zero-cost abstraction.** Everything is resolved at compile time and compiles down to direct calls, so the flexibility costs nothing at runtime and unused implementations never reach the binary. -- **Type-safe wiring.** All wiring is checked at compile time, so a missing dependency is a build error rather than a runtime failure — in safe Rust, with no `dyn`, `Any`, or reflection. -- **Abstract over every dependency.** Write core logic that names its error type, runtime, and I/O abstractly and let each context supply the concrete choice, which keeps the core `no_std`-friendly — from embedded systems to WebAssembly. -- **Still ordinary Rust.** CGP is a superset of ordinary traits that you adopt one piece at a time: providers read like normal impls and implicit arguments like normal parameters, so a codebase can use it in one corner and stay otherwise vanilla. +```rust +use cgp::prelude::*; +``` + +CGP requires **Rust 1.89+** and runs on the **stable** toolchain, and needs neither a nightly toolchain nor a fork. The +[quickstart](https://contextgeneric.dev/docs/quickstart) takes it from there. ## A quick look -Real operations depend on infrastructure — a database, object storage — and the usual ways of supplying it do not scale. Passing each dependency as an argument threads long lists through every layer, while grouping them into a struct and adding methods locks the logic to that one concrete type, so it cannot be reused for a test, an embedded build, or a different backend. CGP lets you write the operation once against the capabilities a context provides. +Real operations depend on infrastructure such as a database or object storage, and the usual ways of +supplying it do not scale. Passing each dependency as an argument threads long lists through every +layer, while grouping them into a struct and adding methods locks the logic to that one concrete +type, so it cannot be reused for a test, an embedded build, or a different backend. CGP lets you +write the operation once against the dependencies a context provides. ```rust use cgp::prelude::*; @@ -42,7 +55,7 @@ pub struct App { // Write the operation once. `#[implicit]` reads `database` from the context; // `user_id` stays an ordinary argument. Any context carrying a matching -// `database` field gains `get_user` — no wiring, no trait impls to write. +// `database` field gains `get_user` without wiring or trait impls. #[cgp_fn] #[async_trait] pub async fn get_user( @@ -54,7 +67,9 @@ pub async fn get_user( } ``` -`get_user` reads like an ordinary async function, yet it works on any context with a matching field — checked at compile time, so a context missing `database` is a build error rather than a runtime failure. When a step needs *more than one* implementation, promote it to a component and let each context pick a provider: +`get_user` reads like an ordinary async function, yet it works on any context with a matching field, checked at compile time, so a context missing +`database` is a build error rather than a runtime failure. When a step needs *more than one* implementation, promote it to a component and let each +context pick a provider: ```rust // One interface... @@ -87,70 +102,130 @@ delegate_components! { } ``` -`App` fetches from Amazon S3, and `GCloudApp` — a context carrying a Google Cloud storage client instead — fetches from Google Cloud. Neither pays for `dyn` or runtime dispatch, the choice is a single greppable line, and code that calls `self.fetch_storage_object(..)` never changes. (Method bodies are elided here for brevity.) +`App` fetches from Amazon S3, and `GCloudApp`, a context carrying a Google Cloud storage client +instead, fetches from Google Cloud. Neither uses `dyn` or runtime dispatch, the choice is one +line that a search finds, and code that calls `self.fetch_storage_object(..)` never changes. (Method +bodies are elided here for brevity.) -## Installation +## Key features -Add the latest stable release with Cargo: +- **One interface, many implementations.** Write interchangeable implementations of one interface and choose between them per application. Separate provider types let implementations coexist while each application makes its choice explicit. +- **Zero-cost abstraction.** Provider selection resolves at compile time and compiles down to direct calls, without a runtime container or vtable lookup, and unused providers are never instantiated. The selected code still does its own work. +- **Type-safe wiring.** Check the wiring at compile time, with `check_components!` or by using the component, so a missing dependency fails the build rather than a call, in safe Rust, without `dyn`, `Any`, or reflection. +- **Abstract over every dependency.** Write core logic that names its error type, runtime, and I/O abstractly and let each context supply the concrete choice, which keeps the core `no_std`-friendly when the chosen implementations support it. +- **Still ordinary Rust.** Adopt CGP one component at a time: providers use familiar impl syntax, implicit arguments resemble parameters, and consumer traits can still be implemented directly. -```bash -cargo add cgp -``` +## Learn CGP -then bring everything into scope with a single import: +The documentation lives on the website, **[contextgeneric.dev](https://contextgeneric.dev/)**, and +each part answers a different question. -```rust -use cgp::prelude::*; -``` +| To… | Read | +| --- | --- | +| Get something running | [Quickstart](https://contextgeneric.dev/docs/quickstart) | +| Learn by building | [Tutorials](https://contextgeneric.dev/docs/tutorials/hello): a first program, then [area calculation](https://contextgeneric.dev/docs/tutorials/area-calculation) | +| Understand why CGP works this way | [Concepts](https://contextgeneric.dev/docs/concepts/): [consumer and provider traits](https://contextgeneric.dev/docs/concepts/consumer-and-provider-traits), [impl-side dependencies](https://contextgeneric.dev/docs/concepts/impl-side-dependencies), [coherence](https://contextgeneric.dev/docs/concepts/coherence), [namespaces](https://contextgeneric.dev/docs/concepts/namespaces) | +| Look up a construct | [Reference](https://contextgeneric.dev/docs/reference/): one page per macro, attribute, derive, provider, and trait | +| Compare it with what you know | [Comparisons](https://contextgeneric.dev/docs/comparisons/): dependency injection, type classes, ML modules, dynamic dispatch, and more | +| See it in a real program | [Projects](https://contextgeneric.dev/docs/projects/) | +| Choose how much CGP a problem needs | [The modularity hierarchy](https://contextgeneric.dev/docs/concepts/modularity-hierarchy) | -CGP requires **Rust 1.89+** and runs on the **stable** toolchain — no nightly, no fork. +## Readable errors: cargo-cgp -### Install cargo-cgp for readable errors - -CGP compiles to ordinary Rust, so a wiring mistake surfaces as a compiler error about generated types — often a wall of them with the real cause buried. **When you start with CGP, install [`cargo-cgp`](https://github.com/contextgeneric/cargo-cgp) alongside it.** cargo-cgp is CGP's error toolchain: a drop-in for `cargo check` that rewrites those errors into a compact, root-cause-first form, leading with the field or wiring that actually failed. It is the single biggest quality-of-life improvement for writing CGP, so treat it as part of your getting-started setup. +CGP compiles to ordinary Rust, so a wiring mistake surfaces as a compiler error about generated +types, often many errors with the real cause hard to find. **When you start with CGP, install +[`cargo-cgp`](https://github.com/contextgeneric/cargo-cgp) alongside it.** It is CGP's error +toolchain: a drop-in for `cargo check` that rewrites those errors into a compact, root-cause-first +form, leading with the field or wiring that actually failed. `cargo cgp check` leads with the root +cause for the classes it recognizes, and the tool does not yet reshape every class. ```bash cargo install --locked cargo-cgp # the front-end (needs Rust 1.96 or newer) cargo cgp setup # provisions the compiler + driver it needs ``` -Then run `cargo cgp check` wherever you would run `cargo check`; it forces the pinned nightly that `cargo cgp setup` installed only for its own check, so your project keeps its toolchain untouched. (Prefer Nix? `nix run github:contextgeneric/cargo-cgp/v0.1.0 -- check` runs it without installing.) See its [README](https://github.com/contextgeneric/cargo-cgp) for the full guide. +Then run `cargo cgp check` wherever you would run `cargo check`; it forces the pinned nightly that +`cargo cgp setup` installed only for its own check, so your project keeps its toolchain untouched. +(Prefer Nix? `nix run github:contextgeneric/cargo-cgp/v0.1.0 -- check` runs it without installing.) +The [installation guide](https://contextgeneric.dev/docs/cargo-cgp/installation) covers every path, +[reading the output](https://contextgeneric.dev/docs/cargo-cgp/reading-output) explains the rewritten +errors, and the [error codes](https://contextgeneric.dev/docs/cargo-cgp/error-codes) catalog every +`[CGP-Exxx]` code. -cargo-cgp is optional and adds only the reading commands `check` and `expand`: keep building, running, and testing with ordinary cargo, since CGP is a plain library needing only stable Rust (1.89+), and reach for `cargo cgp check` when you want a wiring error made readable. Plain `cargo check` still works too, and is fine when you are not expecting a compile error. +cargo-cgp is optional and adds only the reading commands `check` and `expand`: keep building, +running, and testing with ordinary cargo, since CGP is a plain library needing only stable Rust +(1.89+), and reach for `cargo cgp check` when you want a wiring error made readable. Plain +`cargo check` still works too, and is fine when you are not expecting a compile error. -## When to use CGP — and when not +## When to use CGP, and when not -CGP is a tool with a boundary, and it earns its cost only past that boundary. The rule of thumb is to **reach for CGP when a capability needs more than one implementation and the choice belongs to the context — not before.** Concretely: +CGP is a tool with a boundary, and it earns its cost only past that boundary. The rule of thumb is to +**reach for CGP when an interface needs more than one implementation and the choice belongs to the +context, and not before.** Concretely: - **One implementation?** Use a plain trait or function. CGP would be over-engineering. - **A small, closed set of variants?** Use an `enum` and a `match`. -- **Implementations chosen at runtime** — plugins, config-driven selection, heterogeneous collections? Use `dyn Trait`; CGP resolves everything at compile time and gives up that runtime openness by design. -- **One implementation must be globally unique** — a single `Ord` for a map key, say? A coherent trait is the right tool; CGP's per-context choice is deliberately not global. +- **Implementations chosen at runtime**, such as plugins, config-driven selection, or heterogeneous collections? Use `dyn Trait`; CGP resolves everything at compile time and gives up that runtime openness by design. +- **One implementation must be globally unique**, as with a single `Ord` for a map key? A coherent trait is the right tool; CGP's per-context choice is deliberately not global. -CGP is a *superset* of ordinary traits, so adopting it is a climb from the plainer tool rather than a rejection of it. You can use it exactly where it pays and leave the rest of a codebase unchanged. +CGP is a *superset* of ordinary traits, so adopting it starts from the plainer tool rather than +replacing it. You can use it exactly where it pays and leave the rest of a codebase unchanged. The +[modularity hierarchy](https://contextgeneric.dev/docs/concepts/modularity-hierarchy) works through +the choice in more detail. -## Documentation +The costs are real and worth stating beside the benefits: more declarations and wiring, extra +compile-time work, verbose raw diagnostics, and concepts to learn. A delegation entry alone does not +verify its provider's dependencies, so add a check or use the component to force verification. + +## Project status -Learn CGP at the project website, **[contextgeneric.dev](https://contextgeneric.dev/)**, which hosts the guides, worked examples, and project blog. +CGP works today on stable Rust and already offers a broad feature set: components and providers, +abstract types, extensible records and variants, a handler and computation family, namespaces, and +modular error handling. It is also young, with the paradigm and its ecosystem still evolving, so +adopting it is a real decision rather than a foregone one. -> [!NOTE] -> The crates' API docs on `docs.rs` are still sparse. The website is the place to start while the inline documentation is filled in. +Two properties make it low-risk to try. Because CGP is a superset of ordinary traits, it can be +introduced in one corner of a codebase and stepped back from without a rewrite; and because it +adds nothing at runtime, it does not lock a project into a framework's lifecycle. If you are evaluating it +for a team, start small, and use the worked examples on the +[website](https://contextgeneric.dev/docs/projects/) to gauge the learning curve honestly. + +## Documentation -Contributors and coding agents have a second, deeper source: the [CGP knowledge base](https://github.com/contextgeneric/cgp-knowledge-base), which holds the exhaustive per-construct reference, the concept overviews, the writing guides, the compile-error catalog, the worked examples, and the internals of the macros in this repository. It is written for AI agents rather than for learners, so start at the website if you are learning CGP and reach for the knowledge base when you need the exact semantics of a construct or are changing this repository. Start from [AGENTS.md](AGENTS.md) for the conventions this repository follows, and [sibling-projects.md](sibling-projects.md) for the related repositories. +The [website](https://contextgeneric.dev/) is the main documentation: the quickstart, the tutorials, +the concepts, the construct reference, the comparisons, and the project pages. The crates' API +documentation on [docs.rs](https://docs.rs/cgp) covers the items themselves. -## Project status +> [!NOTE] +> The crates' API docs on `docs.rs` are still sparse. The website is the place to start while the +> inline documentation is filled in. -CGP works today on stable Rust and already offers a broad feature set: components and providers, abstract types, extensible records and variants, a handler and computation family, namespaces, and modular error handling. It is also young — the paradigm and its ecosystem are still evolving — so adopting it is a real decision rather than a foregone one. +Contributors and coding agents have a second, deeper source: the +[CGP knowledge base](https://github.com/contextgeneric/cgp-knowledge-base), which holds the +exhaustive per-construct reference, the concept overviews, the writing guides, the compile-error +catalog, the worked examples, and the internals of the macros in this repository. It is written for +AI agents rather than for learners, so start at the website if you are learning CGP and reach for the +knowledge base when you need the exact semantics of a construct or are changing this repository. The +[`/cgp` agent skill](https://contextgeneric.dev/docs/ai/skills/) teaches an assistant to read and +write CGP; it does not remove the reviewer's need to understand the code. -Two properties make it low-risk to try. Because CGP is a superset of ordinary traits, it can be introduced in one corner of a codebase and stepped back from without a rewrite; and because it imposes no runtime, it does not lock a project into a framework's lifecycle. If you are evaluating it for a team, start small, and lean on the worked examples on the [website](https://contextgeneric.dev/) to gauge the learning curve honestly. +Start from [AGENTS.md](AGENTS.md) for the conventions this repository follows, and +[sibling-projects.md](sibling-projects.md) for the related repositories. ## How the project is organized -CGP is a collection of small, layered crates, arranged so that low-level primitives stay independent of the high-level facade. Most users depend only on the single **`cgp`** crate, which re-exports the core and extra functionality through `cgp::prelude`. Pluggable error backends are opt-in as separate crates — `cgp-error-anyhow`, `cgp-error-eyre`, and `cgp-error-std`. Browse [`crates/`](crates) for the full layout. +CGP is a collection of small, layered crates, arranged so that low-level primitives stay independent +of the high-level facade. Most users depend only on the single **`cgp`** crate, which re-exports the +core and extra functionality through `cgp::prelude`. Pluggable error backends are opt-in as separate +crates: `cgp-error-anyhow`, `cgp-error-eyre`, and `cgp-error-std`. Browse [`crates/`](crates) for +the full layout. ## Contributing -Contributions, questions, and bug reports are welcome. Open an [issue](https://github.com/contextgeneric/cgp/issues) or a pull request, and see the [website](https://contextgeneric.dev/) to get oriented first. Unless stated otherwise, contributions are made under the terms of the Apache-2.0 license below. +Contributions, questions, and bug reports are welcome. Open an +[issue](https://github.com/contextgeneric/cgp/issues) or a pull request, and read the +[contribute page](https://contextgeneric.dev/docs/contribute) to get oriented first. Unless stated +otherwise, contributions are made under the terms of the Apache-2.0 license below. ### Development diff --git a/crates/macros/cgp-macro-test-util/README.md b/crates/macros/cgp-macro-test-util/README.md index 1c436069d..1d5a91d5b 100644 --- a/crates/macros/cgp-macro-test-util/README.md +++ b/crates/macros/cgp-macro-test-util/README.md @@ -1,12 +1,14 @@ -# `cgp-macro-test-util` +# cgp-macro-test-util: snapshot-testing macros for the CGP macros -Snapshot-testing macros for the CGP procedural macros. +**The macros that pin the code the CGP procedural macros generate, as inline `insta` snapshots.** + +**[Website](https://contextgeneric.dev/) · [Reference](https://contextgeneric.dev/docs/reference/) · [Implementation record](https://github.com/contextgeneric/cgp-knowledge-base/blob/main/cgp/implementation/entrypoints/snapshot_macros.md)** This crate exposes a family of `snapshot_*!` procedural macros that pin the code the core CGP macros generate. Each one does **two** things at once: it emits the real generated code into the surrounding module, exactly as the underlying CGP macro -would — so the traits, structs, and impls stay live and the rest of the module can -still wire them up and assert their runtime behavior — and it generates a `#[test]` +would, so the traits, structs, and impls stay live and the rest of the module can +still wire them up and assert their runtime behavior, and it generates a `#[test]` that asserts a pretty-printed string of that same code against an inline [`insta`](https://insta.rs) snapshot. Adding or removing a snapshot therefore changes only the golden assertion, never the compile-time or runtime coverage. @@ -15,7 +17,7 @@ Two documents carry what this README does not. The [implementation document](https://github.com/contextgeneric/cgp-knowledge-base/blob/main/cgp/implementation/entrypoints/snapshot_macros.md) in the knowledge base explains how the macros are built and what an invocation expands to; [crates/tests/AGENTS.md](../../tests/AGENTS.md) sets the convention for -*when* to snapshot — a macro's expansion is pinned only in the concept target that +*when* to snapshot: a macro's expansion is pinned only in the concept target that owns that macro's feature, and written plainly everywhere else. ## Crate layout @@ -63,9 +65,9 @@ so a snapshot is guaranteed to show what the production macros generate. | `snapshot_cgp_producer!` | `#[cgp_producer]` | | `snapshot_cgp_auto_dispatch!` | `#[cgp_auto_dispatch]` | -Each accepts the same argument forms as the macro it wraps — `snapshot_cgp_component!` -takes both `#[cgp_component(Greeter)]` and the brace form, for instance — precisely -because it drives the production entry function. +Each accepts the same argument forms as the macro it wraps, because it drives the +production entry function; `snapshot_cgp_component!` takes both +`#[cgp_component(Greeter)]` and the brace form, for instance. ## Anatomy of an invocation @@ -90,9 +92,9 @@ snapshot_cgp_getter! { } ``` -That emits the real `#[cgp_getter]` expansion — the consumer trait and its blanket -impl, the provider trait, the marker struct, and the `UseField`/`UseFields`/ -`RedirectLookup` provider impls — and then a `fn expand_has_name()` holding the same +That emits the real `#[cgp_getter]` expansion, which is the consumer trait and its +blanket impl, the provider trait, the marker struct, and the `UseField`/`UseFields`/ +`RedirectLookup` provider impls, and then a `fn expand_has_name()` holding the same code as a string. The test-function name must be unique within its module, so give each snapshot in a file a distinct one. diff --git a/crates/main/cgp/README.md b/crates/main/cgp/README.md index 8236647a7..2a2fe2eb7 100644 --- a/crates/main/cgp/README.md +++ b/crates/main/cgp/README.md @@ -1,13 +1,41 @@ -# `cgp` — Context-Generic Programming in Rust +# `cgp`: Context-Generic Programming in Rust -## Overview +**A language extension for Rust, with pluggable trait implementations at compile-time.** -Context-Generic Programming (CGP) is a language extension for Rust, with pluggable trait implementations at compile-time. In ordinary Rust a trait has one implementation per type; CGP lets one trait have many interchangeable implementations and lets each *context* choose which one it uses, through a small wiring table the compiler resolves statically — so the flexibility costs nothing at runtime. The `cgp` crate is the facade over a collection of micro crates that provide it, and it re-exports everything through `cgp::prelude`. +The `cgp` crate is the facade over the collection of crates that provide CGP, and it re-exports +everything through `cgp::prelude`. In ordinary Rust a trait has one implementation per type; CGP lets +one trait have many interchangeable implementations and lets each *context* choose which one it uses, +through a small wiring table the compiler resolves statically, so provider selection adds nothing at +runtime. -To learn more, see the website [contextgeneric.dev](https://contextgeneric.dev/) and the book [Context-Generic Programming Patterns](https://patterns.contextgeneric.dev/). +## Learn CGP -
+The documentation lives on the website, [contextgeneric.dev](https://contextgeneric.dev/): -The `cgp` constructs are still mostly undocumented within Rustdoc. The best way to learn CGP today is the book [Context-Generic Programming Patterns](https://patterns.contextgeneric.dev/); for the exhaustive per-construct semantics, see the [CGP knowledge base](https://github.com/contextgeneric/cgp-knowledge-base). +- [Quickstart](https://contextgeneric.dev/docs/quickstart): install it and run a first program. +- [Tutorials](https://contextgeneric.dev/docs/tutorials/hello): learn by building. +- [Concepts](https://contextgeneric.dev/docs/concepts/): why CGP works the way it does. +- [Reference](https://contextgeneric.dev/docs/reference/): one page per construct. -
+The API documentation here covers the items themselves; the website explains how to use them. For the +exhaustive per-construct semantics, the +[CGP knowledge base](https://github.com/contextgeneric/cgp-knowledge-base) is written for agents and +records the internals. + +## Install + +```bash +cargo add cgp +``` + +```rust +use cgp::prelude::*; +``` + +CGP requires Rust 1.89+ and runs on the stable toolchain. When you start with CGP, install +[`cargo-cgp`](https://github.com/contextgeneric/cargo-cgp) alongside it: `cargo cgp check` leads with +the root cause for the classes it recognizes, and the tool does not yet reshape every class. + +## License + +Licensed under the [Apache License, Version 2.0](https://github.com/contextgeneric/cgp/blob/main/LICENSE). diff --git a/crates/standalone/error/cgp-error-anyhow/README.md b/crates/standalone/error/cgp-error-anyhow/README.md index a638ab159..dcb64b997 100644 --- a/crates/standalone/error/cgp-error-anyhow/README.md +++ b/crates/standalone/error/cgp-error-anyhow/README.md @@ -1,10 +1,16 @@ -# cgp-error-anyhow +[![Crates.io](https://img.shields.io/crates/v/cgp-error-anyhow.svg)](https://crates.io/crates/cgp-error-anyhow) +[![Docs.rs](https://docs.rs/cgp-error-anyhow/badge.svg)](https://docs.rs/cgp-error-anyhow) +![License](https://img.shields.io/badge/license-Apache_2.0-blue.svg) + +# cgp-error-anyhow: anyhow as a context's error type `cgp-error-anyhow` makes [`anyhow::Error`](https://docs.rs/anyhow) the abstract error type of a [CGP](https://contextgeneric.dev) context, and supplies the providers that raise errors into it and add context to it. Code written against `HasErrorType`, `CanRaiseError`, and `CanWrapError` stays generic; only the context's wiring names anyhow. +**[Website](https://contextgeneric.dev/) · [Modular error handling](https://contextgeneric.dev/docs/concepts/modular-error-handling) · [The error components](https://contextgeneric.dev/docs/reference/components/has_error_type) · [Project record](https://github.com/contextgeneric/cgp-knowledge-base/blob/main/projects/error/README.md)** + | Provider | Wire it to | What it does | |---|---|---| | `UseAnyhowError` | `ErrorTypeProviderComponent` | sets the context's `Error` to `anyhow::Error` | @@ -43,3 +49,7 @@ feature. Enabling that feature elsewhere in the dependency graph turns on the pa need `std`, such as backtrace capture. The crate re-exports `anyhow::Error` as `cgp_error_anyhow::Error`. + +## License + +Licensed under the [Apache License, Version 2.0](https://github.com/contextgeneric/cgp/blob/main/LICENSE). diff --git a/crates/standalone/error/cgp-error-eyre/README.md b/crates/standalone/error/cgp-error-eyre/README.md index 8a1532c56..8b7c3b48f 100644 --- a/crates/standalone/error/cgp-error-eyre/README.md +++ b/crates/standalone/error/cgp-error-eyre/README.md @@ -1,10 +1,16 @@ -# cgp-error-eyre +[![Crates.io](https://img.shields.io/crates/v/cgp-error-eyre.svg)](https://crates.io/crates/cgp-error-eyre) +[![Docs.rs](https://docs.rs/cgp-error-eyre/badge.svg)](https://docs.rs/cgp-error-eyre) +![License](https://img.shields.io/badge/license-Apache_2.0-blue.svg) + +# cgp-error-eyre: eyre as a context's error type `cgp-error-eyre` makes [`eyre::Report`](https://docs.rs/eyre) the abstract error type of a [CGP](https://contextgeneric.dev) context, and supplies the providers that raise errors into it and add context to it. Code written against `HasErrorType`, `CanRaiseError`, and `CanWrapError` stays generic; only the context's wiring names eyre. +**[Website](https://contextgeneric.dev/) · [Modular error handling](https://contextgeneric.dev/docs/concepts/modular-error-handling) · [The error components](https://contextgeneric.dev/docs/reference/components/has_error_type) · [Project record](https://github.com/contextgeneric/cgp-knowledge-base/blob/main/projects/error/README.md)** + | Provider | Wire it to | What it does | |---|---|---| | `UseEyreError` | `ErrorTypeProviderComponent` | sets the context's `Error` to `eyre::Report` | @@ -48,3 +54,7 @@ error. The crate also enables eyre's `track-caller` feature, and CGP's `raise_er `std`, so this crate does too. The crate re-exports `eyre::Error`, eyre's alias for `Report`, as `cgp_error_eyre::Error`. + +## License + +Licensed under the [Apache License, Version 2.0](https://github.com/contextgeneric/cgp/blob/main/LICENSE). diff --git a/crates/standalone/error/cgp-error-std/README.md b/crates/standalone/error/cgp-error-std/README.md index 039d38f50..81e82e59f 100644 --- a/crates/standalone/error/cgp-error-std/README.md +++ b/crates/standalone/error/cgp-error-std/README.md @@ -1,10 +1,16 @@ -# cgp-error-std +[![Crates.io](https://img.shields.io/crates/v/cgp-error-std.svg)](https://crates.io/crates/cgp-error-std) +[![Docs.rs](https://docs.rs/cgp-error-std/badge.svg)](https://docs.rs/cgp-error-std) +![License](https://img.shields.io/badge/license-Apache_2.0-blue.svg) + +# cgp-error-std: a boxed standard error as a context's error type `cgp-error-std` makes a boxed standard error, `Box`, the abstract error type of a [CGP](https://contextgeneric.dev) context, and supplies the providers that raise errors into it and add context to it. It depends only on `cgp` and `alloc`, so it suits a `no_std` context that still wants an open-ended error type. +**[Website](https://contextgeneric.dev/) · [Modular error handling](https://contextgeneric.dev/docs/concepts/modular-error-handling) · [The error components](https://contextgeneric.dev/docs/reference/components/has_error_type) · [Project record](https://github.com/contextgeneric/cgp-knowledge-base/blob/main/projects/error/README.md)** + | Item | Wire it to | What it does | |---|---|---| | `UseBoxedStdError` | `ErrorTypeProviderComponent` | sets the context's `Error` to `cgp_error_std::Error` | @@ -45,3 +51,7 @@ A `WrapError` prints its detail alone with `{}`, so a reporter that walks `sourc message once, and prints the whole chain with `{:#}` or `{:?}`. A `String` needs `DisplayBoxedStdError` or `DebugBoxedStdError`, because it is not a standard error, and `DebugBoxedStdError` prints it with quotes. + +## License + +Licensed under the [Apache License, Version 2.0](https://github.com/contextgeneric/cgp/blob/main/LICENSE). diff --git a/crates/tests/README.md b/crates/tests/README.md index e6d4b9cae..8b4eb5917 100644 --- a/crates/tests/README.md +++ b/crates/tests/README.md @@ -1,13 +1,15 @@ -# CGP test suite +# CGP test suite: the tests organized by CGP concept This directory holds the test suite for Context-Generic Programming, organized **by -CGP concept** — basic delegation, abstract types, implicit arguments, namespaces, -and so on — rather than by the macro that implements each concept, because a single +CGP concept**, such as basic delegation, abstract types, implicit arguments, or namespaces, +rather than by the macro that implements each concept, because a single macro such as `delegate_components!` serves many concepts at once. This README is the map of what is here and how to run it; [AGENTS.md](AGENTS.md) is the authoritative guide to the conventions, and you should read it before adding, moving, or refactoring a test. +**[Website](https://contextgeneric.dev/) · [Reference](https://contextgeneric.dev/docs/reference/) · [Implementation record](https://github.com/contextgeneric/cgp-knowledge-base/blob/main/cgp/implementation/README.md)** + ## The crates The suite is split into two crates, each with a distinct job. @@ -18,8 +20,8 @@ by compiling. It is also where the user-facing macros are exercised end-to-end a where the canonical macro-expansion snapshots live. **`cgp-macro-tests`** tests the macro internals directly against `cgp-macro-core` -(the parsers and AST types), and is the home for **rejection cases** — inputs CGP -refuses during expansion — and for pinning the invalid tokens a macro currently +(the parsers and AST types), and is the home for **rejection cases**, the inputs CGP +refuses during expansion, and for pinning the invalid tokens a macro currently emits. A third category lives in another repository: the cases where a macro *accepts* @@ -31,7 +33,7 @@ so each is pinned as the readable error the tool renders for it. AGENTS.md's ## How the tests are laid out Inside `cgp-tests`, each concept is one **integration test target**, which Cargo -compiles as its own crate — and therefore its own coherence scope. A target is an +compiles as its own crate, and therefore its own coherence scope. A target is an entrypoint file `tests/_tests.rs` plus a module directory `tests//` holding one `.rs` file per unit test, each self-contained so the type-level wiring of one test never leaks into another. `tests/basic_delegation/` @@ -62,6 +64,6 @@ cargo insta test -p cgp-tests --accept # accept intended snapshot chang Many tests assert the exact code a macro generates, through the `snapshot_*!` macros from `cgp-macro-test-util`: each emits the real generated code into the module *and* generates a `#[test]` asserting a pretty-printed inline `insta` -snapshot of it. So a failing snapshot prints a diff of the generated code — accept +snapshot of it. A failing snapshot prints a diff of the generated code, so accept it with `cargo insta` only after confirming the change is intended. Which target owns a given macro's snapshot is a convention AGENTS.md sets out. diff --git a/sibling-projects.md b/sibling-projects.md index 022de2b54..bfd1e9f95 100644 --- a/sibling-projects.md +++ b/sibling-projects.md @@ -16,6 +16,9 @@ and the worked examples sit at the knowledge base's top level. | `cgp-skills` | | `main` | The agent skills for CGP, deployed on their own, the `/cgp` skill among them. | | `cgp-knowledge-base` | | `main` | The consolidated documentation for every CGP project, written by and for AI agents. | +The knowledge base's [sibling-projects.md](https://github.com/contextgeneric/cgp-knowledge-base/blob/main/sibling-projects.md) is the authoritative list of the whole ecosystem, +including the projects that are not part of the core. + ## Finding a sibling Look for a sibling in the parent directory first, at `../`. Every project in this list,