From 7a62f4aec16b3333c97ecbd8d3814e5389b9ea26 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 7 Jun 2026 21:51:19 +0200 Subject: [PATCH 1/7] Draft implement DefaultImplAttribute --- .../src/types/attributes/default_impl.rs | 51 +++++++++++++++++++ .../src/types/attributes/mod.rs | 2 + .../cgp-macro-core/src/types/cgp_impl/item.rs | 2 +- .../src/types/cgp_impl/lowered.rs | 4 +- .../cgp-tests/src/namespaces/generics.rs | 2 +- 5 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 crates/macros/cgp-macro-core/src/types/attributes/default_impl.rs diff --git a/crates/macros/cgp-macro-core/src/types/attributes/default_impl.rs b/crates/macros/cgp-macro-core/src/types/attributes/default_impl.rs new file mode 100644 index 00000000..e7aef071 --- /dev/null +++ b/crates/macros/cgp-macro-core/src/types/attributes/default_impl.rs @@ -0,0 +1,51 @@ +use syn::spanned::Spanned; +use syn::token::Type; +use syn::{Error, Generics, ItemImpl, parse_quote}; + +use crate::types::ident::IdentWithTypeArgs; + +pub struct DefaultImplAttribute { + pub namespace: IdentWithTypeArgs, +} + +impl DefaultImplAttribute { + pub fn to_item_impl( + &self, + provider_generics: &Generics, + provider_trait_path: &IdentWithTypeArgs, + provider_type: &Type, + ) -> syn::Result { + let mut namespace_trait_path = self.namespace.clone(); + + namespace_trait_path + .type_args + .make_args() + .push(parse_quote!(__Components__)); + + let mut generics = provider_generics.clone(); + generics.params.push(parse_quote!(__Components__)); + + let type_args = provider_trait_path + .type_args + .args + .as_ref() + .ok_or_else(|| Error::new( + provider_trait_path.span(), + "#[default_impl] can only be used with CGP traits with at least one generic argument" + ))? + .args + .clone(); + + let (impl_generics, _, where_clause) = generics.split_for_impl(); + + let item_impl = parse_quote! { + impl #impl_generics #namespace_trait_path for (#type_args) + #where_clause + { + type Delegate = #provider_type; + } + }; + + Ok(item_impl) + } +} diff --git a/crates/macros/cgp-macro-core/src/types/attributes/mod.rs b/crates/macros/cgp-macro-core/src/types/attributes/mod.rs index 72930efc..aaf3fee4 100644 --- a/crates/macros/cgp-macro-core/src/types/attributes/mod.rs +++ b/crates/macros/cgp-macro-core/src/types/attributes/mod.rs @@ -1,9 +1,11 @@ +mod default_impl; mod function; mod impl_attributes; mod use_provider; mod use_type; mod uses; +pub use default_impl::*; pub use function::*; pub use impl_attributes::*; pub use use_provider::*; diff --git a/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs b/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs index 5d6a83fe..4b0d303b 100644 --- a/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs +++ b/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs @@ -54,7 +54,7 @@ impl ItemCgpImpl { args: self.args.clone(), item_impl, context_type, - consumer_trait_path, + provider_trait_path: consumer_trait_path, }) } } diff --git a/crates/macros/cgp-macro-core/src/types/cgp_impl/lowered.rs b/crates/macros/cgp-macro-core/src/types/cgp_impl/lowered.rs index bb1cf48e..529c5899 100644 --- a/crates/macros/cgp-macro-core/src/types/cgp_impl/lowered.rs +++ b/crates/macros/cgp-macro-core/src/types/cgp_impl/lowered.rs @@ -17,7 +17,7 @@ pub struct LoweredCgpImpl { pub args: ImplArgs, pub item_impl: ItemImpl, pub context_type: Type, - pub consumer_trait_path: IdentWithTypeArgs, + pub provider_trait_path: IdentWithTypeArgs, } impl LoweredCgpImpl { @@ -53,7 +53,7 @@ impl LoweredCgpImpl { pub fn to_raw_item_impl(&self) -> syn::Result { let item_impl = &self.item_impl; let context_type = &self.context_type; - let consumer_trait_path = &self.consumer_trait_path; + let consumer_trait_path = &self.provider_trait_path; let provider_type = &self.args.provider_type; let context_ident = if let Ok(ident) = parse2::(context_type.to_token_stream()) { diff --git a/crates/tests/cgp-tests/src/namespaces/generics.rs b/crates/tests/cgp-tests/src/namespaces/generics.rs index b9ac9a27..4958b98d 100644 --- a/crates/tests/cgp-tests/src/namespaces/generics.rs +++ b/crates/tests/cgp-tests/src/namespaces/generics.rs @@ -10,7 +10,7 @@ pub trait Show { } #[cgp_impl(new ShowWithDisplay)] -// #[default_impl(DefaultNamespace1)] +// #[default_impl(DefaultNamespace1)] impl ShowImpl { fn show(&self, value: &T) -> String { value.to_string() From 8cb6b461bcfe46e61a5ad59901b39ec3f47fea4f Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 10 Jun 2026 22:44:20 +0200 Subject: [PATCH 2/7] Implement parsing for DefaultImplAttribute --- .../attribute.rs} | 37 +++++++++++-------- .../attributes/default_impl/attributes.rs | 25 +++++++++++++ .../src/types/attributes/default_impl/mod.rs | 5 +++ .../src/types/attributes/impl_attributes.rs | 15 +++++++- .../cgp-macro-core/src/types/cgp_impl/item.rs | 2 +- .../src/types/cgp_impl/lowered.rs | 4 +- .../cgp-tests/src/namespaces/generics.rs | 12 +++++- 7 files changed, 77 insertions(+), 23 deletions(-) rename crates/macros/cgp-macro-core/src/types/attributes/{default_impl.rs => default_impl/attribute.rs} (59%) create mode 100644 crates/macros/cgp-macro-core/src/types/attributes/default_impl/attributes.rs create mode 100644 crates/macros/cgp-macro-core/src/types/attributes/default_impl/mod.rs diff --git a/crates/macros/cgp-macro-core/src/types/attributes/default_impl.rs b/crates/macros/cgp-macro-core/src/types/attributes/default_impl/attribute.rs similarity index 59% rename from crates/macros/cgp-macro-core/src/types/attributes/default_impl.rs rename to crates/macros/cgp-macro-core/src/types/attributes/default_impl/attribute.rs index e7aef071..571e99d1 100644 --- a/crates/macros/cgp-macro-core/src/types/attributes/default_impl.rs +++ b/crates/macros/cgp-macro-core/src/types/attributes/default_impl/attribute.rs @@ -1,10 +1,12 @@ -use syn::spanned::Spanned; -use syn::token::Type; -use syn::{Error, Generics, ItemImpl, parse_quote}; +use syn::parse::{Parse, ParseStream}; +use syn::token::In; +use syn::{Generics, ItemImpl, Type, parse_quote}; use crate::types::ident::IdentWithTypeArgs; pub struct DefaultImplAttribute { + pub key_type: Type, + pub in_token: In, pub namespace: IdentWithTypeArgs, } @@ -12,9 +14,9 @@ impl DefaultImplAttribute { pub fn to_item_impl( &self, provider_generics: &Generics, - provider_trait_path: &IdentWithTypeArgs, provider_type: &Type, ) -> syn::Result { + let key_type = &self.key_type; let mut namespace_trait_path = self.namespace.clone(); namespace_trait_path @@ -25,21 +27,10 @@ impl DefaultImplAttribute { let mut generics = provider_generics.clone(); generics.params.push(parse_quote!(__Components__)); - let type_args = provider_trait_path - .type_args - .args - .as_ref() - .ok_or_else(|| Error::new( - provider_trait_path.span(), - "#[default_impl] can only be used with CGP traits with at least one generic argument" - ))? - .args - .clone(); - let (impl_generics, _, where_clause) = generics.split_for_impl(); let item_impl = parse_quote! { - impl #impl_generics #namespace_trait_path for (#type_args) + impl #impl_generics #namespace_trait_path for #key_type #where_clause { type Delegate = #provider_type; @@ -49,3 +40,17 @@ impl DefaultImplAttribute { Ok(item_impl) } } + +impl Parse for DefaultImplAttribute { + fn parse(input: ParseStream) -> syn::Result { + let key_type = input.parse()?; + let in_token = input.parse()?; + let namespace = input.parse()?; + + Ok(Self { + key_type, + in_token, + namespace, + }) + } +} diff --git a/crates/macros/cgp-macro-core/src/types/attributes/default_impl/attributes.rs b/crates/macros/cgp-macro-core/src/types/attributes/default_impl/attributes.rs new file mode 100644 index 00000000..53a20d4c --- /dev/null +++ b/crates/macros/cgp-macro-core/src/types/attributes/default_impl/attributes.rs @@ -0,0 +1,25 @@ +use syn::{Generics, ItemImpl, Type}; + +use crate::types::attributes::DefaultImplAttribute; + +#[derive(Default)] +pub struct DefaultImplAttributes { + pub attributes: Vec, +} + +impl DefaultImplAttributes { + pub fn to_item_impls( + &self, + provider_generics: &Generics, + provider_type: &Type, + ) -> syn::Result> { + let mut item_impls = Vec::new(); + + for attribute in &self.attributes { + let item_impl = attribute.to_item_impl(provider_generics, provider_type)?; + item_impls.push(item_impl); + } + + Ok(item_impls) + } +} diff --git a/crates/macros/cgp-macro-core/src/types/attributes/default_impl/mod.rs b/crates/macros/cgp-macro-core/src/types/attributes/default_impl/mod.rs new file mode 100644 index 00000000..ea33ebcb --- /dev/null +++ b/crates/macros/cgp-macro-core/src/types/attributes/default_impl/mod.rs @@ -0,0 +1,5 @@ +mod attribute; +mod attributes; + +pub use attribute::*; +pub use attributes::*; diff --git a/crates/macros/cgp-macro-core/src/types/attributes/impl_attributes.rs b/crates/macros/cgp-macro-core/src/types/attributes/impl_attributes.rs index cea9184b..2f246a48 100644 --- a/crates/macros/cgp-macro-core/src/types/attributes/impl_attributes.rs +++ b/crates/macros/cgp-macro-core/src/types/attributes/impl_attributes.rs @@ -1,10 +1,11 @@ use syn::Attribute; +use syn::parse::Parse; use syn::punctuated::Punctuated; use syn::token::Comma; use crate::types::attributes::{ - UseProviderAttribute, UseProviderAttributes, UseTypeAttribute, UseTypeAttributes, - UsesAttributes, + DefaultImplAttribute, DefaultImplAttributes, UseProviderAttribute, UseProviderAttributes, + UseTypeAttribute, UseTypeAttributes, UsesAttributes, }; use crate::types::ident::IdentWithTypeArgs; @@ -13,6 +14,7 @@ pub struct ImplAttributes { pub uses: UsesAttributes, pub use_type: UseTypeAttributes, pub use_provider: UseProviderAttributes, + pub default_impls: DefaultImplAttributes, pub raw_attributes: Vec, } @@ -47,6 +49,15 @@ impl ImplAttributes { .attributes .extend(use_provider); } + "default_impl" => { + let default_impl = + attribute.parse_args_with(DefaultImplAttribute::parse)?; + + parsed_attributes + .default_impls + .attributes + .push(default_impl); + } _ => { parsed_attributes.raw_attributes.push(attribute.clone()); } diff --git a/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs b/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs index 4b0d303b..5d6a83fe 100644 --- a/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs +++ b/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs @@ -54,7 +54,7 @@ impl ItemCgpImpl { args: self.args.clone(), item_impl, context_type, - provider_trait_path: consumer_trait_path, + consumer_trait_path, }) } } diff --git a/crates/macros/cgp-macro-core/src/types/cgp_impl/lowered.rs b/crates/macros/cgp-macro-core/src/types/cgp_impl/lowered.rs index 529c5899..bb1cf48e 100644 --- a/crates/macros/cgp-macro-core/src/types/cgp_impl/lowered.rs +++ b/crates/macros/cgp-macro-core/src/types/cgp_impl/lowered.rs @@ -17,7 +17,7 @@ pub struct LoweredCgpImpl { pub args: ImplArgs, pub item_impl: ItemImpl, pub context_type: Type, - pub provider_trait_path: IdentWithTypeArgs, + pub consumer_trait_path: IdentWithTypeArgs, } impl LoweredCgpImpl { @@ -53,7 +53,7 @@ impl LoweredCgpImpl { pub fn to_raw_item_impl(&self) -> syn::Result { let item_impl = &self.item_impl; let context_type = &self.context_type; - let consumer_trait_path = &self.provider_trait_path; + let consumer_trait_path = &self.consumer_trait_path; let provider_type = &self.args.provider_type; let context_ident = if let Ok(ident) = parse2::(context_type.to_token_stream()) { diff --git a/crates/tests/cgp-tests/src/namespaces/generics.rs b/crates/tests/cgp-tests/src/namespaces/generics.rs index 4958b98d..9a6f7078 100644 --- a/crates/tests/cgp-tests/src/namespaces/generics.rs +++ b/crates/tests/cgp-tests/src/namespaces/generics.rs @@ -10,13 +10,21 @@ pub trait Show { } #[cgp_impl(new ShowWithDisplay)] -// #[default_impl(DefaultNamespace1)] +// #[default_impl(String in DefaultNamespace1)] impl ShowImpl { fn show(&self, value: &T) -> String { value.to_string() } } +#[cgp_impl(new ShowWithString)] +#[default_impl(String in DefaultNamespace1)] +impl ShowImpl { + fn show(&self, value: &String) -> String { + value.clone() + } +} + // cgp_namespace! { // DefaultShow { // T: @@ -34,5 +42,5 @@ impl ShowImpl { */ impl DefaultImpls1 for String { - type Delegate = ShowWithDisplay; + type Delegate = ShowWithString; } From 8389b00921949daa40bffc926260471ee184a87f Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 10 Jun 2026 22:56:17 +0200 Subject: [PATCH 3/7] Default impl derivation is working --- .../cgp-macro-core/src/types/cgp_impl/item.rs | 17 +++++++++++------ .../src/types/cgp_impl/lowered.rs | 7 +++---- .../cgp-macro-lib/src/entrypoints/cgp_impl.rs | 12 +++++++++--- .../tests/cgp-tests/src/namespaces/generics.rs | 7 +------ 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs b/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs index 5d6a83fe..565db269 100644 --- a/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs +++ b/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs @@ -31,14 +31,18 @@ impl ItemCgpImpl { .use_provider .add_type_param_bounds(&self_type, &mut item_impl.generics)?; - let (consumer_trait_path, context_type) = match &item_impl.trait_ { + let default_impls = attributes + .default_impls + .to_item_impls(&mut item_impl.generics, &self.args.provider_type)?; + + let (provider_trait_path, context_type) = match &item_impl.trait_ { Some((_, path, _)) => { - let consumer_trait_path = parse2(path.to_token_stream())?; + let provider_trait_path = parse2(path.to_token_stream())?; let context_type = item_impl.self_ty.as_ref().clone(); - (consumer_trait_path, context_type) + (provider_trait_path, context_type) } None => { - let consumer_trait_path = parse2(item_impl.self_ty.to_token_stream())?; + let provider_trait_path = parse2(item_impl.self_ty.to_token_stream())?; let context_type = parse_quote! { __Context__ }; item_impl @@ -46,7 +50,7 @@ impl ItemCgpImpl { .params .insert(0, parse_quote! { #context_type }); - (consumer_trait_path, context_type) + (provider_trait_path, context_type) } }; @@ -54,7 +58,8 @@ impl ItemCgpImpl { args: self.args.clone(), item_impl, context_type, - consumer_trait_path, + provider_trait_path, + default_impls, }) } } diff --git a/crates/macros/cgp-macro-core/src/types/cgp_impl/lowered.rs b/crates/macros/cgp-macro-core/src/types/cgp_impl/lowered.rs index bb1cf48e..0bfe97b3 100644 --- a/crates/macros/cgp-macro-core/src/types/cgp_impl/lowered.rs +++ b/crates/macros/cgp-macro-core/src/types/cgp_impl/lowered.rs @@ -17,7 +17,8 @@ pub struct LoweredCgpImpl { pub args: ImplArgs, pub item_impl: ItemImpl, pub context_type: Type, - pub consumer_trait_path: IdentWithTypeArgs, + pub provider_trait_path: IdentWithTypeArgs, + pub default_impls: Vec, } impl LoweredCgpImpl { @@ -53,7 +54,7 @@ impl LoweredCgpImpl { pub fn to_raw_item_impl(&self) -> syn::Result { let item_impl = &self.item_impl; let context_type = &self.context_type; - let consumer_trait_path = &self.consumer_trait_path; + let mut provider_trait_path = self.provider_trait_path.clone(); let provider_type = &self.args.provider_type; let context_ident = if let Ok(ident) = parse2::(context_type.to_token_stream()) { @@ -78,8 +79,6 @@ impl LoweredCgpImpl { out_impl.self_ty = Box::new(provider_type.clone()); - let mut provider_trait_path = consumer_trait_path.clone(); - provider_trait_path .type_args .make_args() diff --git a/crates/macros/cgp-macro-lib/src/entrypoints/cgp_impl.rs b/crates/macros/cgp-macro-lib/src/entrypoints/cgp_impl.rs index 16ee9fe1..7c2a2431 100644 --- a/crates/macros/cgp-macro-lib/src/entrypoints/cgp_impl.rs +++ b/crates/macros/cgp-macro-lib/src/entrypoints/cgp_impl.rs @@ -1,6 +1,6 @@ use cgp_macro_core::types::cgp_impl::{ImplArgs, ItemCgpImpl}; use proc_macro2::TokenStream; -use quote::ToTokens; +use quote::quote; use syn::{ItemImpl, parse2}; pub fn cgp_impl(attr: TokenStream, body: TokenStream) -> syn::Result { @@ -10,7 +10,13 @@ pub fn cgp_impl(attr: TokenStream, body: TokenStream) -> syn::Result { } #[cgp_impl(new ShowWithDisplay)] -// #[default_impl(String in DefaultNamespace1)] impl ShowImpl { fn show(&self, value: &T) -> String { value.to_string() @@ -18,7 +17,7 @@ impl ShowImpl { } #[cgp_impl(new ShowWithString)] -#[default_impl(String in DefaultNamespace1)] +#[default_impl(String in DefaultImpls1)] impl ShowImpl { fn show(&self, value: &String) -> String { value.clone() @@ -40,7 +39,3 @@ impl ShowImpl { } } */ - -impl DefaultImpls1 for String { - type Delegate = ShowWithString; -} From 067b7519fe122fbf9eef5bc8b83a38faf0eaf596 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 10 Jun 2026 23:11:43 +0200 Subject: [PATCH 4/7] Update default impl tests --- .../{generics.rs => default_impl_a.rs} | 34 ++++++++---------- crates/tests/cgp-tests/src/namespaces/mod.rs | 2 +- .../namespace_macro/default_generics.rs | 35 ++++++++++++++----- 3 files changed, 41 insertions(+), 30 deletions(-) rename crates/tests/cgp-tests/src/namespaces/{generics.rs => default_impl_a.rs} (67%) diff --git a/crates/tests/cgp-tests/src/namespaces/generics.rs b/crates/tests/cgp-tests/src/namespaces/default_impl_a.rs similarity index 67% rename from crates/tests/cgp-tests/src/namespaces/generics.rs rename to crates/tests/cgp-tests/src/namespaces/default_impl_a.rs index 8ff116d0..cdf270dd 100644 --- a/crates/tests/cgp-tests/src/namespaces/generics.rs +++ b/crates/tests/cgp-tests/src/namespaces/default_impl_a.rs @@ -9,13 +9,6 @@ pub trait Show { fn show(&self, value: &T) -> String; } -#[cgp_impl(new ShowWithDisplay)] -impl ShowImpl { - fn show(&self, value: &T) -> String { - value.to_string() - } -} - #[cgp_impl(new ShowWithString)] #[default_impl(String in DefaultImpls1)] impl ShowImpl { @@ -24,18 +17,19 @@ impl ShowImpl { } } -// cgp_namespace! { -// DefaultShow { -// T: -// @ShowWithDisplay, -// } -// } +#[cgp_impl(new ShowWithDisplay)] +impl ShowImpl { + fn show(&self, value: &T) -> String { + value.to_string() + } +} -/* - cgp_namespace! { - DefaultNamespace1 { - String: - ShowWithDisplay, - } +cgp_namespace! { + new DefaultShowComponents { + [ + String, + u64, + ]: + ShowWithDisplay, } -*/ +} diff --git a/crates/tests/cgp-tests/src/namespaces/mod.rs b/crates/tests/cgp-tests/src/namespaces/mod.rs index b9a1bced..2beec10d 100644 --- a/crates/tests/cgp-tests/src/namespaces/mod.rs +++ b/crates/tests/cgp-tests/src/namespaces/mod.rs @@ -1,2 +1,2 @@ +pub mod default_impl_a; pub mod extended; -pub mod generics; diff --git a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs index 7d1b7d4e..0ddb8651 100644 --- a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs +++ b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs @@ -1,15 +1,13 @@ use cgp::core::component::DefaultImpls1; use cgp::prelude::*; -use cgp_tests::namespaces::generics::{ShowImplComponent, ShowWithDisplay}; +use cgp_tests::namespaces::default_impl_a::{ + DefaultShowComponents, ShowImplComponent, ShowWithDisplay, +}; -pub struct App; +pub struct AppA; delegate_components! { - App { - // use DefaultNamespace; - // for in DefaultNamespace { - // Component: Provider, - // } + AppA { namespace DefaultNamespace; for in DefaultImpls1 { @@ -18,13 +16,32 @@ delegate_components! { @test.ShowImplComponent.u64: ShowWithDisplay, + } +} + +check_components! { + AppA { + ShowImplComponent: [ + String, + u64, + ] + } +} + +pub struct AppB; + +delegate_components! { + AppB { + namespace DefaultNamespace; - // namespace DefaultNamespace1 => @test.ShowImplComponent; + for in DefaultShowComponents { + @test.ShowImplComponent.T: Provider, + } } } check_components! { - App { + AppB { ShowImplComponent: [ String, u64, From 0b3cd117657d06bd6e42f2508e3068f30e69c2d1 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 10 Jun 2026 23:16:19 +0200 Subject: [PATCH 5/7] Use UniPathOrType in DefaultImplAttribute --- .../attributes/default_impl/attribute.rs | 3 +- .../cgp-macro-core/src/types/path/mod.rs | 2 ++ .../src/types/path/unipath_or_type.rs | 33 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 crates/macros/cgp-macro-core/src/types/path/unipath_or_type.rs diff --git a/crates/macros/cgp-macro-core/src/types/attributes/default_impl/attribute.rs b/crates/macros/cgp-macro-core/src/types/attributes/default_impl/attribute.rs index 571e99d1..d209fee7 100644 --- a/crates/macros/cgp-macro-core/src/types/attributes/default_impl/attribute.rs +++ b/crates/macros/cgp-macro-core/src/types/attributes/default_impl/attribute.rs @@ -3,9 +3,10 @@ use syn::token::In; use syn::{Generics, ItemImpl, Type, parse_quote}; use crate::types::ident::IdentWithTypeArgs; +use crate::types::path::UniPathOrType; pub struct DefaultImplAttribute { - pub key_type: Type, + pub key_type: UniPathOrType, pub in_token: In, pub namespace: IdentWithTypeArgs, } diff --git a/crates/macros/cgp-macro-core/src/types/path/mod.rs b/crates/macros/cgp-macro-core/src/types/path/mod.rs index 7537b012..26f81c79 100644 --- a/crates/macros/cgp-macro-core/src/types/path/mod.rs +++ b/crates/macros/cgp-macro-core/src/types/path/mod.rs @@ -3,9 +3,11 @@ mod path_head; mod path_head_or_type; mod prefix; mod unipath; +mod unipath_or_type; pub use path_element::*; pub use path_head::*; pub use path_head_or_type::*; pub use prefix::*; pub use unipath::*; +pub use unipath_or_type::*; diff --git a/crates/macros/cgp-macro-core/src/types/path/unipath_or_type.rs b/crates/macros/cgp-macro-core/src/types/path/unipath_or_type.rs new file mode 100644 index 00000000..80f4b720 --- /dev/null +++ b/crates/macros/cgp-macro-core/src/types/path/unipath_or_type.rs @@ -0,0 +1,33 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::Type; +use syn::parse::{Parse, ParseStream}; +use syn::token::At; + +use crate::types::path::UniPath; + +pub enum UniPathOrType { + Type(Type), + Path(UniPath), +} + +impl Parse for UniPathOrType { + fn parse(input: ParseStream) -> syn::Result { + if input.peek(At) { + let path = input.parse()?; + Ok(Self::Path(path)) + } else { + let ty = input.parse()?; + Ok(Self::Type(ty)) + } + } +} + +impl ToTokens for UniPathOrType { + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + UniPathOrType::Type(ty) => ty.to_tokens(tokens), + UniPathOrType::Path(path) => path.to_tokens(tokens), + } + } +} From 012a8f3cec9b3c8be1f37b42bf61b554bb425b1d Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 10 Jun 2026 23:23:46 +0200 Subject: [PATCH 6/7] Add test for default impls with path keys --- .../{default_impl_a.rs => default_impls.rs} | 15 +++++++++- crates/tests/cgp-tests/src/namespaces/mod.rs | 2 +- .../{default_generics.rs => default_impls.rs} | 29 +++++++++++++++++-- .../namespace_tests/namespace_macro/mod.rs | 2 +- 4 files changed, 43 insertions(+), 5 deletions(-) rename crates/tests/cgp-tests/src/namespaces/{default_impl_a.rs => default_impls.rs} (68%) rename crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/{default_generics.rs => default_impls.rs} (59%) diff --git a/crates/tests/cgp-tests/src/namespaces/default_impl_a.rs b/crates/tests/cgp-tests/src/namespaces/default_impls.rs similarity index 68% rename from crates/tests/cgp-tests/src/namespaces/default_impl_a.rs rename to crates/tests/cgp-tests/src/namespaces/default_impls.rs index cdf270dd..4a94a54c 100644 --- a/crates/tests/cgp-tests/src/namespaces/default_impl_a.rs +++ b/crates/tests/cgp-tests/src/namespaces/default_impls.rs @@ -9,7 +9,7 @@ pub trait Show { fn show(&self, value: &T) -> String; } -#[cgp_impl(new ShowWithString)] +#[cgp_impl(new ShowString)] #[default_impl(String in DefaultImpls1)] impl ShowImpl { fn show(&self, value: &String) -> String { @@ -33,3 +33,16 @@ cgp_namespace! { ShowWithDisplay, } } + +cgp_namespace! { + new ExtendedNamespace: DefaultNamespace { + } +} + +#[cgp_impl(new ShowU32)] +#[default_impl(@test.ShowImplComponent.u32 in ExtendedNamespace)] +impl ShowImpl { + fn show(&self, value: &u32) -> String { + value.to_string() + } +} diff --git a/crates/tests/cgp-tests/src/namespaces/mod.rs b/crates/tests/cgp-tests/src/namespaces/mod.rs index 2beec10d..c8002a89 100644 --- a/crates/tests/cgp-tests/src/namespaces/mod.rs +++ b/crates/tests/cgp-tests/src/namespaces/mod.rs @@ -1,2 +1,2 @@ -pub mod default_impl_a; +pub mod default_impls; pub mod extended; diff --git a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_impls.rs similarity index 59% rename from crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs rename to crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_impls.rs index 0ddb8651..dabdc5c9 100644 --- a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs +++ b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_impls.rs @@ -1,7 +1,7 @@ use cgp::core::component::DefaultImpls1; use cgp::prelude::*; -use cgp_tests::namespaces::default_impl_a::{ - DefaultShowComponents, ShowImplComponent, ShowWithDisplay, +use cgp_tests::namespaces::default_impls::{ + DefaultShowComponents, ExtendedNamespace, ShowImplComponent, ShowWithDisplay, }; pub struct AppA; @@ -48,3 +48,28 @@ check_components! { ] } } + +pub struct AppC; + +delegate_components! { + AppC { + namespace ExtendedNamespace; + + for in DefaultImpls1 { + @test.ShowImplComponent.T: Provider, + } + + @test.ShowImplComponent.u64: + ShowWithDisplay, + } +} + +check_components! { + AppC { + ShowImplComponent: [ + String, + u64, + u32, + ] + } +} diff --git a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs index 26d24110..42cb4ff2 100644 --- a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs +++ b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs @@ -1,5 +1,5 @@ pub mod basic; -pub mod default_generics; +pub mod default_impls; pub mod extended_namespace; pub mod multi_namespace; pub mod symbol_path; From e89b487e3ef6af6ff86ef4ab897623774cdeeea3 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 10 Jun 2026 23:25:21 +0200 Subject: [PATCH 7/7] Fix clippy --- crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs b/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs index 565db269..26c23029 100644 --- a/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs +++ b/crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs @@ -33,7 +33,7 @@ impl ItemCgpImpl { let default_impls = attributes .default_impls - .to_item_impls(&mut item_impl.generics, &self.args.provider_type)?; + .to_item_impls(&item_impl.generics, &self.args.provider_type)?; let (provider_trait_path, context_type) = match &item_impl.trait_ { Some((_, path, _)) => {