From eaa10a2fa591afd72d9186f69ff652d9c82bae53 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 25 Feb 2026 23:55:14 +0100 Subject: [PATCH] Use `+` instead of `,` to list multiple provider trait bounds in `#[use_provider]` --- .../src/cgp_impl/use_provider.rs | 4 +- .../cgp_impl/implicit_args/generics.rs | 32 ++++ .../cgp_impl/implicit_args/mod.rs | 1 + .../tests/component_tests/cgp_impl/mod.rs | 1 + .../tests/component_tests/cgp_impl/shape.rs | 176 ++++++++++++++++++ .../component_tests/cgp_impl/use_provider.rs | 12 ++ 6 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 crates/cgp-tests/tests/component_tests/cgp_impl/implicit_args/generics.rs create mode 100644 crates/cgp-tests/tests/component_tests/cgp_impl/shape.rs diff --git a/crates/cgp-macro-lib/src/cgp_impl/use_provider.rs b/crates/cgp-macro-lib/src/cgp_impl/use_provider.rs index d6d380e4..7f4d4225 100644 --- a/crates/cgp-macro-lib/src/cgp_impl/use_provider.rs +++ b/crates/cgp-macro-lib/src/cgp_impl/use_provider.rs @@ -1,6 +1,6 @@ use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::token::{Colon, Comma}; +use syn::token::{Colon, Plus}; use syn::{Type, parse_quote}; use crate::parse::SimpleType; @@ -8,7 +8,7 @@ use crate::parse::SimpleType; pub struct UseProviderSpec { pub context_type: Type, pub provider_type: Type, - pub provider_trait_bounds: Punctuated, + pub provider_trait_bounds: Punctuated, } impl Parse for UseProviderSpec { diff --git a/crates/cgp-tests/tests/component_tests/cgp_impl/implicit_args/generics.rs b/crates/cgp-tests/tests/component_tests/cgp_impl/implicit_args/generics.rs new file mode 100644 index 00000000..7cd76684 --- /dev/null +++ b/crates/cgp-tests/tests/component_tests/cgp_impl/implicit_args/generics.rs @@ -0,0 +1,32 @@ +use core::ops::Mul; + +use cgp::prelude::*; + +#[cgp_component(AreaCalculator)] +pub trait CanCalculateArea { + fn area(&self) -> f64; +} + +#[cgp_impl(new RectangleArea)] +impl AreaCalculator +where + Scalar: Mul + Clone + Into, +{ + fn area(&self, #[implicit] width: Scalar, #[implicit] height: Scalar) -> f64 { + (width * height).into() + } +} + +#[derive(HasField)] +pub struct Rectangle { + pub width: f64, + pub height: f64, +} + +delegate_and_check_components! { + CanUseRectangle for Rectangle; + Rectangle { + AreaCalculatorComponent: + RectangleArea, + } +} diff --git a/crates/cgp-tests/tests/component_tests/cgp_impl/implicit_args/mod.rs b/crates/cgp-tests/tests/component_tests/cgp_impl/implicit_args/mod.rs index 65c0dea3..e9cc3a18 100644 --- a/crates/cgp-tests/tests/component_tests/cgp_impl/implicit_args/mod.rs +++ b/crates/cgp-tests/tests/component_tests/cgp_impl/implicit_args/mod.rs @@ -1,2 +1,3 @@ pub mod basic; +pub mod generics; pub mod import; diff --git a/crates/cgp-tests/tests/component_tests/cgp_impl/mod.rs b/crates/cgp-tests/tests/component_tests/cgp_impl/mod.rs index 42012963..f6afef05 100644 --- a/crates/cgp-tests/tests/component_tests/cgp_impl/mod.rs +++ b/crates/cgp-tests/tests/component_tests/cgp_impl/mod.rs @@ -2,4 +2,5 @@ pub mod basic; pub mod impl_self; pub mod implicit_args; pub mod implicit_context; +pub mod shape; pub mod use_provider; diff --git a/crates/cgp-tests/tests/component_tests/cgp_impl/shape.rs b/crates/cgp-tests/tests/component_tests/cgp_impl/shape.rs new file mode 100644 index 00000000..85dcdfda --- /dev/null +++ b/crates/cgp-tests/tests/component_tests/cgp_impl/shape.rs @@ -0,0 +1,176 @@ +use core::f64::consts::PI; + +use cgp::prelude::*; + +#[cgp_fn] +pub fn rectangle_area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { + width * height +} + +#[cgp_fn] +pub fn circle_area(&self, #[implicit] radius: f64) -> f64 { + PI * radius * radius +} + +#[cgp_component(AreaCalculator)] +pub trait CanCalculateArea { + fn area(&self) -> f64; +} + +#[cgp_impl(new RectangleAreaCalculator)] +impl AreaCalculator { + fn area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { + width * height + } +} + +#[cgp_impl(new CircleAreaCalculator)] +impl AreaCalculator { + fn area(&self, #[implicit] radius: f64) -> f64 { + PI * radius * radius + } +} + +#[cgp_impl(new ScaledRectangleAreaCalculator)] +#[use_provider(RectangleAreaCalculator: AreaCalculator)] +impl AreaCalculator { + fn area(&self, #[implicit] scale_factor: f64) -> f64 { + RectangleAreaCalculator::area(self) * scale_factor * scale_factor + } +} + +#[cgp_impl(new ScaledCircleAreaCalculator)] +#[use_provider(CircleAreaCalculator: AreaCalculator)] +impl AreaCalculator { + fn area(&self, #[implicit] scale_factor: f64) -> f64 { + CircleAreaCalculator::area(self) * scale_factor * scale_factor + } +} + +#[cgp_impl(new ScaledAreaCalculator)] +#[use_provider(InnerCalculator: AreaCalculator)] +impl AreaCalculator { + fn area(&self, #[implicit] scale_factor: f64) -> f64 { + let base_area = InnerCalculator::area(self); + + base_area * scale_factor * scale_factor + } +} + +#[derive(HasField)] +pub struct IsThisRectangleOrCircle { + pub width: f64, + pub height: f64, + pub radius: f64, +} + +impl CanCalculateArea for IsThisRectangleOrCircle { + fn area(&self) -> f64 { + CircleAreaCalculator::area(self) + } +} + +#[test] +fn test_rectangle_or_circle() { + let rectangle_or_circle = IsThisRectangleOrCircle { + width: 2.0, + height: 3.0, + radius: 4.0, + }; + + let area = rectangle_or_circle.area(); + assert_eq!(area, 16.0 * PI); + + let rectangle_area = RectangleAreaCalculator::area(&rectangle_or_circle); + assert_eq!(rectangle_area, 6.0); + + let circle_area = CircleAreaCalculator::area(&rectangle_or_circle); + assert_eq!(circle_area, 16.0 * PI); + + let rectangle_area = rectangle_or_circle.rectangle_area(); + assert_eq!(rectangle_area, 6.0); + + let circle_area = rectangle_or_circle.circle_area(); + assert_eq!(circle_area, 16.0 * PI); +} + +#[derive(HasField)] +pub struct PlainRectangle { + pub width: f64, + pub height: f64, +} + +delegate_components! { + PlainRectangle { + AreaCalculatorComponent: + RectangleAreaCalculator, + } +} + +#[derive(HasField)] +pub struct ScaledRectangle { + pub scale_factor: f64, + pub width: f64, + pub height: f64, +} + +delegate_components! { + ScaledRectangle { + AreaCalculatorComponent: + ScaledAreaCalculator, + } +} + +#[derive(HasField)] +pub struct PlainCircle { + pub radius: f64, +} + +delegate_components! { + PlainCircle { + AreaCalculatorComponent: + CircleAreaCalculator, + } +} + +#[derive(HasField)] +pub struct ScaledCircle { + pub scale_factor: f64, + pub radius: f64, +} + +delegate_components! { + ScaledCircle { + AreaCalculatorComponent: + ScaledAreaCalculator, + } +} + +#[test] +fn test_scaled_area() { + let rectangle = PlainRectangle { + width: 3.0, + height: 4.0, + }; + + assert_eq!(rectangle.area(), 12.0); + + let scaled_rectangle = ScaledRectangle { + scale_factor: 2.0, + width: 3.0, + height: 4.0, + }; + + let circle = PlainCircle { radius: 3.0 }; + + assert_eq!(circle.area(), 9.0 * PI); + + assert_eq!(scaled_rectangle.area(), 48.0); + + let scaled_circle = ScaledCircle { + scale_factor: 2.0, + radius: 3.0, + }; + + assert_eq!(scaled_circle.area(), 36.0 * PI); +} diff --git a/crates/cgp-tests/tests/component_tests/cgp_impl/use_provider.rs b/crates/cgp-tests/tests/component_tests/cgp_impl/use_provider.rs index a91c8a33..44e1a690 100644 --- a/crates/cgp-tests/tests/component_tests/cgp_impl/use_provider.rs +++ b/crates/cgp-tests/tests/component_tests/cgp_impl/use_provider.rs @@ -22,3 +22,15 @@ impl AreaCalculator { base_area * scale_factor * scale_factor } } + +#[derive(HasField)] +pub struct Rectangle { + pub width: f64, + pub height: f64, +} + +impl CanCalculateArea for Rectangle { + fn area(&self) -> f64 { + RectangleArea::area(self) + } +}