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

Missing AsRef<str> implementation for unnamed enums #3886

Open
demosdemon opened this issue Oct 18, 2024 · 1 comment
Open

Missing AsRef<str> implementation for unnamed enums #3886

demosdemon opened this issue Oct 18, 2024 · 1 comment

Comments

@demosdemon
Copy link

The generated code for named enums includes an AsRef<str> implementation that defers to Self::as_str.

rustTemplate(
"""
impl #{AsRef}<str> for ${context.enumName} {
fn as_ref(&self) -> &str {
self.as_str()
}
}
""",
*preludeScope,
)

Example:

impl ::std::convert::AsRef<str> for StageType {
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

The implementation for unnamed enums should do the same, but doesn't.

Example:

// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.

/// Targets represent instances in underlying systems, like packages, code deploy apps, etc.
#[non_exhaustive]
#[derive(
    ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::Ord, ::std::cmp::PartialEq, ::std::cmp::PartialOrd, ::std::fmt::Debug, ::std::hash::Hash,
)]
pub struct TargetType(String);
impl TargetType {
    /// Returns the `&str` value of the enum member.
    pub fn as_str(&self) -> &str {
        &self.0
    }
    /// Returns all the `&str` representations of the enum members.
    pub const fn values() -> &'static [&'static str] {
        &["BATS", "CD", "CF", "DG", "ENV", "GEN", "OS", "PKG", "VS"]
    }
}
impl ::std::str::FromStr for TargetType {
    type Err = ::std::convert::Infallible;

    fn from_str(s: &str) -> ::std::result::Result<Self, <Self as ::std::str::FromStr>::Err> {
        ::std::result::Result::Ok(TargetType::from(s))
    }
}
impl<T> ::std::convert::From<T> for TargetType
where
    T: ::std::convert::AsRef<str>,
{
    fn from(s: T) -> Self {
        TargetType(s.as_ref().to_owned())
    }
}

This causes generated clients for models that use these unnamed enums in url path or query parameters to not build due to the AsRef<str> binding here:

/// Format a given string as a query string.
pub fn fmt_string<T: AsRef<str>>(t: T) -> String {
utf8_percent_encode(t.as_ref(), BASE_SET).to_string()
}

@drganjoo
Copy link
Contributor

Unnamed enums already have a blanket implementation for converting from any type that implements AsRef<str>:

impl<T> From<T> for TargetType
where
    T: AsRef<str>,

If we implement AsRef<str> for TargetType, it results in a compilation error:

   conflicting implementation in crate `core`:
           impl<T> From<T> for T;

This conflict occurs because implementing AsRef<str> for TargetType would make TargetType itself eligible for our blanket implementation impl<T> From<T> for TargetType (since it would now implement AsRef<str>). This conflicts with the built-in blanket implementation in the core crate that allows converting a type into itself.

As a workaround, you can use the existing .as_str() method on unnamed enums to get a string reference when needed.

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

2 participants