Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clippy deny because of multiple "to_string" implementations #35

Closed
friedemannsommer opened this issue Nov 22, 2023 · 7 comments
Closed

Comments

@friedemannsommer
Copy link
Contributor

Running clippy with the latest version (0.14.0) leads to an error because of "inherent_to_string_shadow_display".

Example code

markup::define! {
    Layout<'styles, Children: markup::Render>(
        inline_styles: &'styles str,
        children: Children,
    ) {
        @markup::doctype()
        html {
            head {
                meta[charset="utf-8"];
                meta[name="viewport", content="width=device-width, initial-scale=1, user-scalable=1"];
                title { "Example" }
                style {
                    @ inline_styles
                }
            }
            body {
                @ children
            }
        }
    }
}
Macro expansion
pub struct Layout<'styles, Children: markup::Render> {
    pub inline_styles: &'styles str,
    pub children: Children,
}

impl<'styles, Children: markup::Render> Layout<'styles, Children> {
    #[inline]
    #[allow(unused)]
    pub fn to_string(&self) -> String {
        let mut string = String::with_capacity(324usize);
        let _ = ::markup::Render::render(self, &mut string);
        string
    }
}

impl<'styles, Children: markup::Render> ::markup::Render for Layout<'styles, Children> {
    fn render(&self, __writer: &mut impl std::fmt::Write) -> std::fmt::Result {
        let Layout {
            inline_styles,
            children,
        } = self;
        ::markup::Render::render(&(markup::doctype()), __writer)?;
        __writer.write_str("<html><head><meta")?;
        let __value = "utf-8";
        if ::markup::RenderAttributeValue::is_none(&__value)
            || ::markup::RenderAttributeValue::is_false(&__value)
        {
        } else if ::markup::RenderAttributeValue::is_true(&__value) {
            __writer.write_str(" charset")?;
        } else {
            __writer.write_str(" charset=\"")?;
            ::markup::Render::render(&(__value), __writer)?;
            __writer.write_str("\"")?;
        }
        __writer.write_str("><meta")?;
        let __value = "viewport";
        if ::markup::RenderAttributeValue::is_none(&__value)
            || ::markup::RenderAttributeValue::is_false(&__value)
        {
        } else if ::markup::RenderAttributeValue::is_true(&__value) {
            __writer.write_str(" name")?;
        } else {
            __writer.write_str(" name=\"")?;
            ::markup::Render::render(&(__value), __writer)?;
            __writer.write_str("\"")?;
        }
        let __value = "width=device-width, initial-scale=1, user-scalable=1";
        if ::markup::RenderAttributeValue::is_none(&__value)
            || ::markup::RenderAttributeValue::is_false(&__value)
        {
        } else if ::markup::RenderAttributeValue::is_true(&__value) {
            __writer.write_str(" content")?;
        } else {
            __writer.write_str(" content=\"")?;
            ::markup::Render::render(&(__value), __writer)?;
            __writer.write_str("\"")?;
        }
        __writer.write_str("><title>Example</title><style>")?;
        ::markup::Render::render(&(inline_styles), __writer)?;
        __writer.write_str("</style></head><body>")?;
        ::markup::Render::render(&(children), __writer)?;
        __writer.write_str("</body></html>")?;
        Ok(())
    }
}

impl<'styles, Children: markup::Render> std::fmt::Display for Layout<'styles, Children> {
    #[inline]
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        ::markup::Render::render(self, fmt)
    }
}
Relevant code sections

impl ... to_string(&self) -> String

pub fn to_string(&self) -> String {
let mut string = String::with_capacity(#size_hint);
// Ignoring the result because writing to a String can't fail.
let _ = ::markup::Render::render(self, &mut string);
string
}

impl Display for ...

impl #impl_generics std::fmt::Display for #name #ty_generics #where_clause {
#[inline]
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
::markup::Render::render(self, fmt)
}
}

Versions
  • rustc - 1.73.0 (cc66ad468 2023-10-03)
  • cargo - 1.73.0
  • clippy - 0.1.73
  • markup - 0.14.0
@utkarshkukreti
Copy link
Owner

Thanks for the detailed report!

I found this issue on the clippy repo. The reason we have a manual to_string() is exactly the same as the creator of that issue explains - we have a faster to_string() implementation which overrides the slower fmt based implementation.

I think we should add a #![allow(clippy::inherent_to_string_shadow_display)] on the generated code.

@Kijewski
Copy link
Contributor

Yes, IMO suppressing clippy::inherent_to_string_shadow_display is right action. Clippy does not take into account that the explicit implementation is there for a reason: to pre-allocate memory for the returned string.

@friedemannsommer
Copy link
Contributor Author

friedemannsommer commented Nov 22, 2023

I found this issue on the clippy repo. The reason we have a manual to_string() is exactly the same as the creator of that issue explains - we have a faster to_string() implementation which overrides the slower fmt based implementation.

I think we should add a #![allow(clippy::inherent_to_string_shadow_display)] on the generated code.

Sounds good to me.

@utkarshkukreti
Copy link
Owner

utkarshkukreti commented Nov 22, 2023

I pushed e5cdaaf, let's see if all the CI tests pass on the oldest Rust version we support.

@utkarshkukreti
Copy link
Owner

@friedemannsommer can you try out 0a31d3d and let me know if it works for you? I'll make a release hopefully by tomorrow.

markup = { git = "https://github.com/utkarshkukreti/markup.rs", rev = "0a31d3da565214e24a527b15c93dd0b02b6a9ae6" }

@friedemannsommer
Copy link
Contributor Author

@utkarshkukreti it works without any issue.

Thank you for the quick response and fix 👍.

Macro expansion
pub struct Layout<'styles, Children: markup::Render> {
    pub inline_styles: &'styles str,
    pub children: Children,
}

impl<'styles, Children: markup::Render> Layout<'styles, Children> {
    #[inline]
    #[allow(clippy::inherent_to_string_shadow_display)]
    #[allow(unused)]
    pub fn to_string(&self) -> String {
        let mut string = String::with_capacity(324usize);
        let _ = ::markup::Render::render(self, &mut string);
        string
    }
}

impl<'styles, Children: markup::Render> ::markup::Render for Layout<'styles, Children> {
    fn render(&self, __writer: &mut impl std::fmt::Write) -> std::fmt::Result {
        let Layout {
            inline_styles,
            children,
        } = self;
        ::markup::Render::render(&(markup::doctype()), __writer)?;
        __writer.write_str("<html><head><meta")?;
        let __value = "utf-8";
        if ::markup::RenderAttributeValue::is_none(&__value)
            || ::markup::RenderAttributeValue::is_false(&__value)
        {
        } else if ::markup::RenderAttributeValue::is_true(&__value) {
            __writer.write_str(" charset")?;
        } else {
            __writer.write_str(" charset=\"")?;
            ::markup::Render::render(&(__value), __writer)?;
            __writer.write_str("\"")?;
        }
        __writer.write_str("><meta")?;
        let __value = "viewport";
        if ::markup::RenderAttributeValue::is_none(&__value)
            || ::markup::RenderAttributeValue::is_false(&__value)
        {
        } else if ::markup::RenderAttributeValue::is_true(&__value) {
            __writer.write_str(" name")?;
        } else {
            __writer.write_str(" name=\"")?;
            ::markup::Render::render(&(__value), __writer)?;
            __writer.write_str("\"")?;
        }
        let __value = "width=device-width, initial-scale=1, user-scalable=1";
        if ::markup::RenderAttributeValue::is_none(&__value)
            || ::markup::RenderAttributeValue::is_false(&__value)
        {
        } else if ::markup::RenderAttributeValue::is_true(&__value) {
            __writer.write_str(" content")?;
        } else {
            __writer.write_str(" content=\"")?;
            ::markup::Render::render(&(__value), __writer)?;
            __writer.write_str("\"")?;
        }
        __writer.write_str("><title>Example</title><style>")?;
        ::markup::Render::render(&(inline_styles), __writer)?;
        __writer.write_str("</style></head><body>")?;
        ::markup::Render::render(&(children), __writer)?;
        __writer.write_str("</body></html>")?;
        Ok(())
    }
}

impl<'styles, Children: markup::Render> std::fmt::Display for Layout<'styles, Children> {
    #[inline]
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        ::markup::Render::render(self, fmt)
    }
}
Versions

@utkarshkukreti
Copy link
Owner

0.15.0 has been published.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants