Refactor and move check_components! implementation to cgp-macro-core#239
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
AI Summary
This PR is an internal refactor of the macro logic behind the
check_components!and
delegate_and_check_components!macros. It moves the parsing and codegeneration for CGP's compile-time wiring checks out of the thin
cgp-macro-libcrate and into the shared
cgp-macro-corecrate, reorganizing one large fileinto a focused set of small, single-responsibility modules.
There are no changes to the public macro surface — the syntax accepted by
check_components!anddelegate_and_check_components!(array syntax,#[check_trait],#[check_providers],#[check_params],#[skip_check],generic parameters) and the code they generate are preserved. This is a
"move and reshape" change, not a feature change.
High-level concepts
The check macros generate the compile-time check traits described in the CGP
fundamentals: a dummy alias trait (
__Check{Context}/__CanUse{Context})with
CanUseComponent(orIsProviderForfor provider checks) as its supertrait,plus one impl block per component/parameter pair being verified. This forces the
compiler to surface the real missing dependency rather than a vague
"provider trait not implemented" error.
Previously, the type definitions, parser, and the
derive_check_components/derive_check_providercode generator for these traits all lived insidecgp-macro-lib. This PR turns that logic into a set of first-class typesin
cgp-macro-corethat own both their parsing and their evaluation:CheckComponentsTable(formerlyCheckComponents) now exposeseval()and
to_items()methods directly, rather than being fed to a free functionderive_check_components. Generation is now a method on the data, not aseparate procedure.
CheckEntry(which previously baked the resolved span and a singleoptional param into one struct at parse time) is replaced by a layered model:
CheckKey—Single(Type)orMulti([..]), modeling the component-keyarray syntax explicitly.
CheckValue—SingleorMulti([..]), modeling the parameter arraysyntax explicitly.
CheckEntry— akey/valuepair as written in source.EvaluatedCheckEntry— the expanded form (one key, one optional value,one resolved span) produced by
CheckEntry::eval().TypeWithGenerics(a type plus itsImplGenerics) is promoted to its ownmodule and reused throughout, including inside
EvaluatedCheckEntry.The key structural shift is the separation of parsing (source syntax →
CheckEntrywithCheckKey/CheckValue) from evaluation (the cartesianexpansion of keys × params into
EvaluatedCheckEntry, with span-resolutionheuristics). Previously these two concerns were fused into a single
ParseCheckEntries::parseimplementation that did expansion inline duringparsing.
Structural changes
Added —
cgp-macro-core/src/types/check_components/A new module split into one concept per file:
CheckComponentsTablewithparse,eval,to_items, and theoverride_spanhelperCheckComponentsTables(a sequence of tables)CheckEntry+ theeval()expansion logicCheckEntriesCheckKeyCheckValueTypeWithGenericsEvaluatedCheckEntrypub mod check_components;in types/mod.rsRemoved —
cgp-macro-libsrc/check_components/(whole directory):derive.rs(
derive_check_components/derive_check_provider),override_span.rs,mod.rssrc/parse/check_components.rs(the oldCheckComponents,CheckEntries,CheckEntry,ParseCheckEntries,TypeWithGenerics)mod/pub uselines inlib.rs and
parse/mod.rs
Rewired —
cgp-macro-libentrypointsnow parses straight into
CheckComponentsTablesand emitstables.to_items(),replacing the manual loop over
derive_check_components.now builds
CheckEntry { key, value }values (usingCheckKey::Single/CheckValue::Single) and letsCheckComponentsTable::eval()resolve spans,instead of constructing pre-evaluated entries with manually computed spans.
Net diff: ~512 insertions / ~403 deletions across 18 files; the deletions are
almost entirely the old
cgp-macro-libimplementation being relocated.Impacts
Crate boundary moved. The check-trait generation logic now lives in
cgp-macro-corealongside the other CGP code generators (cgp_component,cgp_impl,delegate_component, etc.).cgp-macro-libkeeps only theproc-macro entrypoints and delegates into the core types — consistent with how
the other macros are already structured. This makes the check logic reusable
by anything depending on
cgp-macro-core, not just thecgp-macro-libentrypoints.Parse/eval separation. Source syntax is now preserved faithfully in
CheckKey/CheckValueand only expanded later ineval(). This is a cleanerpipeline and makes the array/cartesian expansion easier to reason about and test
in isolation.
Span-resolution behavior unchanged, but relocated. The heuristic that aims
the error span at the component type when
component_types_count >= component_params_count(and otherwise at theparameter type) is moved verbatim from parse-time into
CheckEntry::eval().The
override_spanhelper (which retargets the context type's tokens sounsatisfied-constraint errors point at the component) now lives privately in
table.rs. Error-message quality for failed wiring checks should be unchanged.delegate_and_check_components!span handling simplified. The entrypoint nolonger pre-computes spans; it hands raw key/value pairs to
eval(). The#[skip_check]path (an empty parameter list) naturally emits zero check implsbecause the per-param loop has nothing to iterate — this is now documented inline.
Provider checks (
#[check_providers]) now share one code path. Previouslyderive_check_providerwas a separate function that usedimpl_genericsas-isand dropped any generics attached to the check value (
..pattern). The unifiedeval()now merges the check value's generics with the impl generics for theprovider case too. In practice the existing macro inputs produce equivalent
output, but provider checks are now consistent with context checks and would
correctly carry generics on the checked parameter if present.
No public API / no syntax change.
check_components!,delegate_and_check_components!, and all their attributes behave the same forend users. No downstream crate needs changes.