Skip to content

Commit

Permalink
refactor: change Visitable to use static dispatch instead
Browse files Browse the repository at this point in the history
This option was not available when this macro was written. Making this
change can have a small performance improvement.

BREAKING CHANGE: This may break in functions which received the
`visitor` via an argument that expect a dynamic visitor.
  • Loading branch information
chesedo committed Aug 12, 2024
1 parent 43d62b8 commit 05f7439
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 46 deletions.
17 changes: 10 additions & 7 deletions despatma/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ pub fn interpolate_traits(tokens: TokenStream, concrete_impl: TokenStream) -> To
/// Creates an abstract visitor for a list of elements.
///
/// This macro does three things:
/// 1. A `Visitor` trait is created with methods to visit each element. Each method calls a default helper function by default.
/// 1. A `Visitor` trait is created with methods to visit each element in the list. Each method calls a default helper function by default (see point 2).
/// 1. A helper function is created for each element. The idea is for this function to traverse into the elements children.
/// 1. A `Visitable` trait is created that redirects / reflects each element back to its visitor
///
Expand Down Expand Up @@ -338,7 +338,7 @@ pub fn interpolate_traits(tokens: TokenStream, concrete_impl: TokenStream) -> To
/// ```
///
/// ## Output
/// The three elements listed above will be created.
/// The three sets of things listed earlier will be created.
/// ```
/// use despatma::visitor;
///
Expand Down Expand Up @@ -371,20 +371,20 @@ pub fn interpolate_traits(tokens: TokenStream, concrete_impl: TokenStream) -> To
/// }
///
/// trait Visitable {
/// fn apply(&self, visitor: &mut dyn Visitor);
/// fn apply(&self, visitor: &mut impl Visitor);
/// }
/// impl Visitable for Arc {
/// fn apply(&self, visitor: &mut dyn Visitor) {
/// fn apply(&self, visitor: &mut impl Visitor) {
/// visitor.visit_arc(self);
/// }
/// }
/// impl Visitable for Rectangle {
/// fn apply(&self, visitor: &mut dyn Visitor) {
/// fn apply(&self, visitor: &mut impl Visitor) {
/// visitor.visit_rectangle(self);
/// }
/// }
/// impl Visitable for Point {
/// fn apply(&self, visitor: &mut dyn Visitor) {
/// fn apply(&self, visitor: &mut impl Visitor) {
/// visitor.visit_point(self);
/// }
/// }
Expand All @@ -405,7 +405,7 @@ pub fn interpolate_traits(tokens: TokenStream, concrete_impl: TokenStream) -> To
/// }
/// ```
///
/// The input shows `Visitor` can be applied to structs (`Rectangle`) and traits (`Arc` and `Point`).
/// The input shows `Visitor` can be applied to structs, but the macro also supports traits.
///
/// ## Usage
/// Any visitor can now just implement the `Visitor` trait and provide its own implementation for any of the visitor methods.
Expand Down Expand Up @@ -438,6 +438,9 @@ pub fn interpolate_traits(tokens: TokenStream, concrete_impl: TokenStream) -> To
/// }
///
/// impl Visitor for PointCounter {
/// // Only override the visit_point method
/// // All other methods will call the default helper function since we don't care about those type.
/// // But we still need to call the helper function to keep the traversal intact.
/// fn visit_point(&mut self, point: &Point) {
/// self.count += 1;
///
Expand Down
18 changes: 9 additions & 9 deletions despatma/src/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use syn::{Ident, Token};
/// Thus, it takes a list of types that will be visited.
/// A type can be concrete or dynamic.
///
/// Options can also be passed to type:
/// Options can also be passed to the type:
/// - `no_default` to turn-off the defualt implementation for the trait method.
/// - 'helper_tmpl` to be filled into the helper template for traversing a types internal structure.
#[cfg_attr(test, derive(Eq, PartialEq, Debug))]
Expand Down Expand Up @@ -93,7 +93,7 @@ impl VisitorFunction {
// Make visitable
visitables.push(quote! {
impl Visitable for #elem_type {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.#fn_name(self);
}
}
Expand All @@ -109,7 +109,7 @@ impl VisitorFunction {
#(#helpers)*

trait Visitable {
fn apply(&self, visitor: &mut dyn Visitor);
fn apply(&self, visitor: &mut impl Visitor);
}
#(#visitables)*
}
Expand Down Expand Up @@ -246,7 +246,7 @@ mod tests {
});
input.types.push(parse_quote! {
#[helper_tmpl = {
visitor.visit_button(window.button);
visitor.visit_button(&window.button);
}]
Window
});
Expand All @@ -273,24 +273,24 @@ mod tests {
where
V: Visitor + ?Sized,
{
visitor.visit_button(window.button);
visitor.visit_button(&window.button);
}

trait Visitable {
fn apply(&self, visitor: &mut dyn Visitor);
fn apply(&self, visitor: &mut impl Visitor);
}
impl Visitable for Button {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_button(self);
}
}
impl Visitable for dyn Text {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_text(self);
}
}
impl Visitable for Window {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_window(self);
}
}
Expand Down
16 changes: 8 additions & 8 deletions despatma/tests/expand/visitor/complex.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ pub fn visit_arc<V>(visitor: &mut V, arc: &dyn Arc)
where
V: Visitor + ?Sized,
{
visitor.visit_point(arc.center);
visitor.visit_point(&arc.center);
}
pub fn visit_rectangle<V>(visitor: &mut V, rectangle: &Rectangle)
where
V: Visitor + ?Sized,
{
visitor.visit_point(rectangle.top_left);
visitor.visit_point(rectangle.bottom_right);
visitor.visit_point(&rectangle.top_left);
visitor.visit_point(&rectangle.bottom_right);
}
pub fn visit_point<V>(_visitor: &mut V, _point: &dyn Point)
where
Expand All @@ -30,25 +30,25 @@ where
V: Visitor + ?Sized,
{}
trait Visitable {
fn apply(&self, visitor: &mut dyn Visitor);
fn apply(&self, visitor: &mut impl Visitor);
}
impl Visitable for dyn Arc {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_arc(self);
}
}
impl Visitable for Rectangle {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_rectangle(self);
}
}
impl Visitable for dyn Point {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_point(self);
}
}
impl Visitable for dyn Circle {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_circle(self);
}
}
6 changes: 3 additions & 3 deletions despatma/tests/expand/visitor/complex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ use despatma::visitor;

visitor!(
#[
helper_tmpl = {visitor.visit_point(arc.center);},
helper_tmpl = {visitor.visit_point(&arc.center);},
no_default,
]
dyn Arc,

#[
no_default,
helper_tmpl = {
visitor.visit_point(rectangle.top_left);
visitor.visit_point(rectangle.bottom_right);
visitor.visit_point(&rectangle.top_left);
visitor.visit_point(&rectangle.bottom_right);
},
]
Rectangle,
Expand Down
12 changes: 6 additions & 6 deletions despatma/tests/expand/visitor/helper_tmpl.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,28 @@ pub fn visit_rectangle<V>(visitor: &mut V, rectangle: &Rectangle)
where
V: Visitor + ?Sized,
{
visitor.visit_point(rectangle.top_left);
visitor.visit_point(rectangle.bottom_right);
visitor.visit_point(&rectangle.top_left);
visitor.visit_point(&rectangle.bottom_right);
}
pub fn visit_point<V>(_visitor: &mut V, _point: &Point)
where
V: Visitor + ?Sized,
{}
trait Visitable {
fn apply(&self, visitor: &mut dyn Visitor);
fn apply(&self, visitor: &mut impl Visitor);
}
impl Visitable for dyn Arc {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_arc(self);
}
}
impl Visitable for Rectangle {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_rectangle(self);
}
}
impl Visitable for Point {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_point(self);
}
}
4 changes: 2 additions & 2 deletions despatma/tests/expand/visitor/helper_tmpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ visitor!(
dyn Arc,

#[helper_tmpl = {
visitor.visit_point(rectangle.top_left);
visitor.visit_point(rectangle.bottom_right);
visitor.visit_point(&rectangle.top_left);
visitor.visit_point(&rectangle.bottom_right);
}]
Rectangle,

Expand Down
12 changes: 6 additions & 6 deletions despatma/tests/expand/visitor/multiple.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,30 +38,30 @@ where
V: Visitor + ?Sized,
{}
trait Visitable {
fn apply(&self, visitor: &mut dyn Visitor);
fn apply(&self, visitor: &mut impl Visitor);
}
impl Visitable for dyn Circle {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_circle(self);
}
}
impl Visitable for Rectangle {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_rectangle(self);
}
}
impl Visitable for dyn Sphere {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_sphere(self);
}
}
impl Visitable for Arc {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_arc(self);
}
}
impl Visitable for dyn Cube {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_cube(self);
}
}
6 changes: 3 additions & 3 deletions despatma/tests/expand/visitor/no_default.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ where
V: Visitor + ?Sized,
{}
trait Visitable {
fn apply(&self, visitor: &mut dyn Visitor);
fn apply(&self, visitor: &mut impl Visitor);
}
impl Visitable for dyn Button {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_button(self);
}
}
impl Visitable for Window {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_window(self);
}
}
4 changes: 2 additions & 2 deletions despatma/tests/expand/visitor/simple.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ where
V: Visitor + ?Sized,
{}
trait Visitable {
fn apply(&self, visitor: &mut dyn Visitor);
fn apply(&self, visitor: &mut impl Visitor);
}
impl Visitable for Window {
fn apply(&self, visitor: &mut dyn Visitor) {
fn apply(&self, visitor: &mut impl Visitor) {
visitor.visit_window(self);
}
}

0 comments on commit 05f7439

Please sign in to comment.