[AI] Refactor constructs for parsing ident/path with type parameters#237
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
CGP's procedural macros (
#[cgp_component],#[cgp_impl],#[cgp_provider],delegate_components!, the#[uses]/#[use_type]/#[use_provider]attributes, etc.) need to parse the angle-bracketed generic lists that appear
in their inputs. Two different positions exist:
<A, B>inFoo<A, B>(what you pass).<'a, C>inBar<'a, C>(what youdeclare).
Previously these were modelled with permissive
synwrappers(
GenericArgumentsaroundsyn::AngleBracketedGenericArguments, andsyn::Generics/TypeGenerics). Those wrappers silently accepted many formsthat are invalid in CGP positions — associated bindings (
Foo<A, B = C>),associated bounds (
Foo<A: Clone>), turbofish (Foo::<A>), parameter defaults(
A = B), parenthesized args (Fn(A) -> B) — and the failures only surfacedlater as confusing downstream errors.
This PR replaces that machinery with a set of purpose-built, strict parser
types that reject invalid forms at parse time with clear messages, and at the
same time generalizes identifier heads to full paths so attributes can
accept
path::to::Trait<A>rather than only a bare identifier.High-level concepts
New strict parsing types (in cgp/crates/macros/cgp-macro-core/src/types/ident/)
TypeArg/TypeArgs(type_arg.rs){ }const argsTypeGenericParam/TypeGenericParams(type_generic_param.rs)const N: TPathWithTypeArgs(path_with_type_args.rs)path::to::Foo<A, B>, lifts final-segment args intoTypeArgsShared
parse_angle_bracketed/to_tokens_angle_bracketedhelpers(angle_bracketed.rs)
back both list types; an absent
<...>and an explicit empty<>both renderas nothing (stable round-trip).
Reworked existing types
IdentWithTypeArgs.type_args:GenericArguments→TypeArgs.IdentWithTypeGenerics.type_generics:TypeGenerics→TypeGenericParams.TypeGenericsis kept (still used to adapt an already-parsedsyn::Genericsoff an item, viasplit_for_impl) and is now documented asthe deliberate complement to
TypeGenericParams— the two are intentionallynot merged because
TypeGenerics's normalization (collapsingconst N: Ttoa bare
N) is load-bearing for some callers.Structural changes
(the
GenericArgumentswrapper and itsmake_args()get-or-insert helper);removed from generics/mod.rs.
Optionremoved from the list payloads (TypeArgs::args,TypeGenericParams::params) — an emptyPunctuatednow represents "nobrackets", eliminating
Optionhandling andmake_args()mutation.cgp-macro-core: the attribute parsers(
function,prefix,uses,use_type,use_provider,default_impl,cgp_impl_attributes),cgp_provider,cgp_impl,delegate_component(incl.
eval/for_loop/table),namespace(inherit/table), andprovider_implwere moved fromIdentWithTypeArgs→PathWithTypeArgsandfrom
GenericArguments/make_args→TypeArgs. Fields such asnamespace,trait_path,provider_trait_path,provider_trait_bounds,uses,imports, andparent_namespaceare now path-aware.cgp-macro-lib'sparse/component_spec.rs
(the
CgpComponentArgsparser) was removed; the equivalent logic now lives incgp-macro-core(cgp_component/args/component_args.rs), consolidatingcomponent-spec parsing in the core crate.
cgp-macro-testsadded to the workspace(Cargo.toml), with parse/reject/idempotency tests for
IdentWithTypeArgs,IdentWithTypeGenerics, andPathWithTypeArgs, plus aside-by-side comparison documenting where their behaviors diverge.
cgp-macro-core,syn,quote,proc-macro2) added toboth
cgp-macro-testsand the existingcgp-testscrate to allow directunit-testing of the macro-core parsers.
Impacts
bindings, associated bounds, turbofish, defaults, parenthesized args,
generics on non-final path segments) are now rejected at parse time with
explicit messages, instead of being silently accepted or producing opaque
downstream compile errors.
provider, or namespace now accept fully-qualified paths
(
path::to::Trait<A>), not just bare identifiers — a genuine featureaddition, not only a refactor.
TypeGenericParamscan nowrepresent
const N: usizeparameters; normalization differences vs.TypeGenericsare explicitly documented.Optionandmake_args()removes a classof get-or-insert mutation; empty-list semantics are uniform across both list
types.
cgp-macro-libto
cgp-macro-core; anything that importedCgpComponentArgsfrom the libcrate path is affected.
compile and test time.
the new tests; the regression-risk surface is specifically any code that
relied on the old permissive parsing of now-rejected forms.