Skip to content

AI Updates #5: #[default_impl] fix, a span audit, and a new guides section#253

Merged
soareschen merged 6 commits into
mainfrom
ai-updates-5
Jul 5, 2026
Merged

AI Updates #5: #[default_impl] fix, a span audit, and a new guides section#253
soareschen merged 6 commits into
mainfrom
ai-updates-5

Conversation

@soareschen

@soareschen soareschen commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

AI Overview

This PR does two loosely-coupled things. It hardens the CGP macros' error behavior — fixing one real bug in namespace default registration and pinning a set of span, coherence, and orphan-rule behaviors with compile-fail regression tests — and it restructures the knowledge base by adding a fourth top-level guides section that absorbs the old modern-idioms content and grows new namespace and debugging guides. There is one source-code change; everything else is tests and documentation. The branch is five commits ahead of main, touching 38 files (+1441 / −343), with no source behavior removed and nothing that requires a version edit.

The code change: #[default_impl] drops the provider's where clause

The one behavioral fix corrects how #[default_impl] builds its namespace-registration impl. That attribute registers a provider as a namespace's per-component default by emitting impl Namespace<..> for PathKey { type Delegate = Provider; }, and it builds that impl from the provider impl's generics. The problem is that by the time it runs, those generics already carry the impl-side bounds that #[use_type], #[uses], #[implicit], and #[use_provider] push onto Self — a provider using #[use_type(HasErrorType.Error)], for example, arrives carrying where Self: HasErrorType. On the registration impl, Self is the path key PathCons<..>, not the context, so a leaked Self: HasErrorType becomes the demand PathCons<..>: HasErrorType, which never resolves. The result was that any provider with an impl-side dependency silently failed to route through the namespace, breaking every context that joined it. The fix clears the where clause before splitting the generics, keeping only the parameters that name the key and the provider plus the __Components__ table. This is the sole change in attribute.rs, guarded by a new regression test that exercises a #[default_impl] provider carrying both a #[use_type] abstract-type dependency and an #[implicit] field read.

The compile-fail audit: four new fixtures pinning spans and coherence

The PR adds four trybuild fixtures under cgp-compile-fail-tests, all in the acceptable/ tree — meaning each is a failure CGP deliberately defers to the Rust compiler rather than a case the macro should reject, so the fixture guards the caret position and message, not a new rejection. Two are span-regression tests: duplicate_component_name pins that a name clash on a derived component marker reports its E0428 note on the provider name the user wrote inside #[cgp_component(..)] rather than on the whole attribute, and missing_dependency pins that check_components! lands its E0277 caret on the failing component inside the block rather than on the shared context token. The other two document coherence and orphan-rule limits of namespaces: override_registered_path pins that a context cannot re-wire a path its joined namespace already registers (an E0119 overlap), and default_impl_foreign_prefix_path pins that a downstream crate cannot register a default for a prefixed upstream component, because the path key is entirely foreign (an E0210 orphan violation). Supporting these, cgp-compile-fail-tests gains a dependency on cgp-test-crate-a, and one unrelated stderr snapshot (option_slice.stderr) is refreshed to match a newer compiler's more detailed diagnostics.

The cross-crate tests: a fourth namespace ability

The cross-crate coherence suite grows from three demonstrated abilities to four. cgp-test-crate-a now declares a shared AppNamespace inheriting DefaultNamespace, and cgp-test-crate-b registers a local component and provider into that upstream namespace with #[default_impl], then joins the namespace and resolves the capability through it with no direct wiring. This is orphan-safe precisely because the downstream crate owns the component key even though it does not own the namespace — the complement of the default_impl_foreign_prefix_path fixture, which shows the case that is not orphan-safe.

The documentation restructuring: a new guides section

The largest structural change is a new fourth top-level documentation section, docs/guides/, sitting alongside reference, concepts, and examples. The four sections now answer four distinct questions: reference says what a construct is, concepts explain an idea, examples show a construct solving a problem, and a guide is prescriptive — it recommends a default form, names the trade-offs of the alternatives, and usually walks a concrete before/after refactoring. The old docs/concepts/modern-idioms.md migration guide (215 lines) is removed, and its content is redistributed across granular new guides: writing providers, declaring dependencies, reading context fields, importing abstract types, capability supertraits, and dispatching per type. Two entirely new guides join them: a large namespaces-and-prefixes guide that works keeping a growing wiring table short as a real refactoring, and a debugging guide for tracing a lazy-wiring failure back to its cause. The section indexes and authoring rules are updated to match — docs/README.md (three to four sections), docs/AGENTS.md (a new guides-directory rule), and the concepts and examples READMEs.

The example and reference updates

The money-transfer-api example is substantially rewritten to carry the new material end to end. It gains a status-coded errors section and reorganizes its context wiring around a namespace (a renamed and expanded "Organizing the wiring with a namespace" section), so the example now demonstrates the constructs the new guides recommend. In parallel, the implementation and reference documents that describe the fixed and pinned behaviors are updated in the same change, per the knowledge base's synchronization rule: the #[default_impl] where-clause behavior is documented in the attributes implementation doc, the default_namespace reference, and the namespaces sub-skill; new Failure modes sections are added to the cgp_component and check_components implementation docs; and a Known issues note on namespace override overlap is added to the cgp_namespace reference.

Impacts

The following are the concrete effects a reviewer or user should expect from merging this PR.

  • #[default_impl] now works with dependency-carrying providers. A provider that uses #[use_type], #[uses], #[implicit], or #[use_provider] can be registered as a namespace default and will resolve correctly; previously it compiled but silently failed to route, breaking every context that joined the namespace.
  • Span behavior for two macros is now locked by regression tests. The derived-marker note position of #[cgp_component] and the unsatisfied-dependency caret of check_components! are pinned by .stderr snapshots, so a future regression to Span::call_site() changes a snapshot instead of silently degrading compiler and IDE navigation.
  • Two namespace limits are now documented and test-backed. The overlap when a context tries to override a namespace-registered path, and the orphan-rule confinement of a prefixed component's default to the namespace's own crate, are both captured as fixtures and written up in the reference, guides, and skill.
  • The cross-crate suite covers a fourth coherence ability, giving downstream registration of a local component into an upstream namespace an executable guarantee.
  • A new documentation section exists to maintain. Guides are bound by the same synchronization rule as everything else, so their code snippets must keep compiling against current CGP; the concept index no longer lists modern-idioms, and links pointing at it must resolve to the new guides.
  • The money-transfer example changed shape. Any document, snippet, or link that referenced its old "Wiring a context" section or its previous structure now points at the namespace-organized and status-coded-error version.
  • A new test-crate dependency and test module are wired in. cgp-compile-fail-tests depends on cgp-test-crate-a (reflected in Cargo.lock), and the namespaces test module gains default_impl_use_type, so the full workspace suite must be run to confirm the fixtures and snapshots pass.
  • No public API, macro syntax, or version changes. The change is additive to tests and docs plus one internal codegen fix, so downstream code that compiled against this tree before continues to compile.

@soareschen soareschen added the AI label Jul 5, 2026
@soareschen soareschen changed the title AI Updates #5 AI Updates #5: #[default_impl] fix, a span audit, and a new guides section Jul 5, 2026
@soareschen soareschen merged commit b2978e0 into main Jul 5, 2026
3 checks passed
@soareschen soareschen deleted the ai-updates-5 branch July 5, 2026 19:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant