Skip to content

Commit

Permalink
Pass value_changed to macro_rules! macros
Browse files Browse the repository at this point in the history
In Rust, variable identifiers in a `macro_rules!` body are resolved
in the scope of tht body - they cannot see through to the caller's body.
For example, the following code errors:

`rust
macro_rules! weird_ident {
    () => { my_ident; }
}

fn main() {
    let my_ident = 1;
    weird_ident!();
}
`

However, due to a compiler bug (rust-lang/rust#43081),
this kind of code current compiles when a procedural macro is invoked by
a `macro_rules!` macro. Eventually, this will cause a compilation error.

In the `color!` and `slider!` macro, you're currently writing an expression
involving `value_changed`, and passing it to a procedural macro (`html!`).
However, `value_changed` comes from the body of the caller of `color!`/`slider!`,
so this code will stop compiling once the compiler bug is fixed.

Fortunately, the identifier of `value_changed` can be passed into
`color!` and `slider!`. This modified code will with the current version of
Rust, as well as future version that causes the old code into an error.

I also ran `cargo update` to bump the dependencies in your Cargo.lock.
This will allow your crate to continue to compile when the compiler bug is fixed,
as you are depending on some crates (e.g. `syn`) that have released updates
to address the issue.

Feel free to ask me about any questions you may have. For more details,
see rust-lang/rust#72622
  • Loading branch information
Aaron1011 committed May 31, 2020
1 parent adf4937 commit 9c78df9
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 78 deletions.
72 changes: 36 additions & 36 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl Component for ColorPicker {

#[macro_export]
macro_rules! color {
( $name:expr, $value:expr ) => {
html!(<ColorPicker name=$name value=&mut $value as *mut String value_changed=value_changed.clone() />)
( $name:expr, $value:expr, $value_changed:expr) => {
html!(<ColorPicker name=$name value=&mut $value as *mut String value_changed=$value_changed.clone() />)
};
}
14 changes: 7 additions & 7 deletions src/parts/eyes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ impl Eyes {
pub fn controls(&mut self, value_changed: Callback<()>) -> Html {
html!(
<Group name="Eyes">
{crate::color!("Color", self.color)}
{crate::slider!("Width", 0.0, 6.0, self.size.0)}
{crate::slider!("Height", 0.0, 3.0, self.size.1)}
{crate::slider!("Separation", 0.0, 6.0, self.separation)}
{crate::color!("Color", self.color, value_changed)}
{crate::slider!("Width", 0.0, 6.0, self.size.0, value_changed)}
{crate::slider!("Height", 0.0, 3.0, self.size.1, value_changed)}
{crate::slider!("Separation", 0.0, 6.0, self.separation, value_changed)}
<Group name="Brows">
{crate::slider!("B1", 0.0, 2.0, self.brows.end_height.0)}
{crate::slider!("B2", 0.0, 2.0, self.brows.curve)}
{crate::slider!("B3", 0.0, 2.0, self.brows.end_height.1)}
{crate::slider!("B1", 0.0, 2.0, self.brows.end_height.0, value_changed)}
{crate::slider!("B2", 0.0, 2.0, self.brows.curve, value_changed)}
{crate::slider!("B3", 0.0, 2.0, self.brows.end_height.1, value_changed)}
</Group>
</Group>
)
Expand Down
22 changes: 11 additions & 11 deletions src/parts/face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ impl Forehead {
pub fn controls(&mut self, value_changed: Callback<()>) -> Html {
html!(
<Group name="Forehead">
{crate::slider!("RX", 0.0, 7.0, self.roundness.0)}
{crate::slider!("RY", 0.0, 10.0, self.roundness.1)}
{crate::slider!("RX", 0.0, 7.0, self.roundness.0, value_changed)}
{crate::slider!("RY", 0.0, 10.0, self.roundness.1, value_changed)}
</Group>
)
}
Expand All @@ -53,10 +53,10 @@ impl Fringe {
pub fn controls(&mut self, value_changed: Callback<()>) -> Html {
html!(
<Group name="Fringe">
{crate::color!("Color", self.hair_color)}
{crate::slider!("Thickness", 0.0, 10.0, self.thickness)}
{crate::slider!("RX", 0.0, 7.0, self.roundness.0)}
{crate::slider!("RY", 0.0, 10.0, self.roundness.1)}
{crate::color!("Color", self.hair_color, value_changed)}
{crate::slider!("Thickness", 0.0, 10.0, self.thickness, value_changed)}
{crate::slider!("RX", 0.0, 7.0, self.roundness.0, value_changed)}
{crate::slider!("RY", 0.0, 10.0, self.roundness.1, value_changed)}
</Group>
)
}
Expand All @@ -70,8 +70,8 @@ impl Chin {
pub fn controls(&mut self, value_changed: Callback<()>) -> Html {
html!(
<Group name="Chin">
{crate::slider!("RX", 0.0, 7.0, self.roundness.0)}
{crate::slider!("RY", 0.0, 10.0, self.roundness.1)}
{crate::slider!("RX", 0.0, 7.0, self.roundness.0, value_changed)}
{crate::slider!("RY", 0.0, 10.0, self.roundness.1, value_changed)}
</Group>
)
}
Expand All @@ -90,9 +90,9 @@ impl Face {
pub fn controls(&mut self, value_changed: Callback<()>) -> Html {
html!(
<Group name="Face">
{crate::color!("Skin", self.skin_color)}
{crate::slider!("Width", 0.0, 16.0, self.width)}
{crate::slider!("Height", 0.0, 32.0, self.height)}
{crate::color!("Skin", self.skin_color, value_changed)}
{crate::slider!("Width", 0.0, 16.0, self.width, value_changed)}
{crate::slider!("Height", 0.0, 32.0, self.height, value_changed)}
{self.forehead.controls(value_changed.clone())}
{self.fringe.controls(value_changed.clone())}
{self.chin.controls(value_changed.clone())}
Expand Down
2 changes: 1 addition & 1 deletion src/parts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl ScaledHead {
html!(
<>
<Group name="Grid">
{crate::slider!("Size", 8.0, 32.0, self.scale)}
{crate::slider!("Size", 8.0, 32.0, self.scale, value_changed)}
</Group>
{self.head.controls(value_changed.clone())}
</>
Expand Down
18 changes: 9 additions & 9 deletions src/parts/mouth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ impl TopLip {
pub fn controls(&mut self, value_changed: Callback<()>) -> Html {
html!(
<Group name="Top Lip">
{crate::slider!("RX", 0.0, 2.0, self.roundness.0)}
{crate::slider!("RY", 0.0, 2.0, self.roundness.1)}
{crate::slider!("RX", 0.0, 2.0, self.roundness.0, value_changed)}
{crate::slider!("RY", 0.0, 2.0, self.roundness.1, value_changed)}
<Group name="Philtrum">
{crate::slider!("Width", 0.0, 1.0, self.philtrum.0)}
{crate::slider!("Position", 0.0, 1.0, self.philtrum.1)}
{crate::slider!("Width", 0.0, 1.0, self.philtrum.0, value_changed)}
{crate::slider!("Position", 0.0, 1.0, self.philtrum.1, value_changed)}
</Group>
</Group>
)
Expand All @@ -30,8 +30,8 @@ impl BottomLip {
pub fn controls(&mut self, value_changed: Callback<()>) -> Html {
html!(
<Group name="Bottom Lip">
{crate::slider!("RX", 0.0, 2.0, self.roundness.0)}
{crate::slider!("RY", 0.0, 2.0, self.roundness.1)}
{crate::slider!("RX", 0.0, 2.0, self.roundness.0, value_changed)}
{crate::slider!("RY", 0.0, 2.0, self.roundness.1, value_changed)}
</Group>
)
}
Expand All @@ -50,12 +50,12 @@ impl Mouth {
pub fn controls(&mut self, value_changed: Callback<()>) -> Html {
html!(
<Group name="Mouth">
{crate::color!("Color", self.color)}
{crate::color!("Color", self.color, value_changed)}
{self.top_lip.controls(value_changed.clone())}
{self.bottom_lip.controls(value_changed.clone())}
<Group name="Smile">
{crate::slider!("Width", 0.0, 2.0, self.smile.0)}
{crate::slider!("Height", 0.0, 2.0, self.smile.1)}
{crate::slider!("Width", 0.0, 2.0, self.smile.0, value_changed)}
{crate::slider!("Height", 0.0, 2.0, self.smile.1, value_changed)}
</Group>
</Group>
)
Expand Down
20 changes: 10 additions & 10 deletions src/parts/nose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@ impl Nose {
pub fn controls(&mut self, value_changed: Callback<()>) -> Html {
html!(
<Group name="Nose">
{crate::slider!("Width", 0.0, 4.0, self.width)}
{crate::slider!("Height", 0.0, 5.0, self.height)}
{crate::slider!("Width", 0.0, 4.0, self.width, value_changed)}
{crate::slider!("Height", 0.0, 5.0, self.height, value_changed)}
<Group name="Bridge">
<Group name="Gap">
{crate::slider!("X", 0.0, 2.0, self.bridge_gap.0)}
{crate::slider!("Y", 0.0, 2.0, self.bridge_gap.1)}
{crate::slider!("X", 0.0, 2.0, self.bridge_gap.0, value_changed)}
{crate::slider!("Y", 0.0, 2.0, self.bridge_gap.1, value_changed)}
</Group>
<Group name="Top Curve">
{crate::slider!("X", 0.0, 4.0, self.bridge_top_curve.0)}
{crate::slider!("Y", 0.0, 4.0, self.bridge_top_curve.1)}
{crate::slider!("X", 0.0, 4.0, self.bridge_top_curve.0, value_changed)}
{crate::slider!("Y", 0.0, 4.0, self.bridge_top_curve.1, value_changed)}
</Group>
<Group name="Side Curve">
{crate::slider!("X", 0.0, 1.0, self.bridge_side_curve.0)}
{crate::slider!("Y", 0.0, 1.0, self.bridge_side_curve.1)}
{crate::slider!("X", 0.0, 1.0, self.bridge_side_curve.0, value_changed)}
{crate::slider!("Y", 0.0, 1.0, self.bridge_side_curve.1, value_changed)}
</Group>
{crate::slider!("Nostril", 0.0, 0.5, self.nostril_radius)}
{crate::slider!("Tip", 0.0, 0.5, self.tip_curve)}
{crate::slider!("Nostril", 0.0, 0.5, self.nostril_radius, value_changed)}
{crate::slider!("Tip", 0.0, 0.5, self.tip_curve, value_changed)}
</Group>
</Group>
)
Expand Down
4 changes: 2 additions & 2 deletions src/slider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl Component for Slider {

#[macro_export]
macro_rules! slider {
( $name:expr, $min:expr, $max:expr, $value:expr ) => {
html!(<Slider name=$name min=$min max=$max value=&mut $value as *mut Value value_changed=value_changed.clone() />)
( $name:expr, $min:expr, $max:expr, $value:expr, $value_changed:ident ) => {
html!(<Slider name=$name min=$min max=$max value=&mut $value as *mut Value value_changed=$value_changed.clone() />)
};
}

0 comments on commit 9c78df9

Please sign in to comment.