From 9b1afa4518350052455c29a381cc91861b29febf Mon Sep 17 00:00:00 2001 From: Uday Prakash Date: Mon, 12 Jan 2026 20:01:27 -0600 Subject: [PATCH 1/2] fix: Add AsRef impl for unnamed enums Unnamed enums (newtype string wrappers like `pub struct Foo(String)`) were missing the `AsRef` implementation that named enums have. This caused compilation errors when using unnamed enums with APIs that require `AsRef`, such as `aws_smithy_http::query::fmt_string()`. Changes: - Add `impl AsRef` to `renderUnnamedEnum()` in EnumGenerator.kt - Change `impl From where T: AsRef` to `impl From<&str>` in ClientEnumGenerator.kt to avoid conflicting impl error (E0119) when the type itself implements `AsRef` --- .../client/smithy/generators/ClientEnumGenerator.kt | 6 +++--- .../codegen/core/smithy/generators/EnumGenerator.kt | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGenerator.kt index 4b5cac04ab7..9247c8a5bef 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGenerator.kt @@ -84,9 +84,9 @@ data class InfallibleEnumType( writable { rustTemplate( """ - impl #{From} for ${context.enumName} where T: #{AsRef} { - fn from(s: T) -> Self { - ${context.enumName}(s.as_ref().to_owned()) + impl #{From}<&str> for ${context.enumName} { + fn from(s: &str) -> Self { + ${context.enumName}(s.to_owned()) } } """, diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/EnumGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/EnumGenerator.kt index 80bceeb6306..c18999476c5 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/EnumGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/EnumGenerator.kt @@ -274,6 +274,16 @@ open class EnumGenerator( rust("&self.0") }, ) + rustTemplate( + """ + impl #{AsRef} for ${context.enumName} { + fn as_ref(&self) -> &str { + self.as_str() + } + } + """, + *preludeScope, + ) // impl From for Blah { ... } enumType.implFromForStrForUnnamedEnum(context)(this) // impl FromStr for Blah { ... } From 08bea9112dc48cbd70d13fc57e4560bfa21a6033 Mon Sep 17 00:00:00 2001 From: Uday Prakash Date: Mon, 12 Jan 2026 20:09:35 -0600 Subject: [PATCH 2/2] test: Add tests for unnamed enums implementing AsRef Add tests to verify that unnamed enums correctly implement AsRef: - EnumGeneratorTest: Test that unnamed enums can be used with AsRef - ClientEnumGeneratorTest: Test the same for client-generated enums These tests verify the fix that adds impl AsRef to unnamed enums. --- .../generators/ClientEnumGeneratorTest.kt | 34 +++++++++++++++++++ .../smithy/generators/EnumGeneratorTest.kt | 34 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGeneratorTest.kt index f04cef05c75..74584788271 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGeneratorTest.kt @@ -72,6 +72,40 @@ class ClientEnumGeneratorTest { expectMatchExpressionCompiles(modelV2, "test#SomeEnum", variant3AsVariant3) } + @Test + fun `unnamed enums implement AsRef`() { + val model = + """ + namespace test + @enum([ + { value: "Foo" }, + { value: "Bar" }, + ]) + string SomeEnum + """.asSmithyModel() + + val shape = model.lookup("test#SomeEnum") + val context = testClientCodegenContext(model) + val project = TestWorkspace.testProject(context.symbolProvider) + project.moduleFor(shape) { + ClientEnumGenerator(context, shape, emptyList()).render(this) + unitTest( + "unnamed_enums_implement_asref", + """ + let foo = SomeEnum::from("Foo"); + let foo_ref: &str = foo.as_ref(); + assert_eq!(foo_ref, "Foo"); + + fn takes_asref(s: impl AsRef) -> String { + s.as_ref().to_owned() + } + assert_eq!(takes_asref(SomeEnum::from("Bar")), "Bar"); + """, + ) + } + project.compileAndTest() + } + @Test fun `impl debug for non-sensitive enum should implement the derived debug trait`() { val model = diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/EnumGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/EnumGeneratorTest.kt index d5fe0e7e3f0..916411ce11d 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/EnumGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/EnumGeneratorTest.kt @@ -235,6 +235,40 @@ class EnumGeneratorTest { project.compileAndTest() } + @Test + fun `unnamed enums implement AsRef`() { + val model = + """ + namespace test + @enum([ + { value: "Foo" }, + { value: "Bar" }, + ]) + string SomeEnum + """.asSmithyModel() + + val shape = model.lookup("test#SomeEnum") + val provider = testSymbolProvider(model) + val project = TestWorkspace.testProject(provider) + project.moduleFor(shape) { + renderEnum(model, provider, shape) + unitTest( + "unnamed_enums_implement_asref", + """ + let foo = SomeEnum::from("Foo"); + let foo_ref: &str = foo.as_ref(); + assert_eq!(foo_ref, "Foo"); + + fn takes_asref(s: impl AsRef) -> String { + s.as_ref().to_owned() + } + assert_eq!(takes_asref(SomeEnum::from("Bar")), "Bar"); + """, + ) + } + project.compileAndTest() + } + @Test fun `it generates unnamed enums`() { val model =