From 17d4b717172f42f3a1da785af8d813339c9ab4d4 Mon Sep 17 00:00:00 2001 From: John DiSanti Date: Thu, 11 May 2023 17:12:57 -0700 Subject: [PATCH 1/7] Fix client operation name collisions with the standard library prelude Operations named `Send` or `Sync` (and probably others) were colliding with the types in the standard library prelude and causing compiler errors. This PR adds tests that include all the type names from the Rust prelude, and fixes the compiler errors they cause. In the future, the `no_implicit_prelude` attribute can be added to certain code generated modules to better enforce that there can't be name collisions, but for now, the `tokio::test` macro doesn't compile with that attribute enabled (and likely other macros from other libraries). --- .../rustsdk/AwsFluentClientDecorator.kt | 9 +- .../smithy/rustsdk/AwsPresigningDecorator.kt | 3 +- .../rustsdk/customize/s3/S3Decorator.kt | 3 +- codegen-client-test/build.gradle.kts | 16 +++ .../codegen/client/smithy/ClientRustModule.kt | 8 +- .../IdempotencyTokenGenerator.kt | 8 +- .../smithy/endpoint/EndpointsDecorator.kt | 14 +- .../smithy/generators/ClientEnumGenerator.kt | 14 +- .../generators/NestedAccessorGenerator.kt | 10 +- .../smithy/generators/PaginatorGenerator.kt | 28 ++-- .../ServiceRuntimePluginGenerator.kt | 15 ++- .../client/CustomizableOperationGenerator.kt | 58 ++++---- .../client/FluentClientGenerator.kt | 43 +++--- .../error/OperationErrorGenerator.kt | 44 ++++-- .../http/RequestBindingGenerator.kt | 24 ++-- .../protocol/MakeOperationGenerator.kt | 13 +- .../protocol/ProtocolTestGenerator.kt | 2 +- .../protocols/HttpBoundProtocolGenerator.kt | 14 +- .../naming-obstacle-course-prelude-ops.smithy | 92 +++++++++++++ ...ing-obstacle-course-prelude-structs.smithy | 125 ++++++++++++++++++ .../codegen/core/rustlang/CargoDependency.kt | 2 +- .../rust/codegen/core/rustlang/RustModule.kt | 21 +-- .../rust/codegen/core/rustlang/RustType.kt | 3 +- .../rust/codegen/core/rustlang/RustWriter.kt | 24 +++- .../rust/codegen/core/smithy/RuntimeType.kt | 56 +++++++- .../smithy/generators/BuilderGenerator.kt | 23 ++-- .../core/smithy/generators/EnumGenerator.kt | 2 +- .../core/smithy/generators/Instantiator.kt | 13 +- .../core/smithy/generators/UnionGenerator.kt | 18 ++- .../generators/error/ErrorImplGenerator.kt | 6 +- .../parse/EventStreamUnmarshallerGenerator.kt | 2 +- 31 files changed, 540 insertions(+), 173 deletions(-) create mode 100644 codegen-core/common-test-models/naming-obstacle-course-prelude-ops.smithy create mode 100644 codegen-core/common-test-models/naming-obstacle-course-prelude-structs.smithy diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt index cca5c9f910..fa9c5ed63f 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt @@ -223,6 +223,7 @@ private fun renderCustomizableOperationSendMethod( val combinedGenerics = operationGenerics + handleGenerics val codegenScope = arrayOf( + *RuntimeType.preludeScope, "combined_generics_decl" to combinedGenerics.declaration(), "handle_generics_bounds" to handleGenerics.bounds(), "SdkSuccess" to RuntimeType.sdkSuccess(runtimeConfig), @@ -238,11 +239,11 @@ private fun renderCustomizableOperationSendMethod( #{handle_generics_bounds:W} { /// Sends this operation's request - pub async fn send(self) -> Result> + pub async fn send(self) -> #{Result}> where - E: std::error::Error + Send + Sync + 'static, - O: #{ParseHttpResponse}> + Send + Sync + Clone + 'static, - Retry: #{ClassifyRetry}<#{SdkSuccess}, #{SdkError}> + Send + Sync + Clone, + E: std::error::Error + #{Send} + #{Sync} + 'static, + O: #{ParseHttpResponse}> + #{Send} + #{Sync} + #{Clone} + 'static, + Retry: #{ClassifyRetry}<#{SdkSuccess}, #{SdkError}> + #{Send} + #{Sync} + #{Clone}, { self.handle.client.call(self.operation).await } diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsPresigningDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsPresigningDecorator.kt index 20d280ddf9..f6a3cd889c 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsPresigningDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsPresigningDecorator.kt @@ -250,6 +250,7 @@ class AwsPresignedFluentBuilderMethod( ) : FluentClientCustomization() { private val codegenScope = ( presigningTypes + arrayOf( + *RuntimeType.preludeScope, "Error" to AwsRuntimeType.presigning().resolve("config::Error"), "SdkError" to RuntimeType.sdkError(runtimeConfig), ) @@ -264,7 +265,7 @@ class AwsPresignedFluentBuilderMethod( pub async fn presigned( self, presigning_config: #{PresigningConfig}, - ) -> Result<#{PresignedRequest}, #{SdkError}<#{OpError}>> + ) -> #{Result}<#{PresignedRequest}, #{SdkError}<#{OpError}>> """, *codegenScope, "OpError" to section.operationErrorType, diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/s3/S3Decorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/s3/S3Decorator.kt index 664494d021..0a2bd05212 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/s3/S3Decorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/s3/S3Decorator.kt @@ -131,6 +131,7 @@ class FilterEndpointTests( class S3ProtocolOverride(codegenContext: CodegenContext) : RestXml(codegenContext) { private val runtimeConfig = codegenContext.runtimeConfig private val errorScope = arrayOf( + *RuntimeType.preludeScope, "Bytes" to RuntimeType.Bytes, "ErrorMetadata" to RuntimeType.errorMetadata(runtimeConfig), "ErrorBuilder" to RuntimeType.errorMetadataBuilder(runtimeConfig), @@ -143,7 +144,7 @@ class S3ProtocolOverride(codegenContext: CodegenContext) : RestXml(codegenContex override fun parseHttpErrorMetadata(operationShape: OperationShape): RuntimeType { return ProtocolFunctions.crossOperationFn("parse_http_error_metadata") { fnName -> rustBlockTemplate( - "pub fn $fnName(response_status: u16, _response_headers: &#{HeaderMap}, response_body: &[u8]) -> Result<#{ErrorBuilder}, #{XmlDecodeError}>", + "pub fn $fnName(response_status: u16, _response_headers: &#{HeaderMap}, response_body: &[u8]) -> #{Result}<#{ErrorBuilder}, #{XmlDecodeError}>", *errorScope, ) { rustTemplate( diff --git a/codegen-client-test/build.gradle.kts b/codegen-client-test/build.gradle.kts index f3796a6911..b833bfb195 100644 --- a/codegen-client-test/build.gradle.kts +++ b/codegen-client-test/build.gradle.kts @@ -92,6 +92,22 @@ val allCodegenTests = "../codegen-core/common-test-models".let { commonModels -> """.trimIndent(), imports = listOf("$commonModels/naming-obstacle-course-structs.smithy"), ), + CodegenTest( + "crate#Config", + "naming_test_prelude_ops", + """ + , "codegen": { "renameErrors": false } + """.trimIndent(), + imports = listOf("$commonModels/naming-obstacle-course-prelude-ops.smithy"), + ), + CodegenTest( + "crate#Config", + "naming_test_prelude_structs", + """ + , "codegen": { "renameErrors": false } + """.trimIndent(), + imports = listOf("$commonModels/naming-obstacle-course-prelude-structs.smithy"), + ), CodegenTest("aws.protocoltests.json#TestService", "endpoint-rules"), CodegenTest("com.aws.example.rust#PokemonService", "pokemon-service-client", imports = listOf("$commonModels/pokemon.smithy", "$commonModels/pokemon-common.smithy")), CodegenTest("com.aws.example.rust#PokemonService", "pokemon-service-awsjson-client", imports = listOf("$commonModels/pokemon-awsjson.smithy", "$commonModels/pokemon-common.smithy")), diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustModule.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustModule.kt index aa1f547dc4..988cac62f4 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustModule.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustModule.kt @@ -26,6 +26,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.ModuleDocProvider import software.amazon.smithy.rust.codegen.core.smithy.ModuleProvider import software.amazon.smithy.rust.codegen.core.smithy.ModuleProviderContext +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.contextName import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticInputTrait @@ -122,7 +123,7 @@ class ClientModuleDocProvider( operation call. For example, this can be used to add an additional HTTP header: ```ignore - ## async fn wrapper() -> Result<(), $moduleUseName::Error> { + ## async fn wrapper() -> #{Result}<(), $moduleUseName::Error> { ## let client: $moduleUseName::Client = unimplemented!(); use #{http}::header::{HeaderName, HeaderValue}; @@ -142,6 +143,7 @@ class ClientModuleDocProvider( ## } ``` """.trimIndent(), + *RuntimeType.preludeScope, "http" to CargoDependency.Http.toDevDependency().toType(), ) } @@ -194,6 +196,10 @@ object ClientModuleProvider : ModuleProvider { operationModuleName, parent = ClientRustModule.Operation, documentationOverride = "Types for the `$contextName` operation.", + // TODO(https://github.com/tokio-rs/tokio/issues/5683): Uncomment the NoImplicitPrelude attribute once this Tokio issue is resolved + // // Disable the Rust prelude since every prelude type should be referenced with its + // // fully qualified name to avoid name collisions with the generated operation shapes. + // additionalAttributes = listOf(Attribute.NoImplicitPrelude) ) } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/IdempotencyTokenGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/IdempotencyTokenGenerator.kt index 8dd67bb9fe..24738036e1 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/IdempotencyTokenGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/IdempotencyTokenGenerator.kt @@ -8,9 +8,10 @@ package software.amazon.smithy.rust.codegen.client.smithy.customizations import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.traits.IdempotencyTokenTrait import software.amazon.smithy.rust.codegen.core.rustlang.Writable -import software.amazon.smithy.rust.codegen.core.rustlang.rust +import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.customize.OperationCustomization import software.amazon.smithy.rust.codegen.core.smithy.customize.OperationSection import software.amazon.smithy.rust.codegen.core.util.findMemberWithTrait @@ -28,12 +29,13 @@ class IdempotencyTokenGenerator(codegenContext: CodegenContext, operationShape: val memberName = symbolProvider.toMemberName(idempotencyTokenMember) return when (section) { is OperationSection.MutateInput -> writable { - rust( + rustTemplate( """ if ${section.input}.$memberName.is_none() { - ${section.input}.$memberName = Some(${section.config}.make_token.make_idempotency_token()); + ${section.input}.$memberName = #{Some}(${section.config}.make_token.make_idempotency_token()); } """, + *preludeScope, ) } else -> emptySection diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/EndpointsDecorator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/EndpointsDecorator.kt index bc101412af..0678a4db40 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/EndpointsDecorator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/EndpointsDecorator.kt @@ -25,6 +25,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.customize.OperationCustomization import software.amazon.smithy.rust.codegen.core.smithy.customize.OperationSection @@ -166,6 +167,7 @@ class EndpointsDecorator : ClientCodegenDecorator { override fun section(section: OperationSection): Writable { val codegenScope = arrayOf( + *RuntimeType.preludeScope, "Params" to typesGenerator.paramsStruct(), "ResolveEndpointError" to types.resolveEndpointError, ) @@ -174,10 +176,10 @@ class EndpointsDecorator : ClientCodegenDecorator { rustTemplate( """ let params_result = #{Params}::builder()#{builderFields:W}.build() - .map_err(|err|#{ResolveEndpointError}::from_source("could not construct endpoint parameters", err)); + .map_err(|err| #{ResolveEndpointError}::from_source("could not construct endpoint parameters", err)); let (endpoint_result, params) = match params_result { - Ok(params) => (${section.config}.endpoint_resolver.resolve_endpoint(¶ms), Some(params)), - Err(e) => (Err(e), None) + #{Ok}(params) => (${section.config}.endpoint_resolver.resolve_endpoint(¶ms), #{Some}(params)), + #{Err}(e) => (#{Err}(e), #{None}) }; """, "builderFields" to builderFields(typesGenerator.params, section), @@ -188,7 +190,7 @@ class EndpointsDecorator : ClientCodegenDecorator { is OperationSection.MutateRequest -> writable { // insert the endpoint the bag rustTemplate("${section.request}.properties_mut().insert(endpoint_result);") - rustTemplate("""if let Some(params) = params { ${section.request}.properties_mut().insert(params); }""") + rustTemplate("""if let #{Some}(params) = params { ${section.request}.properties_mut().insert(params); }""", *codegenScope) } else -> emptySection @@ -199,8 +201,8 @@ class EndpointsDecorator : ClientCodegenDecorator { val node = this return writable { when (node) { - is StringNode -> rust("Some(${node.value.dq()}.to_string())") - is BooleanNode -> rust("Some(${node.value})") + is StringNode -> rustTemplate("#{Some}(${node.value.dq()}.to_string())", *RuntimeType.preludeScope) + is BooleanNode -> rustTemplate("#{Some}(${node.value})", *RuntimeType.preludeScope) else -> PANIC("unsupported default value: $node") } } 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 d1b87591cb..538e1df83b 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 @@ -17,6 +17,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.generators.EnumGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.EnumGeneratorContext import software.amazon.smithy.rust.codegen.core.smithy.generators.EnumMemberModel @@ -60,16 +61,17 @@ data class InfallibleEnumType( } override fun implFromStr(context: EnumGeneratorContext): Writable = writable { - rust( + rustTemplate( """ - impl std::str::FromStr for ${context.enumName} { - type Err = std::convert::Infallible; + impl ::std::str::FromStr for ${context.enumName} { + type Err = ::std::convert::Infallible; - fn from_str(s: &str) -> std::result::Result { - Ok(${context.enumName}::from(s)) + fn from_str(s: &str) -> #{Result} { + #{Ok}(${context.enumName}::from(s)) } } """, + *preludeScope, ) } @@ -98,7 +100,7 @@ data class InfallibleEnumType( """.trimIndent(), ) context.enumMeta.render(this) - rust("struct $UnknownVariantValue(pub(crate) String);") + rustTemplate("struct $UnknownVariantValue(pub(crate) #{String});", *preludeScope) rustBlock("impl $UnknownVariantValue") { // The generated as_str is not pub as we need to prevent users from calling it on this opaque struct. rustBlock("pub(crate) fn as_str(&self) -> &str") { diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/NestedAccessorGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/NestedAccessorGenerator.kt index 2c752814be..138c7eb123 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/NestedAccessorGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/NestedAccessorGenerator.kt @@ -15,6 +15,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.makeOptional import software.amazon.smithy.rust.codegen.core.smithy.mapRustType @@ -72,17 +73,18 @@ class NestedAccessorGenerator(private val codegenContext: CodegenContext) { "" } if (path.isEmpty()) { - rust("Some(input)") + rustTemplate("#{Some}(input)", *preludeScope) } else { val head = path.first() if (symbolProvider.toSymbol(head).isOptional()) { - rust( + rustTemplate( """ let input = match ${ref}input.${symbolProvider.toMemberName(head)} { - None => return None, - Some(t) => t + #{None} => return #{None}, + #{Some}(t) => t }; """, + *preludeScope, ) } else { rust("let input = input.${symbolProvider.toMemberName(head)};") diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/PaginatorGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/PaginatorGenerator.kt index a20a33ecb0..d9709f5ff0 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/PaginatorGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/PaginatorGenerator.kt @@ -16,11 +16,11 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.rustlang.RustType import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.rustlang.render -import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.util.PANIC import software.amazon.smithy.rust.codegen.core.util.findMemberWithTrait @@ -86,6 +86,7 @@ class PaginatorGenerator private constructor( ) private val codegenScope = arrayOf( + *preludeScope, "generics" to generics.decl, "bounds" to generics.bounds, "page_size_setter" to pageSizeSetter(), @@ -158,31 +159,31 @@ class PaginatorGenerator private constructor( /// Create the pagination stream /// /// _Note:_ No requests will be dispatched until the stream is used (eg. with [`.next().await`](tokio_stream::StreamExt::next)). - pub fn send(self) -> impl #{Stream}>> + Unpin + pub fn send(self) -> impl #{Stream}>> + #{Unpin} #{send_bounds:W} { // Move individual fields out of self for the borrow checker let builder = self.builder; let handle = self.handle; - #{fn_stream}::FnStream::new(move |tx| Box::pin(async move { + #{fn_stream}::FnStream::new(move |tx| #{Box}::pin(async move { // Build the input for the first time. If required fields are missing, this is where we'll produce an early error. let mut input = match builder.build().map_err(#{SdkError}::construction_failure) { - Ok(input) => input, - Err(e) => { let _ = tx.send(Err(e)).await; return; } + #{Ok}(input) => input, + #{Err}(e) => { let _ = tx.send(#{Err}(e)).await; return; } }; loop { let op = match input.make_operation(&handle.conf) .await .map_err(#{SdkError}::construction_failure) { - Ok(op) => op, - Err(e) => { - let _ = tx.send(Err(e)).await; + #{Ok}(op) => op, + #{Err}(e) => { + let _ = tx.send(#{Err}(e)).await; return; } }; let resp = handle.client.call(op).await; // If the input member is None or it was an error let done = match resp { - Ok(ref resp) => { + #{Ok}(ref resp) => { let new_token = #{output_token}(resp); let is_empty = new_token.map(|token| token.is_empty()).unwrap_or(true); if !is_empty && new_token == input.$inputTokenMember.as_ref() && self.stop_on_duplicate_token { @@ -192,7 +193,7 @@ class PaginatorGenerator private constructor( is_empty } }, - Err(_) => true, + #{Err}(_) => true, }; if tx.send(resp).await.is_err() { // receiving end was dropped @@ -263,7 +264,7 @@ class PaginatorGenerator private constructor( /// _Note: No requests will be dispatched until the stream is used (eg. with [`.next().await`](tokio_stream::StreamExt::next))._ /// /// To read the entirety of the paginator, use [`.collect::, _>()`](tokio_stream::StreamExt::collect). - pub fn send(self) -> impl #{Stream}>> + Unpin + pub fn send(self) -> impl #{Stream}>> + #{Unpin} #{send_bounds:W} { #{fn_stream}::TryFlatMap::new(self.0.send()).flat_map(|page| #{extract_items}(page).unwrap_or_default().into_iter()) } @@ -284,16 +285,17 @@ class PaginatorGenerator private constructor( val memberName = symbolProvider.toMemberName(it) val pageSizeT = symbolProvider.toSymbol(it).rustType().stripOuter().render(true) - rust( + rustTemplate( """ /// Set the page size /// /// _Note: this method will override any previously set value for `$memberName`_ pub fn page_size(mut self, limit: $pageSizeT) -> Self { - self.builder.$memberName = Some(limit); + self.builder.$memberName = #{Some}(limit); self } """, + *preludeScope, ) } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ServiceRuntimePluginGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ServiceRuntimePluginGenerator.kt index 25f9a19a5f..a5a0edca2c 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ServiceRuntimePluginGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ServiceRuntimePluginGenerator.kt @@ -14,6 +14,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.customize.NamedCustomization import software.amazon.smithy.rust.codegen.core.smithy.customize.Section import software.amazon.smithy.rust.codegen.core.smithy.customize.writeCustomizations @@ -67,6 +68,8 @@ class ServiceRuntimePluginGenerator( val runtime = RuntimeType.smithyRuntime(rc) val runtimeApi = RuntimeType.smithyRuntimeApi(rc) arrayOf( + *preludeScope, + "Arc" to RuntimeType.Arc, "AnonymousIdentityResolver" to runtimeApi.resolve("client::identity::AnonymousIdentityResolver"), "BoxError" to runtimeApi.resolve("client::runtime_plugin::BoxError"), "ConfigBag" to runtimeApi.resolve("config_bag::ConfigBag"), @@ -92,17 +95,17 @@ class ServiceRuntimePluginGenerator( """ ##[derive(Debug)] pub(crate) struct ServiceRuntimePlugin { - handle: std::sync::Arc, + handle: #{Arc}, } impl ServiceRuntimePlugin { - pub fn new(handle: std::sync::Arc) -> Self { + pub fn new(handle: #{Arc}) -> Self { Self { handle } } } impl #{RuntimePlugin} for ServiceRuntimePlugin { - fn configure(&self, cfg: &mut #{ConfigBag}, _interceptors: &mut #{Interceptors}) -> Result<(), #{BoxError}> { + fn configure(&self, cfg: &mut #{ConfigBag}, _interceptors: &mut #{Interceptors}) -> #{Result}<(), #{BoxError}> { use #{ConfigBagAccessors}; // HACK: Put the handle into the config bag to work around config not being fully implemented yet @@ -114,7 +117,7 @@ class ServiceRuntimePluginGenerator( cfg.set_http_auth_schemes(http_auth_schemes); // Set an empty auth option resolver to be overridden by operations that need auth. - cfg.set_auth_option_resolver(#{StaticAuthOptionResolver}::new(Vec::new())); + cfg.set_auth_option_resolver(#{StaticAuthOptionResolver}::new(#{Vec}::new())); let endpoint_resolver = #{DefaultEndpointResolver}::<#{Params}>::new( #{SharedEndpointResolver}::from(self.handle.conf.endpoint_resolver())); @@ -125,9 +128,9 @@ class ServiceRuntimePluginGenerator( // TODO(RuntimePlugins): Replace this with the correct long-term solution let sleep_impl = self.handle.conf.sleep_impl(); - let connection: Box = self.handle.conf.http_connector() + let connection: #{Box} = self.handle.conf.http_connector() .and_then(move |c| c.connector(&#{ConnectorSettings}::default(), sleep_impl)) - .map(|c| Box::new(#{DynConnectorAdapter}::new(c)) as _) + .map(|c| #{Box}::new(#{DynConnectorAdapter}::new(c)) as _) .expect("connection set"); cfg.set_connection(connection); diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/CustomizableOperationGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/CustomizableOperationGenerator.kt index a45bad43d0..d16d927d7f 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/CustomizableOperationGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/CustomizableOperationGenerator.kt @@ -14,6 +14,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.RustCrate /** @@ -54,33 +55,27 @@ class CustomizableOperationGenerator( val combinedGenerics = operationGenerics + handleGenerics val codegenScope = arrayOf( + *preludeScope, + "Arc" to RuntimeType.Arc, + "Infallible" to RuntimeType.stdConvert.resolve("Infallible"), // SDK Types - "http_result" to smithyHttp.resolve("result"), - "http_body" to smithyHttp.resolve("body"), "HttpRequest" to RuntimeType.HttpRequest, "handle_generics_decl" to handleGenerics.declaration(), "handle_generics_bounds" to handleGenerics.bounds(), "operation_generics_decl" to operationGenerics.declaration(), "combined_generics_decl" to combinedGenerics.declaration(), "customize_module" to ClientRustModule.Client.customize, + "SdkBody" to RuntimeType.sdkBody(runtimeConfig), ) writer.rustTemplate( """ - use crate::client::Handle; - - use #{http_body}::SdkBody; - use #{http_result}::SdkError; - - use std::convert::Infallible; - use std::sync::Arc; - /// A wrapper type for [`Operation`](aws_smithy_http::operation::Operation)s that allows for /// customization of the operation before it is sent. A `CustomizableOperation` may be sent /// by calling its [`.send()`][#{customize_module}::CustomizableOperation::send] method. ##[derive(Debug)] pub struct CustomizableOperation#{combined_generics_decl:W} { - pub(crate) handle: Arc, + pub(crate) handle: #{Arc}, pub(crate) operation: Operation#{operation_generics_decl:W}, } @@ -91,19 +86,19 @@ class CustomizableOperationGenerator( /// Allows for customizing the operation's request pub fn map_request( mut self, - f: impl FnOnce(#{HttpRequest}) -> Result<#{HttpRequest}, E>, - ) -> Result { + f: impl #{FnOnce}(#{HttpRequest}<#{SdkBody}>) -> #{Result}<#{HttpRequest}<#{SdkBody}>, E>, + ) -> #{Result} { let (request, response) = self.operation.into_request_response(); let request = request.augment(|req, _props| f(req))?; self.operation = Operation::from_parts(request, response); - Ok(self) + #{Ok}(self) } /// Convenience for `map_request` where infallible direct mutation of request is acceptable - pub fn mutate_request(self, f: impl FnOnce(&mut #{HttpRequest})) -> Self { + pub fn mutate_request(self, f: impl #{FnOnce}(&mut #{HttpRequest}<#{SdkBody}>)) -> Self { self.map_request(|mut req| { f(&mut req); - Result::<_, Infallible>::Ok(req) + #{Result}::<_, #{Infallible}>::Ok(req) }) .expect("infallible") } @@ -111,19 +106,19 @@ class CustomizableOperationGenerator( /// Allows for customizing the entire operation pub fn map_operation( mut self, - f: impl FnOnce(Operation#{operation_generics_decl:W}) -> Result, - ) -> Result { + f: impl #{FnOnce}(Operation#{operation_generics_decl:W}) -> #{Result}, + ) -> #{Result} { self.operation = f(self.operation)?; - Ok(self) + #{Ok}(self) } /// Direct access to read the HTTP request - pub fn request(&self) -> &#{HttpRequest} { + pub fn request(&self) -> &#{HttpRequest}<#{SdkBody}> { self.operation.request() } /// Direct access to mutate the HTTP request - pub fn request_mut(&mut self) -> &mut #{HttpRequest} { + pub fn request_mut(&mut self) -> &mut #{HttpRequest}<#{SdkBody}> { self.operation.request_mut() } } @@ -142,6 +137,7 @@ fun renderCustomizableOperationSend(runtimeConfig: RuntimeConfig, generics: Flue val combinedGenerics = operationGenerics + handleGenerics val codegenScope = arrayOf( + *preludeScope, "combined_generics_decl" to combinedGenerics.declaration(), "handle_generics_bounds" to handleGenerics.bounds(), "ParseHttpResponse" to smithyHttp.resolve("response::ParseHttpResponse"), @@ -160,13 +156,13 @@ fun renderCustomizableOperationSend(runtimeConfig: RuntimeConfig, generics: Flue #{handle_generics_bounds:W} { /// Sends this operation's request - pub async fn send(self) -> Result> + pub async fn send(self) -> #{Result}> where - E: std::error::Error + Send + Sync + 'static, - O: #{ParseHttpResponse}> + Send + Sync + Clone + 'static, - Retry: Send + Sync + Clone, - Retry: #{ClassifyRetry}<#{SdkSuccess}, #{SdkError}> + Send + Sync + Clone, - ::Policy: #{SmithyRetryPolicy} + Clone, + E: std::error::Error + #{Send} + #{Sync} + 'static, + O: #{ParseHttpResponse}> + #{Send} + #{Sync} + #{Clone} + 'static, + Retry: #{Send} + #{Sync} + #{Clone}, + Retry: #{ClassifyRetry}<#{SdkSuccess}, #{SdkError}> + #{Send} + #{Sync} + #{Clone}, + ::Policy: #{SmithyRetryPolicy} + #{Clone}, { self.handle.client.call(self.operation).await } @@ -182,11 +178,11 @@ fun renderCustomizableOperationSend(runtimeConfig: RuntimeConfig, generics: Flue #{handle_generics_bounds:W} { /// Sends this operation's request - pub async fn send(self) -> Result> + pub async fn send(self) -> #{Result}> where - E: std::error::Error + Send + Sync + 'static, - O: #{ParseHttpResponse}> + Send + Sync + Clone + 'static, - Retry: #{ClassifyRetry}<#{SdkSuccess}, #{SdkError}> + Send + Sync + Clone, + E: std::error::Error + #{Send} + #{Sync} + 'static, + O: #{ParseHttpResponse}> + #{Send} + #{Sync} + #{Clone} + 'static, + Retry: #{ClassifyRetry}<#{SdkSuccess}, #{SdkError}> + #{Send} + #{Sync} + #{Clone}, { self.handle.client.call(self.operation).await } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerator.kt index 551a33a14a..10a4f0c02f 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerator.kt @@ -41,6 +41,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter import software.amazon.smithy.rust.codegen.core.rustlang.withBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.customize.writeCustomizations @@ -112,12 +113,12 @@ class FluentClientGenerator( } #{client_docs:W} - ##[derive(std::fmt::Debug)] + ##[derive(::std::fmt::Debug)] pub struct Client#{generics_decl:W} { - handle: std::sync::Arc + handle: #{Arc} } - impl${generics.inst} std::clone::Clone for Client${generics.inst} { + impl${generics.inst} #{Clone} for Client${generics.inst} { fn clone(&self) -> Self { Self { handle: self.handle.clone() } } @@ -133,7 +134,7 @@ class FluentClientGenerator( /// Creates a client with the given service configuration. pub fn with_config(client: #{client}::Client#{smithy_inst:W}, conf: crate::Config) -> Self { Self { - handle: std::sync::Arc::new(Handle { + handle: #{Arc}::new(Handle { client, conf, }) @@ -146,6 +147,8 @@ class FluentClientGenerator( } } """, + *preludeScope, + "Arc" to RuntimeType.Arc, "generics_decl" to generics.decl, "smithy_inst" to generics.smithyInst, "client" to RuntimeType.smithyClient(runtimeConfig), @@ -249,14 +252,15 @@ class FluentClientGenerator( ) { rustTemplate( """ - handle: std::sync::Arc, + handle: #{Arc}, inner: #{Inner}, """, "Inner" to symbolProvider.symbolForBuilder(input), + "Arc" to RuntimeType.Arc, "generics" to generics.decl, ) if (smithyRuntimeMode.generateOrchestrator) { - rust("config_override: std::option::Option,") + rustTemplate("config_override: #{Option},", *preludeScope) } } @@ -270,21 +274,23 @@ class FluentClientGenerator( rust("/// Creates a new `${operationSymbol.name}`.") withBlockTemplate( - "pub(crate) fn new(handle: std::sync::Arc) -> Self {", + "pub(crate) fn new(handle: #{Arc}) -> Self {", "}", + "Arc" to RuntimeType.Arc, "generics" to generics.decl, ) { withBlockTemplate( "Self {", "}", ) { - rust("handle, inner: Default::default(),") + rustTemplate("handle, inner: #{Default}::default(),", *preludeScope) if (smithyRuntimeMode.generateOrchestrator) { - rust("config_override: None,") + rustTemplate("config_override: #{None},", *preludeScope) } } } val middlewareScope = arrayOf( + *preludeScope, "CustomizableOperation" to ClientRustModule.Client.customize.toType() .resolve("CustomizableOperation"), "ClassifyRetry" to RuntimeType.classifyRetry(runtimeConfig), @@ -303,7 +309,7 @@ class FluentClientGenerator( """ /// Consume this builder, creating a customizable operation that can be modified before being /// sent. The operation's inner [http::Request] can be modified as well. - pub async fn customize(self) -> std::result::Result< + pub async fn customize(self) -> #{Result}< #{CustomizableOperation}#{customizable_op_type_params:W}, #{SdkError}<#{OperationError}> > #{send_bounds:W} { @@ -312,12 +318,12 @@ class FluentClientGenerator( .make_operation(&handle.conf) .await .map_err(#{SdkError}::construction_failure)?; - Ok(#{CustomizableOperation} { handle, operation }) + #{Ok}(#{CustomizableOperation} { handle, operation }) } // This function will go away in the near future. Do not rely on it. ##[doc(hidden)] - pub async fn send_middleware(self) -> std::result::Result<#{OperationOutput}, #{SdkError}<#{OperationError}>> + pub async fn send_middleware(self) -> #{Result}<#{OperationOutput}, #{SdkError}<#{OperationError}>> #{send_bounds:W} { let op = self.inner.build().map_err(#{SdkError}::construction_failure)? .make_operation(&self.handle.conf) @@ -339,7 +345,7 @@ class FluentClientGenerator( /// By default, any retryable failures will be retried twice. Retry behavior /// is configurable with the [RetryConfig](aws_smithy_types::retry::RetryConfig), which can be /// set when configuring the client. - pub async fn send(self) -> std::result::Result<#{OperationOutput}, #{SdkError}<#{OperationError}>> + pub async fn send(self) -> #{Result}<#{OperationOutput}, #{SdkError}<#{OperationError}>> #{send_bounds:W} { self.send_middleware().await } @@ -350,6 +356,7 @@ class FluentClientGenerator( if (smithyRuntimeMode.generateOrchestrator) { val orchestratorScope = arrayOf( + *preludeScope, "HttpResponse" to RuntimeType.smithyRuntimeApi(runtimeConfig) .resolve("client::orchestrator::HttpResponse"), "OperationError" to errorType, @@ -365,14 +372,14 @@ class FluentClientGenerator( rustTemplate( """ ##[doc(hidden)] - pub async fn send_orchestrator(self) -> std::result::Result<#{OperationOutput}, #{SdkError}<#{OperationError}, #{HttpResponse}>> { - self.send_orchestrator_with_plugin(Option::>::None).await + pub async fn send_orchestrator(self) -> #{Result}<#{OperationOutput}, #{SdkError}<#{OperationError}, #{HttpResponse}>> { + self.send_orchestrator_with_plugin(#{Option}::>::None).await } ##[doc(hidden)] // TODO(enableNewSmithyRuntime): Delete when unused /// Equivalent to [`Self::send_orchestrator`] but adds a final runtime plugin to shim missing behavior - pub async fn send_orchestrator_with_plugin(self, final_plugin: Option) -> std::result::Result<#{OperationOutput}, #{SdkError}<#{OperationError}, #{HttpResponse}>> { + pub async fn send_orchestrator_with_plugin(self, final_plugin: #{Option}) -> #{Result}<#{OperationOutput}, #{SdkError}<#{OperationError}, #{HttpResponse}>> { let mut runtime_plugins = #{RuntimePlugins}::new() .with_client_plugin(crate::config::ServiceRuntimePlugin::new(self.handle.clone())); if let Some(config_override) = self.config_override { @@ -393,7 +400,7 @@ class FluentClientGenerator( .unwrap() }) })?; - Ok(#{TypedBox}::<#{OperationOutput}>::assume_from(output).expect("correct output type").unwrap()) + #{Ok}(#{TypedBox}::<#{OperationOutput}>::assume_from(output).expect("correct output type").unwrap()) } """, *orchestratorScope, @@ -409,7 +416,7 @@ class FluentClientGenerator( /// By default, any retryable failures will be retried twice. Retry behavior /// is configurable with the [RetryConfig](aws_smithy_types::retry::RetryConfig), which can be /// set when configuring the client. - pub async fn send(self) -> std::result::Result<#{OperationOutput}, #{SdkError}<#{OperationError}, #{HttpResponse}>> { + pub async fn send(self) -> #{Result}<#{OperationOutput}, #{SdkError}<#{OperationError}, #{HttpResponse}>> { self.send_orchestrator().await } """, diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/OperationErrorGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/OperationErrorGenerator.kt index 26d926a78d..8e17d5bd9d 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/OperationErrorGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/OperationErrorGenerator.kt @@ -22,10 +22,12 @@ import software.amazon.smithy.rust.codegen.core.rustlang.docs import software.amazon.smithy.rust.codegen.core.rustlang.documentShape import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock +import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.errorMetadata +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.unhandledError import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.customize.Section @@ -107,14 +109,16 @@ class OperationErrorGenerator( ) } writer.rustBlock("impl #T for ${errorSymbol.name}", createUnhandledError) { - rustBlock( + rustBlockTemplate( """ fn create_unhandled_error( - source: Box, - meta: std::option::Option<#T> + source: #{Box}, + meta: #{Option}<#{ErrorMeta}> ) -> Self """, - errorMetadata, + *preludeScope, + "StdError" to RuntimeType.StdError, + "ErrorMeta" to errorMetadata, ) { rust( """ @@ -129,7 +133,7 @@ class OperationErrorGenerator( } } writer.rustBlock("impl #T for ${errorSymbol.name}", RuntimeType.Display) { - rustBlock("fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result") { + rustBlock("fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result") { delegateToVariants(errors) { writable { rust("_inner.fmt(f)") } } @@ -152,21 +156,28 @@ class OperationErrorGenerator( "impl #T for ${errorSymbol.name}", RuntimeType.provideErrorKind(symbolProvider.config.runtimeConfig), ) { - rustBlock("fn code(&self) -> std::option::Option<&str>") { + rustBlockTemplate("fn code(&self) -> #{Option}<&str>", *preludeScope) { rust("#T::code(self)", RuntimeType.provideErrorMetadataTrait(runtimeConfig)) } - rustBlock("fn retryable_error_kind(&self) -> std::option::Option<#T>", retryErrorKindT) { + rustBlockTemplate( + "fn retryable_error_kind(&self) -> #{Option}<#{ErrorKind}>", + "ErrorKind" to retryErrorKindT, + *preludeScope, + ) { val retryableVariants = errors.filter { it.hasTrait() } if (retryableVariants.isEmpty()) { - rust("None") + rustTemplate("#{None}", *preludeScope) } else { rustBlock("match self") { retryableVariants.forEach { val errorVariantSymbol = symbolProvider.toSymbol(it) - rust("Self::${errorVariantSymbol.name}(inner) => Some(inner.retryable_error_kind()),") + rustTemplate( + "Self::${errorVariantSymbol.name}(inner) => #{Some}(inner.retryable_error_kind()),", + *preludeScope, + ) } - rust("_ => None") + rustTemplate("_ => #{None}", *preludeScope) } } } @@ -176,7 +187,7 @@ class OperationErrorGenerator( writer.rustTemplate( """ /// Creates the `${errorSymbol.name}::Unhandled` variant from any error type. - pub fn unhandled(err: impl Into>) -> Self { + pub fn unhandled(err: impl #{Into}<#{Box}>) -> Self { Self::Unhandled(#{Unhandled}::builder().source(err).build()) } @@ -185,8 +196,9 @@ class OperationErrorGenerator( Self::Unhandled(#{Unhandled}::builder().source(err.clone()).meta(err).build()) } """, + *preludeScope, "error_metadata" to errorMetadata, - "std_error" to RuntimeType.StdError, + "StdError" to RuntimeType.StdError, "Unhandled" to unhandledError(runtimeConfig), ) writer.docs( @@ -216,10 +228,14 @@ class OperationErrorGenerator( } writer.rustBlock("impl #T for ${errorSymbol.name}", RuntimeType.StdError) { - rustBlock("fn source(&self) -> std::option::Option<&(dyn #T + 'static)>", RuntimeType.StdError) { + rustBlockTemplate( + "fn source(&self) -> #{Option}<&(dyn #{StdError} + 'static)>", + *preludeScope, + "StdError" to RuntimeType.StdError, + ) { delegateToVariants(errors) { writable { - rust("Some(_inner)") + rustTemplate("#{Some}(_inner)", *preludeScope) } } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/RequestBindingGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/RequestBindingGenerator.kt index 148a09d4bd..0a4e5fb09b 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/RequestBindingGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/RequestBindingGenerator.kt @@ -23,6 +23,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.generators.OperationBuildError import software.amazon.smithy.rust.codegen.core.smithy.generators.http.HttpBindingGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.operationBuildError @@ -71,6 +72,7 @@ class RequestBindingGenerator( private val encoder = RuntimeType.smithyTypes(runtimeConfig).resolve("primitive::Encoder") private val codegenScope = arrayOf( + *preludeScope, "BuildError" to runtimeConfig.operationBuildError(), "HttpRequestBuilder" to RuntimeType.HttpRequestBuilder, "Input" to symbolProvider.toSymbol(inputShape), @@ -90,11 +92,11 @@ class RequestBindingGenerator( fn update_http_builder( input: &#{Input}, builder: #{HttpRequestBuilder} - ) -> std::result::Result<#{HttpRequestBuilder}, #{BuildError}> + ) -> #{Result}<#{HttpRequestBuilder}, #{BuildError}> """, *codegenScope, ) { - write("let mut uri = String::new();") + rustTemplate("let mut uri = #{String}::new();", *preludeScope) write("uri_base(input, &mut uri)?;") if (hasQuery) { write("uri_query(input, &mut uri)?;") @@ -107,7 +109,7 @@ class RequestBindingGenerator( addHeadersFn, ) } - write("Ok(builder.method(${httpTrait.method.dq()}).uri(uri))") + rustTemplate("#{Ok}(builder.method(${httpTrait.method.dq()}).uri(uri))", *preludeScope) } } @@ -126,7 +128,7 @@ class RequestBindingGenerator( } val combinedArgs = listOf(formatString, *args.toTypedArray()) writer.rustBlockTemplate( - "fn uri_base(_input: &#{Input}, output: &mut String) -> std::result::Result<(), #{BuildError}>", + "fn uri_base(_input: &#{Input}, output: &mut #{String}) -> #{Result}<(), #{BuildError}>", *codegenScope, ) { rust("use #T as _;", RuntimeType.stdFmt.resolve("Write")) @@ -134,8 +136,8 @@ class RequestBindingGenerator( val member = inputShape.expectMember(label.content) serializeLabel(member, label, local(member)) } - rust("""write!(output, ${combinedArgs.joinToString(", ")}).expect("formatting should succeed");""") - rust("Ok(())") + rust("""::std::write!(output, ${combinedArgs.joinToString(", ")}).expect("formatting should succeed");""") + rustTemplate("#{Ok}(())", *codegenScope) } } @@ -165,7 +167,7 @@ class RequestBindingGenerator( } val preloadedParams = literalParams.keys + dynamicParams.map { it.locationName } writer.rustBlockTemplate( - "fn uri_query(_input: &#{Input}, mut output: &mut String) -> Result<(), #{BuildError}>", + "fn uri_query(_input: &#{Input}, mut output: &mut #{String}) -> #{Result}<(), #{BuildError}>", *codegenScope, ) { write("let mut query = #T::new(output);", RuntimeType.queryFormat(runtimeConfig, "Writer")) @@ -212,6 +214,7 @@ class RequestBindingGenerator( if (memberShape.isRequired) { val codegenScope = arrayOf( + *preludeScope, "BuildError" to OperationBuildError(runtimeConfig).missingField( memberName, "cannot be empty or unset", @@ -229,7 +232,7 @@ class RequestBindingGenerator( // Strings that aren't enums must be checked to see if they're empty if (target.isStringShape && !target.hasTrait()) { rustBlock("if $derefName.is_empty()") { - rustTemplate("return Err(#{BuildError:W});", *codegenScope) + rustTemplate("return #{Err}(#{BuildError:W});", *codegenScope) } } @@ -241,7 +244,7 @@ class RequestBindingGenerator( } } } - writer.rust("Ok(())") + writer.rustTemplate("#{Ok}(())", *codegenScope) } return true } @@ -329,9 +332,10 @@ class RequestBindingGenerator( rustTemplate( """ if $outputVar.is_empty() { - return Err(#{buildError:W}) + return #{Err}(#{buildError:W}) } """, + *preludeScope, "buildError" to buildError, ) } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/MakeOperationGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/MakeOperationGenerator.kt index 5d206d47e8..8f2dcda292 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/MakeOperationGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/MakeOperationGenerator.kt @@ -20,6 +20,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.rustlang.withBlockTemplate import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.customize.OperationCustomization import software.amazon.smithy.rust.codegen.core.smithy.customize.OperationSection import software.amazon.smithy.rust.codegen.core.smithy.customize.writeCustomizations @@ -56,13 +57,15 @@ open class MakeOperationGenerator( ?: codegenContext.serviceShape.id.getName(codegenContext.serviceShape) private val codegenScope = arrayOf( + *preludeScope, "config" to ClientRustModule.Config, "header_util" to RuntimeType.smithyHttp(runtimeConfig).resolve("header"), "http" to RuntimeType.Http, + "operation" to RuntimeType.operationModule(runtimeConfig), "HttpRequestBuilder" to RuntimeType.HttpRequestBuilder, "OpBuildError" to runtimeConfig.operationBuildError(), - "operation" to RuntimeType.operationModule(runtimeConfig), "SdkBody" to RuntimeType.sdkBody(runtimeConfig), + "SharedPropertyBag" to RuntimeType.smithyHttp(runtimeConfig).resolve("property_bag::SharedPropertyBag"), ) fun generateMakeOperation( @@ -73,7 +76,7 @@ open class MakeOperationGenerator( val operationName = symbolProvider.toSymbol(shape).name val baseReturnType = buildOperationType(implBlockWriter, shape, customizations) val returnType = - "std::result::Result<$baseReturnType, ${implBlockWriter.format(runtimeConfig.operationBuildError())}>" + "#{Result}<$baseReturnType, ${implBlockWriter.format(runtimeConfig.operationBuildError())}>" val outputSymbol = symbolProvider.toSymbol(shape) val takesOwnership = bodyGenerator.payloadMetadata(shape).takesOwnership @@ -99,7 +102,7 @@ open class MakeOperationGenerator( withBlock("let mut request = {", "};") { createHttpRequest(this, shape) } - rust("let mut properties = aws_smithy_http::property_bag::SharedPropertyBag::new();") + rustTemplate("let mut properties = #{SharedPropertyBag}::new();", *codegenScope) // When the payload is a `ByteStream`, `into_inner()` already returns an `SdkBody`, so we mute this // Clippy warning to make the codegen a little simpler in that case. @@ -116,7 +119,7 @@ open class MakeOperationGenerator( if (includeDefaultPayloadHeaders && needsContentLength(shape)) { rustTemplate( """ - if let Some(content_length) = body.content_length() { + if let #{Some}(content_length) = body.content_length() { request = #{header_util}::set_request_header_if_absent(request, #{http}::header::CONTENT_LENGTH, content_length); } """, @@ -140,7 +143,7 @@ open class MakeOperationGenerator( "OperationType" to symbolProvider.toSymbol(shape), ) writeCustomizations(customizations, OperationSection.FinalizeOperation(customizations, "op", "_config")) - rust("Ok(op)") + rustTemplate("#{Ok}(op)", *codegenScope) } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGenerator.kt index 5a1c4993b0..cafefc1179 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGenerator.kt @@ -351,7 +351,7 @@ class ProtocolTestGenerator( rustWriter.rustTemplate( """ // No body - #{AssertEq}(std::str::from_utf8(body).unwrap(), ""); + #{AssertEq}(::std::str::from_utf8(body).unwrap(), ""); """, *codegenScope, ) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/HttpBoundProtocolGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/HttpBoundProtocolGenerator.kt index 83578b2ac5..ae83e78cfe 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/HttpBoundProtocolGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/HttpBoundProtocolGenerator.kt @@ -19,6 +19,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.customize.OperationCustomization import software.amazon.smithy.rust.codegen.core.smithy.customize.OperationSection import software.amazon.smithy.rust.codegen.core.smithy.customize.writeCustomizations @@ -61,6 +62,7 @@ open class HttpBoundProtocolTraitImplGenerator( private val parserGenerator = ProtocolParserGenerator(codegenContext, protocol) private val codegenScope = arrayOf( + *preludeScope, "ParseStrict" to RuntimeType.parseStrictResponse(runtimeConfig), "ParseResponse" to RuntimeType.parseHttpResponse(runtimeConfig), "http" to RuntimeType.Http, @@ -114,7 +116,7 @@ open class HttpBoundProtocolTraitImplGenerator( rustTemplate( """ impl #{ParseStrict} for $operationName { - type Output = std::result::Result<#{O}, #{E}>; + type Output = #{Result}<#{O}, #{E}>; fn parse(&self, response: &#{http}::Response<#{Bytes}>) -> Self::Output { let (success, status) = (response.status().is_success(), response.status().as_u16()); let headers = response.headers(); @@ -144,14 +146,14 @@ open class HttpBoundProtocolTraitImplGenerator( rustTemplate( """ impl #{ParseResponse} for $operationName { - type Output = std::result::Result<#{O}, #{E}>; - fn parse_unloaded(&self, response: &mut #{operation}::Response) -> Option { + type Output = #{Result}<#{O}, #{E}>; + fn parse_unloaded(&self, response: &mut #{operation}::Response) -> #{Option} { #{BeforeParseResponse} // This is an error, defer to the non-streaming parser if !response.http().status().is_success() && response.http().status().as_u16() != $successCode { - return None; + return #{None}; } - Some(#{parse_streaming_response}(response)) + #{Some}(#{parse_streaming_response}(response)) } fn parse_loaded(&self, response: &#{http}::Response<#{Bytes}>) -> Self::Output { // if streaming, we only hit this case if its an error @@ -180,7 +182,7 @@ open class HttpBoundProtocolTraitImplGenerator( return protocolFunctions.deserializeFn(operationShape, fnNameSuffix = "op_response") { fnName -> Attribute.AllowClippyUnnecessaryWraps.render(this) rustBlockTemplate( - "pub fn $fnName(op_response: &mut #{operation}::Response) -> std::result::Result<#{O}, #{E}>", + "pub fn $fnName(op_response: &mut #{operation}::Response) -> #{Result}<#{O}, #{E}>", *codegenScope, "O" to outputSymbol, "E" to errorSymbol, diff --git a/codegen-core/common-test-models/naming-obstacle-course-prelude-ops.smithy b/codegen-core/common-test-models/naming-obstacle-course-prelude-ops.smithy new file mode 100644 index 0000000000..36b7ee61d3 --- /dev/null +++ b/codegen-core/common-test-models/naming-obstacle-course-prelude-ops.smithy @@ -0,0 +1,92 @@ +$version: "1.0" +namespace crate + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests +use aws.protocols#awsJson1_1 +use aws.api#service +use smithy.framework#ValidationException + +/// Confounds model generation machinery by using operations named after every item in the Rust prelude +@awsJson1_1 +@service(sdkId: "Config") +service Config { + version: "2006-03-01", + operations: [ + // Rust Prelude + Copy, + Send, + Sized, + Sync, + Unpin, + Drop, + Fn, + FnMut, + FnOnce, + Box, + ToOwned, + Clone, + PartialEq, + PartialOrd, + Eq, + Ord, + AsRef, + AsMut, + Into, + From, + Default, + Iterator, + Extend, + IntoIterator, + DoubleEndedIterator, + ExactSizeIterator, + Option, + Some, + None, + Result, + Ok, + Err, + String, + ToString, + Vec, + ] +} + +structure Input {} +structure Output {} + +operation Copy { input: Input, output: Output } +operation Send { input: Input, output: Output } +operation Sized { input: Input, output: Output } +operation Sync { input: Input, output: Output } +operation Unpin { input: Input, output: Output } +operation Drop { input: Input, output: Output } +operation Fn { input: Input, output: Output } +operation FnMut { input: Input, output: Output } +operation FnOnce { input: Input, output: Output } +operation Box { input: Input, output: Output } +operation ToOwned { input: Input, output: Output } +operation Clone { input: Input, output: Output } +operation PartialEq { input: Input, output: Output } +operation PartialOrd { input: Input, output: Output } +operation Eq { input: Input, output: Output } +operation Ord { input: Input, output: Output } +operation AsRef { input: Input, output: Output } +operation AsMut { input: Input, output: Output } +operation Into { input: Input, output: Output } +operation From { input: Input, output: Output } +operation Default { input: Input, output: Output } +operation Iterator { input: Input, output: Output } +operation Extend { input: Input, output: Output } +operation IntoIterator { input: Input, output: Output } +operation DoubleEndedIterator { input: Input, output: Output } +operation ExactSizeIterator { input: Input, output: Output } +operation Option { input: Input, output: Output } +operation Some { input: Input, output: Output } +operation None { input: Input, output: Output } +operation Result { input: Input, output: Output } +operation Ok { input: Input, output: Output } +operation Err { input: Input, output: Output } +operation String { input: Input, output: Output } +operation ToString { input: Input, output: Output } +operation Vec { input: Input, output: Output } diff --git a/codegen-core/common-test-models/naming-obstacle-course-prelude-structs.smithy b/codegen-core/common-test-models/naming-obstacle-course-prelude-structs.smithy new file mode 100644 index 0000000000..0047c182c3 --- /dev/null +++ b/codegen-core/common-test-models/naming-obstacle-course-prelude-structs.smithy @@ -0,0 +1,125 @@ +$version: "1.0" +namespace crate + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests +use aws.protocols#awsJson1_1 +use aws.api#service +use smithy.framework#ValidationException + +/// Confounds model generation machinery by using structs named after every item in the Rust prelude +@awsJson1_1 +@service(sdkId: "Config") +service Config { + version: "2006-03-01", + operations: [ + UseCopy, + UseSend, + UseSized, + UseSync, + UseUnpin, + UseDrop, + UseFn, + UseFnMut, + UseFnOnce, + UseBox, + UseToOwned, + UseClone, + UsePartialEq, + UsePartialOrd, + UseEq, + UseOrd, + UseAsRef, + UseAsMut, + UseInto, + UseFrom, + UseDefault, + UseIterator, + UseExtend, + UseIntoIterator, + UseDoubleEndedIterator, + UseExactSizeIterator, + UseOption, + UseSome, + UseNone, + UseResult, + UseOk, + UseErr, + UseString, + UseToString, + UseVec, + ] +} + +// Rust Prelude +structure Copy {} +structure Send {} +structure Sized {} +structure Sync {} +structure Unpin {} +structure Drop {} +structure Fn {} +structure FnMut {} +structure FnOnce {} +structure Box {} +structure ToOwned {} +structure Clone {} +structure PartialEq {} +structure PartialOrd {} +structure Eq {} +structure Ord {} +structure AsRef {} +structure AsMut {} +structure Into {} +structure From {} +structure Default {} +structure Iterator {} +structure Extend {} +structure IntoIterator {} +structure DoubleEndedIterator {} +structure ExactSizeIterator {} +structure Option {} +structure Some {} +structure None {} +structure Result {} +structure Ok {} +structure Err {} +structure String {} +structure ToString {} +structure Vec {} + +operation UseCopy { input: Copy, output: Copy } +operation UseSend { input: Send, output: Send } +operation UseSized { input: Sized, output: Sized } +operation UseSync { input: Sync, output: Sync } +operation UseUnpin { input: Unpin, output: Unpin } +operation UseDrop { input: Drop, output: Drop } +operation UseFn { input: Fn, output: Fn } +operation UseFnMut { input: FnMut, output: FnMut } +operation UseFnOnce { input: FnOnce, output: FnOnce } +operation UseBox { input: Box, output: Box } +operation UseToOwned { input: ToOwned, output: ToOwned } +operation UseClone { input: Clone, output: Clone } +operation UsePartialEq { input: PartialEq, output: PartialEq } +operation UsePartialOrd { input: PartialOrd, output: PartialOrd } +operation UseEq { input: Eq, output: Eq } +operation UseOrd { input: Ord, output: Ord } +operation UseAsRef { input: AsRef, output: AsRef } +operation UseAsMut { input: AsMut, output: AsMut } +operation UseInto { input: Into, output: Into } +operation UseFrom { input: From, output: From } +operation UseDefault { input: Default, output: Default } +operation UseIterator { input: Iterator, output: Iterator } +operation UseExtend { input: Extend, output: Extend } +operation UseIntoIterator { input: IntoIterator, output: IntoIterator } +operation UseDoubleEndedIterator { input: DoubleEndedIterator, output: DoubleEndedIterator } +operation UseExactSizeIterator { input: ExactSizeIterator, output: ExactSizeIterator } +operation UseOption { input: Option, output: Option } +operation UseSome { input: Some, output: Some } +operation UseNone { input: None, output: None } +operation UseResult { input: Result, output: Result } +operation UseOk { input: Ok, output: Ok } +operation UseErr { input: Err, output: Err } +operation UseString { input: String, output: String } +operation UseToString { input: ToString, output: ToString } +operation UseVec { input: Vec, output: Vec } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/CargoDependency.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/CargoDependency.kt index 2e372b4989..6976236d85 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/CargoDependency.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/CargoDependency.kt @@ -197,7 +197,7 @@ data class CargoDependency( } fun toType(): RuntimeType { - return RuntimeType(rustName, this) + return RuntimeType("::$rustName", this) } companion object { diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustModule.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustModule.kt index b8c3237e41..78dee92dae 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustModule.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustModule.kt @@ -79,14 +79,19 @@ sealed class RustModule { } /** Creates a new public module */ - fun public(name: String, parent: RustModule = LibRs, documentationOverride: String? = null): LeafModule = - new( - name, - visibility = Visibility.PUBLIC, - inline = false, - parent = parent, - documentationOverride = documentationOverride, - ) + fun public( + name: String, + parent: RustModule = LibRs, + documentationOverride: String? = null, + additionalAttributes: List = emptyList(), + ): LeafModule = new( + name, + visibility = Visibility.PUBLIC, + inline = false, + parent = parent, + documentationOverride = documentationOverride, + additionalAttributes = additionalAttributes, + ) /** Creates a new private module */ fun private(name: String, parent: RustModule = LibRs): LeafModule = diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustType.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustType.kt index 79dde7de12..6d010089d2 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustType.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustType.kt @@ -199,7 +199,7 @@ fun RustType.qualifiedName(): String { /** Format this Rust type as an `impl Into` */ fun RustType.implInto(fullyQualified: Boolean = true): String { - return "impl Into<${this.render(fullyQualified)}>" + return "impl ${RuntimeType.Into.fullyQualifiedName()}<${this.render(fullyQualified)}>" } /** Format this Rust type so that it may be used as an argument type in a function definition */ @@ -498,6 +498,7 @@ class Attribute(val inner: Writable, val isDeriveHelper: Boolean = false) { val DenyMissingDocs = Attribute(deny("missing_docs")) val DocHidden = Attribute(doc("hidden")) val DocInline = Attribute(doc("inline")) + val NoImplicitPrelude = Attribute("no_implicit_prelude") fun shouldPanic(expectedMessage: String) = Attribute(macroWithArgs("should_panic", "expected = ${expectedMessage.dq()}")) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriter.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriter.kt index 61f219488a..5781a3404e 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriter.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriter.kt @@ -26,6 +26,7 @@ import software.amazon.smithy.model.traits.DocumentationTrait import software.amazon.smithy.rust.codegen.core.rustlang.Attribute.Companion.deprecated import software.amazon.smithy.rust.codegen.core.smithy.ModuleDocProvider import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.protocols.serialize.ValueExpression import software.amazon.smithy.rust.codegen.core.smithy.rustType @@ -142,6 +143,27 @@ fun > T.conditionalBlock( return this } +fun RustWriter.conditionalBlockTemplate( + textBeforeNewLine: String, + textAfterNewLine: String, + conditional: Boolean = true, + vararg args: Pair, + block: RustWriter.() -> Unit, +): RustWriter { + if (conditional) { + withTemplate(textBeforeNewLine.trim(), args) { text -> + openBlock(text) + } + } + block(this) + if (conditional) { + withTemplate(textAfterNewLine.trim(), args) { text -> + closeBlock(text) + } + } + return this +} + /** * Convenience wrapper that tells Intellij that the contents of this block are Rust */ @@ -608,7 +630,7 @@ class RustWriter private constructor( when { member.isOptional() -> { val innerValue = ValueExpression.Reference(safeName("inner")) - rustBlock("if let Some(${innerValue.name}) = ${value.asRef()}") { + rustBlockTemplate("if let #{Some}(${innerValue.name}) = ${value.asRef()}", *preludeScope) { block(innerValue) } } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt index f8c656c08e..6616fdd96f 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt @@ -193,14 +193,57 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null) * The companion object contains commonly used RuntimeTypes */ companion object { + /** Scope that contains all Rust prelude types, but not macros or functions */ + val preludeScope by lazy { + arrayOf( + "Copy" to std.resolve("marker::Copy"), + "Send" to Send, + "Sized" to std.resolve("marker::Sized"), + "Sync" to Sync, + "Unpin" to std.resolve("marker::Unpin"), + "Drop" to std.resolve("ops::Drop"), + "Fn" to std.resolve("ops::Fn"), + "FnMut" to std.resolve("ops::FnMut"), + "FnOnce" to std.resolve("ops::FnOnce"), + "Box" to Box, + "ToOwned" to std.resolve("borrow::ToOwned"), + "Clone" to Clone, + "PartialEq" to std.resolve("cmp::PartialEq"), + "PartialOrd" to std.resolve("cmp::PartialOrd"), + "Eq" to Eq, + "Ord" to Ord, + "AsRef" to AsRef, + "AsMut" to std.resolve("convert::AsMut"), + "Into" to Into, + "From" to From, + "Default" to Default, + "Iterator" to std.resolve("iter::Iterator"), + "Extend" to std.resolve("iter::Extend"), + "IntoIterator" to std.resolve("iter::IntoIterator"), + "DoubleEndedIterator" to std.resolve("iter::DoubleEndedIterator"), + "ExactSizeIterator" to std.resolve("iter::ExactSizeIterator"), + "Option" to Option, + "Some" to Option.resolve("Some"), + "None" to Option.resolve("None"), + "Result" to std.resolve("result::Result"), + "Ok" to std.resolve("result::Result::Ok"), + "Err" to std.resolve("result::Result::Err"), + "String" to String, + "ToString" to std.resolve("string::ToString"), + "Vec" to Vec, + ) + } + // stdlib types - val std = RuntimeType("std") + val std = RuntimeType("::std") val stdCmp = std.resolve("cmp") val stdFmt = std.resolve("fmt") val stdConvert = std.resolve("convert") + val Arc = std.resolve("sync::Arc") val AsRef = stdConvert.resolve("AsRef") - val ByteSlab = std.resolve("vec::Vec") + val Bool = std.resolve("primitive::bool") val Box = std.resolve("boxed::Box") + val ByteSlab = std.resolve("vec::Vec") val Clone = std.resolve("clone::Clone") val Cow = std.resolve("borrow::Cow") val Debug = stdFmt.resolve("Debug") @@ -210,19 +253,18 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null) val From = stdConvert.resolve("From") val Hash = std.resolve("hash::Hash") val HashMap = std.resolve("collections::HashMap") - val Ord = stdCmp.resolve("Ord") + val Into = stdConvert.resolve("Into") val Option = std.resolve("option::Option") + val Ord = stdCmp.resolve("Ord") val PartialEq = stdCmp.resolve("PartialEq") val PartialOrd = stdCmp.resolve("PartialOrd") val Phantom = std.resolve("marker::PhantomData") + val Send = std.resolve("marker::Send") val StdError = std.resolve("error::Error") val String = std.resolve("string::String") - val Bool = std.resolve("primitive::bool") + val Sync = std.resolve("marker::Sync") val TryFrom = stdConvert.resolve("TryFrom") val Vec = std.resolve("vec::Vec") - val Arc = std.resolve("sync::Arc") - val Send = std.resolve("marker::Send") - val Sync = std.resolve("marker::Sync") // external cargo dependency types val Bytes = CargoDependency.Bytes.toType().resolve("Bytes") diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGenerator.kt index 16cb28b803..da008a6bee 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGenerator.kt @@ -17,13 +17,14 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.rustlang.asArgument import software.amazon.smithy.rust.codegen.core.rustlang.asOptional -import software.amazon.smithy.rust.codegen.core.rustlang.conditionalBlock +import software.amazon.smithy.rust.codegen.core.rustlang.conditionalBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.deprecatedShape import software.amazon.smithy.rust.codegen.core.rustlang.docs import software.amazon.smithy.rust.codegen.core.rustlang.documentShape import software.amazon.smithy.rust.codegen.core.rustlang.render import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock +import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter import software.amazon.smithy.rust.codegen.core.rustlang.withBlock @@ -31,6 +32,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.Default import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.canUseDefault import software.amazon.smithy.rust.codegen.core.smithy.customize.NamedCustomization @@ -126,7 +128,6 @@ class BuilderGenerator( private val runtimeConfig = symbolProvider.config.runtimeConfig private val members: List = shape.allMembers.values.toList() private val structureSymbol = symbolProvider.toSymbol(shape) - private val builderSymbol = symbolProvider.symbolForBuilder(shape) private val metadata = structureSymbol.expectRustMetadata() // Filter out any derive that isn't Debug, PartialEq, or Clone. Then add a Default derive @@ -147,12 +148,12 @@ class BuilderGenerator( val fallibleBuilder = hasFallibleBuilder(shape, symbolProvider) val outputSymbol = symbolProvider.toSymbol(shape) val returnType = when (fallibleBuilder) { - true -> "Result<${implBlockWriter.format(outputSymbol)}, ${implBlockWriter.format(runtimeConfig.operationBuildError())}>" + true -> "#{Result}<${implBlockWriter.format(outputSymbol)}, ${implBlockWriter.format(runtimeConfig.operationBuildError())}>" false -> implBlockWriter.format(outputSymbol) } implBlockWriter.docs("Consumes the builder and constructs a #D.", outputSymbol) - implBlockWriter.rustBlock("pub fn build(self) -> $returnType") { - conditionalBlock("Ok(", ")", conditional = fallibleBuilder) { + implBlockWriter.rustBlockTemplate("pub fn build(self) -> $returnType", *preludeScope) { + conditionalBlockTemplate("#{Ok}(", ")", conditional = fallibleBuilder, *preludeScope) { // If a wrapper is specified, use the `::new` associated function to construct the wrapper coreBuilder(this) } @@ -182,7 +183,7 @@ class BuilderGenerator( writer.documentShape(member, model) writer.deprecatedShape(member) writer.rustBlock("pub fn $memberName(mut self, ${input.argument}) -> Self") { - write("self.$memberName = Some(${input.value});") + rustTemplate("self.$memberName = #{Some}(${input.value});", *preludeScope) write("self") } } @@ -273,13 +274,14 @@ class BuilderGenerator( val input = coreType.member.asArgument("input") rustBlock("pub fn $memberName(mut self, ${input.argument}) -> Self") { - rust( + rustTemplate( """ let mut v = self.$memberName.unwrap_or_default(); v.push(${input.value}); - self.$memberName = Some(v); + self.$memberName = #{Some}(v); self """, + *preludeScope, ) } } @@ -297,13 +299,14 @@ class BuilderGenerator( rustBlock( "pub fn $memberName(mut self, ${k.argument}, ${v.argument}) -> Self", ) { - rust( + rustTemplate( """ let mut hash_map = self.$memberName.unwrap_or_default(); hash_map.insert(${k.value}, ${v.value}); - self.$memberName = Some(hash_map); + self.$memberName = #{Some}(hash_map); self """, + *preludeScope, ) } } 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 379a6982da..d5565880f1 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 @@ -295,7 +295,7 @@ open class EnumGenerator( """ impl #{Debug} for ${context.enumName} { fn fmt(&self, f: &mut #{StdFmt}::Formatter<'_>) -> #{StdFmt}::Result { - write!(f, $REDACTION) + ::std::write!(f, $REDACTION) } } """, diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/Instantiator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/Instantiator.kt index e77f942a29..089143feea 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/Instantiator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/Instantiator.kt @@ -37,7 +37,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency import software.amazon.smithy.rust.codegen.core.rustlang.RustType import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.Writable -import software.amazon.smithy.rust.codegen.core.rustlang.conditionalBlock +import software.amazon.smithy.rust.codegen.core.rustlang.conditionalBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.escape import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock @@ -47,6 +47,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.customize.NamedCustomization import software.amazon.smithy.rust.codegen.core.smithy.customize.Section @@ -208,17 +209,19 @@ open class Instantiator( } else { // Structure builder setters for structure shape members _always_ take in `Option`. // Other aggregate shapes' members are optional only when their symbol is. - writer.conditionalBlock( - "Some(", + writer.conditionalBlockTemplate( + "#{Some}(", ")", // The conditions are not commutative: note client builders always take in `Option`. conditional = symbol.isOptional() || (model.expectShape(memberShape.container) is StructureShape && builderKindBehavior.doesSetterTakeInOption(memberShape)), + *preludeScope, ) { - writer.conditionalBlock( - "Box::new(", + writer.conditionalBlockTemplate( + "#{Box}::new(", ")", conditional = symbol.rustType().stripOuter() is RustType.Box, + *preludeScope, ) { render( this, diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/UnionGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/UnionGenerator.kt index 39b191ba96..3f7927d728 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/UnionGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/UnionGenerator.kt @@ -19,9 +19,11 @@ import software.amazon.smithy.rust.codegen.core.rustlang.documentShape import software.amazon.smithy.rust.codegen.core.rustlang.render import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock +import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata import software.amazon.smithy.rust.codegen.core.smithy.renamedFrom import software.amazon.smithy.rust.codegen.core.smithy.rustType @@ -134,7 +136,7 @@ open class UnionGenerator( """ impl #{Debug} for ${unionSymbol.name} { fn fmt(&self, f: &mut #{StdFmt}::Formatter<'_>) -> #{StdFmt}::Result { - write!(f, $REDACTION) + ::std::write!(f, $REDACTION) } } """, @@ -197,8 +199,11 @@ private fun RustWriter.renderAsVariant( "/// Tries to convert the enum instance into [`$variantName`], extracting the inner `()`.", ) rust("/// Returns `Err(&Self)` if it can't be converted.") - rustBlock("pub fn as_$funcNamePart(&self) -> std::result::Result<(), &Self>") { - rust("if let ${unionSymbol.name}::$variantName = &self { Ok(()) } else { Err(self) }") + rustBlockTemplate("pub fn as_$funcNamePart(&self) -> #{Result}<(), &Self>", *preludeScope) { + rustTemplate( + "if let ${unionSymbol.name}::$variantName = &self { #{Ok}(()) } else { #{Err}(self) }", + *preludeScope, + ) } } else { val memberSymbol = symbolProvider.toSymbol(member) @@ -209,8 +214,11 @@ private fun RustWriter.renderAsVariant( targetSymbol, ) rust("/// Returns `Err(&Self)` if it can't be converted.") - rustBlock("pub fn as_$funcNamePart(&self) -> std::result::Result<&${memberSymbol.rustType().render()}, &Self>") { - rust("if let ${unionSymbol.name}::$variantName(val) = &self { Ok(val) } else { Err(self) }") + rustBlockTemplate("pub fn as_$funcNamePart(&self) -> #{Result}<&${memberSymbol.rustType().render()}, &Self>", *preludeScope) { + rustTemplate( + "if let ${unionSymbol.name}::$variantName(val) = &self { #{Ok}(val) } else { #{Err}(self) }", + *preludeScope, + ) } } } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ErrorImplGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ErrorImplGenerator.kt index 692bf32aab..049933bc45 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ErrorImplGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ErrorImplGenerator.kt @@ -156,13 +156,13 @@ class ErrorImplGenerator( val errorDesc = symbol.name.letIf(symbol.name != shape.id.name) { symbolName -> "$symbolName [${shape.id.name}]" } - write("write!(f, ${errorDesc.dq()})?;") + write("::std::write!(f, ${errorDesc.dq()})?;") messageShape?.let { if (it.shouldRedact(model)) { - write("""write!(f, ": {}", $REDACTION)?;""") + write("""::std::write!(f, ": {}", $REDACTION)?;""") } else { ifSet(it, symbolProvider.toSymbol(it), ValueExpression.Reference("&self.message")) { field -> - write("""write!(f, ": {}", ${field.asRef()})?;""") + write("""::std::write!(f, ": {}", ${field.asRef()})?;""") } } } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/EventStreamUnmarshallerGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/EventStreamUnmarshallerGenerator.kt index 6e9826f054..6b706a1e09 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/EventStreamUnmarshallerGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/EventStreamUnmarshallerGenerator.kt @@ -276,7 +276,7 @@ class EventStreamUnmarshallerGenerator( is StringShape -> { rustTemplate( """ - std::str::from_utf8(message.payload()) + ::std::str::from_utf8(message.payload()) .map_err(|_| #{Error}::unmarshalling("message payload is not valid UTF-8"))? .to_owned() """, From a1207f9dda2cd6a1509600a9c5c98584322d5be4 Mon Sep 17 00:00:00 2001 From: John DiSanti Date: Thu, 11 May 2023 17:27:03 -0700 Subject: [PATCH 2/7] Update changelog --- CHANGELOG.next.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 93b581e99d..16c3fc9b6c 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -37,3 +37,9 @@ message = """`ShapeId` is the new structure used to represent a shape, with its author = "82marbag" references = ["smithy-rs#2678"] meta = { "breaking" = true, "tada" = false, "bug" = false } + +[[smithy-rs]] +message = "Fix compiler errors in generated code when naming shapes after types in the Rust standard library prelude." +references = ["smithy-rs#2696"] +meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "client"} +author = "jdisanti" From 8be1ff55130f49e00cc4a1c44e6e83bb2d5d57e2 Mon Sep 17 00:00:00 2001 From: John DiSanti Date: Thu, 11 May 2023 17:57:12 -0700 Subject: [PATCH 3/7] Fix SDK compilation --- .../smithy/rustsdk/AwsFluentClientDecorator.kt | 2 +- .../smithy/rust/codegen/core/rustlang/RustWriter.kt | 12 +++--------- .../codegen/core/smithy/generators/Instantiator.kt | 2 +- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt index fa9c5ed63f..d0639dbb81 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt @@ -239,7 +239,7 @@ private fun renderCustomizableOperationSendMethod( #{handle_generics_bounds:W} { /// Sends this operation's request - pub async fn send(self) -> #{Result}> + pub async fn send(self) -> #{Result}> where E: std::error::Error + #{Send} + #{Sync} + 'static, O: #{ParseHttpResponse}> + #{Send} + #{Sync} + #{Clone} + 'static, diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriter.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriter.kt index 5781a3404e..007f5e24d3 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriter.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriter.kt @@ -150,15 +150,9 @@ fun RustWriter.conditionalBlockTemplate( vararg args: Pair, block: RustWriter.() -> Unit, ): RustWriter { - if (conditional) { - withTemplate(textBeforeNewLine.trim(), args) { text -> - openBlock(text) - } - } - block(this) - if (conditional) { - withTemplate(textAfterNewLine.trim(), args) { text -> - closeBlock(text) + withTemplate(textBeforeNewLine.trim(), args) { beforeNewLine -> + withTemplate(textAfterNewLine.trim(), args) { afterNewLine -> + conditionalBlock(beforeNewLine, afterNewLine, conditional = conditional, block = block) } } return this diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/Instantiator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/Instantiator.kt index 089143feea..3a59bc1bcd 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/Instantiator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/Instantiator.kt @@ -205,7 +205,7 @@ open class Instantiator( check(symbol.isOptional()) { "A null node was provided for $memberShape but the symbol was not optional. This is invalid input data." } - writer.rust("None") + writer.rustTemplate("#{None}", *preludeScope) } else { // Structure builder setters for structure shape members _always_ take in `Option`. // Other aggregate shapes' members are optional only when their symbol is. From e21477147f863610fdcc50c3c1b41ccdfd00a253 Mon Sep 17 00:00:00 2001 From: John DiSanti Date: Thu, 11 May 2023 18:17:53 -0700 Subject: [PATCH 4/7] Test fixes --- .../codegen/core/rustlang/RustTypeTest.kt | 24 +++++++++---------- .../codegen/core/rustlang/RustWriterTest.kt | 4 ++-- .../codegen/core/rustlang/WritableTest.kt | 4 ++-- .../SmithyTypesPubUseExtraTest.kt | 20 ++++++++-------- .../PythonServerSymbolProviderTest.kt | 4 ++-- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustTypeTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustTypeTest.kt index 7fa364dfaf..1c89f39058 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustTypeTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustTypeTest.kt @@ -54,14 +54,14 @@ internal class RustTypesTest { @Test fun `RustType_String_writable produces a template-compatible RuntimeType`() { - forInputExpectOutput(RustType.String.writable, "'std::string::String'") + forInputExpectOutput(RustType.String.writable, "'::std::string::String'") } @Test fun `RustType_Vec_writable produces a template-compatible RuntimeType`() { forInputExpectOutput( RustType.Vec(RustType.String).writable, - "'std::vec::Vec'", + "'::std::vec::Vec<::std::string::String>'", ) } @@ -69,7 +69,7 @@ internal class RustTypesTest { fun `RustType_Slice_writable produces a template-compatible RuntimeType`() { forInputExpectOutput( RustType.Slice(RustType.String).writable, - "'[std::string::String]'", + "'[::std::string::String]'", ) } @@ -77,7 +77,7 @@ internal class RustTypesTest { fun `RustType_HashMap_writable produces a template-compatible RuntimeType`() { forInputExpectOutput( RustType.HashMap(RustType.String, RustType.String).writable, - "'std::collections::HashMap'", + "'::std::collections::HashMap<::std::string::String, ::std::string::String>'", ) } @@ -87,7 +87,7 @@ internal class RustTypesTest { RustType.HashSet(RustType.String).writable, // Rust doesn't guarantee that `HashSet`s are insertion ordered, so we use a `Vec` instead. // This is called out in a comment in the RustType.HashSet declaration - "'std::vec::Vec'", + "'::std::vec::Vec<::std::string::String>'", ) } @@ -95,15 +95,15 @@ internal class RustTypesTest { fun `RustType_Reference_writable produces a template-compatible RuntimeType`() { forInputExpectOutput( RustType.Reference("&", RustType.String).writable, - "'&std::string::String'", + "'&::std::string::String'", ) forInputExpectOutput( RustType.Reference("&mut", RustType.String).writable, - "'&mut std::string::String'", + "'&mut ::std::string::String'", ) forInputExpectOutput( RustType.Reference("&'static", RustType.String).writable, - "&'static std::string::String'", + "&'static ::std::string::String'", ) } @@ -111,7 +111,7 @@ internal class RustTypesTest { fun `RustType_Option_writable produces a template-compatible RuntimeType`() { forInputExpectOutput( RustType.Option(RustType.String).writable, - "'std::option::Option'", + "'::std::option::Option<::std::string::String>'", ) } @@ -119,7 +119,7 @@ internal class RustTypesTest { fun `RustType_Box_writable produces a template-compatible RuntimeType`() { forInputExpectOutput( RustType.Box(RustType.String).writable, - "'std::boxed::Box'", + "'::std::boxed::Box<::std::string::String>'", ) } @@ -147,7 +147,7 @@ internal class RustTypesTest { fun `types render properly`() { val type = RustType.Box(RustType.Option(RustType.Reference("a", RustType.Vec(RustType.String)))) type.render(false) shouldBe "Box>>" - type.render(true) shouldBe "std::boxed::Box>>" + type.render(true) shouldBe "::std::boxed::Box<::std::option::Option<&'a ::std::vec::Vec<::std::string::String>>>" } @Test @@ -211,7 +211,7 @@ internal class RustTypesTest { writable { attributeMacro.render(this) }, - "#[derive(std::clone::Clone, std::error::Error, std::fmt::Debug)]\n", + "#[derive(::std::clone::Clone, ::std::error::Error, ::std::fmt::Debug)]\n", ) } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriterTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriterTest.kt index ac14bcd20f..2bd5269cc2 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriterTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriterTest.kt @@ -143,7 +143,7 @@ class RustWriterTest { ) val sut = RustWriter.root() metadata.render(sut) - sut.toString().shouldContain("#[allow(deprecated)]\n#[derive(std::fmt::Debug)]\n#[foo]") + sut.toString().shouldContain("#[allow(deprecated)]\n#[derive(::std::fmt::Debug)]\n#[foo]") } @Test @@ -183,7 +183,7 @@ class RustWriterTest { "Inner" to inner, "http" to RuntimeType.Http.resolve("foo"), ) - sut.toString().shouldContain("inner: hello, regular: http::foo") + sut.toString().shouldContain("inner: hello, regular: ::http::foo") } @Test diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/WritableTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/WritableTest.kt index 7da0562451..04c5ff2f1a 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/WritableTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/WritableTest.kt @@ -33,7 +33,7 @@ internal class RustTypeParametersTest { @Test fun `rustTypeParameters accepts RuntimeType`() { val runtimeType = RuntimeType.String - forInputExpectOutput(runtimeType, "''") + forInputExpectOutput(runtimeType, "'<::std::string::String>'") } @Test @@ -60,7 +60,7 @@ internal class RustTypeParametersTest { writer.rustInlineTemplate("#{tps:W}", "tps" to tps) writer.rustInlineTemplate("'") - writer.toString() shouldContain "''" + writer.toString() shouldContain "''" } @Test diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtraTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtraTest.kt index 120fc5cb20..55b792218f 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtraTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtraTest.kt @@ -74,38 +74,38 @@ class SmithyTypesPubUseExtraTest { @Test fun `it re-exports Blob when a model uses blobs`() { - assertDoesntHaveType(typesWithEmptyModel(), "aws_smithy_types::Blob") - assertHasType(typesWithMember(inputMember = "foo: Blob"), "aws_smithy_types::Blob") - assertHasType(typesWithMember(outputMember = "foo: Blob"), "aws_smithy_types::Blob") + assertDoesntHaveType(typesWithEmptyModel(), "::aws_smithy_types::Blob") + assertHasType(typesWithMember(inputMember = "foo: Blob"), "::aws_smithy_types::Blob") + assertHasType(typesWithMember(outputMember = "foo: Blob"), "::aws_smithy_types::Blob") assertHasType( typesWithMember(inputMember = "foo: SomeUnion", unionMember = "foo: Blob"), - "aws_smithy_types::Blob", + "::aws_smithy_types::Blob", ) assertHasType( typesWithMember(outputMember = "foo: SomeUnion", unionMember = "foo: Blob"), - "aws_smithy_types::Blob", + "::aws_smithy_types::Blob", ) } @Test fun `it re-exports DateTime when a model uses timestamps`() { assertDoesntHaveType(typesWithEmptyModel(), "aws_smithy_types::DateTime") - assertHasType(typesWithMember(inputMember = "foo: Timestamp"), "aws_smithy_types::DateTime") - assertHasType(typesWithMember(outputMember = "foo: Timestamp"), "aws_smithy_types::DateTime") + assertHasType(typesWithMember(inputMember = "foo: Timestamp"), "::aws_smithy_types::DateTime") + assertHasType(typesWithMember(outputMember = "foo: Timestamp"), "::aws_smithy_types::DateTime") assertHasType( typesWithMember(inputMember = "foo: SomeUnion", unionMember = "foo: Timestamp"), - "aws_smithy_types::DateTime", + "::aws_smithy_types::DateTime", ) assertHasType( typesWithMember(outputMember = "foo: SomeUnion", unionMember = "foo: Timestamp"), - "aws_smithy_types::DateTime", + "::aws_smithy_types::DateTime", ) } @Test fun `it re-exports ByteStream and AggregatedBytes when a model has streaming`() { val streamingTypes = - listOf("aws_smithy_http::byte_stream::ByteStream", "aws_smithy_http::byte_stream::AggregatedBytes") + listOf("::aws_smithy_http::byte_stream::ByteStream", "::aws_smithy_http::byte_stream::AggregatedBytes") val streamingShape = "@streaming blob Streaming" assertDoesntHaveTypes(typesWithEmptyModel(), streamingTypes) diff --git a/codegen-server/python/src/test/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerSymbolProviderTest.kt b/codegen-server/python/src/test/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerSymbolProviderTest.kt index c7467b58ed..e3ab955a9f 100644 --- a/codegen-server/python/src/test/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerSymbolProviderTest.kt +++ b/codegen-server/python/src/test/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerSymbolProviderTest.kt @@ -16,8 +16,8 @@ import software.amazon.smithy.rust.codegen.server.smithy.testutil.ServerTestRust import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestRustSettings internal class PythonServerSymbolProviderTest { - private val pythonBlobType = RustType.Opaque("Blob", "aws_smithy_http_server_python::types") - private val pythonTimestampType = RustType.Opaque("DateTime", "aws_smithy_http_server_python::types") + private val pythonBlobType = RustType.Opaque("Blob", "::aws_smithy_http_server_python::types") + private val pythonTimestampType = RustType.Opaque("DateTime", "::aws_smithy_http_server_python::types") @Test fun `python symbol provider rewrites timestamp shape symbol`() { From 57ccc344a0b5c864f5c5018a0ff323a2f0ce1dbf Mon Sep 17 00:00:00 2001 From: John DiSanti Date: Fri, 12 May 2023 10:12:55 -0700 Subject: [PATCH 5/7] Fix `codegen-server` tests --- .../smithy/generators/ConstrainedCollectionGenerator.kt | 2 +- .../server/smithy/UnconstrainedShapeSymbolProviderTest.kt | 2 +- .../server/smithy/generators/ConstrainedBlobGeneratorTest.kt | 4 ++-- .../smithy/generators/ConstrainedCollectionGeneratorTest.kt | 4 ++-- .../server/smithy/generators/ConstrainedMapGeneratorTest.kt | 4 ++-- .../smithy/generators/ConstrainedNumberGeneratorTest.kt | 2 +- .../smithy/generators/ConstrainedStringGeneratorTest.kt | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGenerator.kt index 9b5775478e..f705e4af3a 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGenerator.kt @@ -72,7 +72,7 @@ class ConstrainedCollectionGenerator( } val name = constrainedShapeSymbolProvider.toSymbol(shape).name - val inner = "std::vec::Vec<#{ValueMemberSymbol}>" + val inner = "::std::vec::Vec<#{ValueMemberSymbol}>" val constraintViolation = constraintViolationSymbolProvider.toSymbol(shape) val constrainedSymbol = symbolProvider.toSymbol(shape) diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProviderTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProviderTest.kt index 7c8efe9c17..5f47e10779 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProviderTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProviderTest.kt @@ -98,6 +98,6 @@ class UnconstrainedShapeSymbolProviderTest { val structureBShape = model.lookup("test#StructureB") unconstrainedShapeSymbolProvider.toSymbol(structureBShape).rustType().render() shouldBe "crate::model::StructureB" - unconstrainedShapeSymbolProvider.toSymbol(listAShape).rustType().render() shouldBe "std::vec::Vec" + unconstrainedShapeSymbolProvider.toSymbol(listAShape).rustType().render() shouldBe "::std::vec::Vec" } } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt index 060e0166a4..3a35120f83 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt @@ -117,7 +117,7 @@ class ConstrainedBlobGeneratorTest { } @Test - fun `type should not be constructible without using a constructor`() { + fun `type should not be constructable without using a constructor`() { val model = """ namespace test @@ -139,6 +139,6 @@ class ConstrainedBlobGeneratorTest { ).render() // Check that the wrapped type is `pub(crate)`. - writer.toString() shouldContain "pub struct ConstrainedBlob(pub(crate) aws_smithy_types::Blob);" + writer.toString() shouldContain "pub struct ConstrainedBlob(pub(crate) ::aws_smithy_types::Blob);" } } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt index cce7da4aa6..3b9e0d4a7b 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt @@ -258,7 +258,7 @@ class ConstrainedCollectionGeneratorTest { } @Test - fun `type should not be constructible without using a constructor`() { + fun `type should not be constructable without using a constructor`() { val model = """ namespace test @@ -276,7 +276,7 @@ class ConstrainedCollectionGeneratorTest { render(codegenContext, writer, constrainedCollectionShape) // Check that the wrapped type is `pub(crate)`. - writer.toString() shouldContain "pub struct ConstrainedList(pub(crate) std::vec::Vec);" + writer.toString() shouldContain "pub struct ConstrainedList(pub(crate) ::std::vec::Vec<::std::string::String>);" } private fun render( diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt index 0eebb7e36b..cd83336124 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt @@ -128,7 +128,7 @@ class ConstrainedMapGeneratorTest { } @Test - fun `type should not be constructible without using a constructor`() { + fun `type should not be constructable without using a constructor`() { val model = """ namespace test @@ -146,7 +146,7 @@ class ConstrainedMapGeneratorTest { render(codegenContext, writer, constrainedMapShape) // Check that the wrapped type is `pub(crate)`. - writer.toString() shouldContain "pub struct ConstrainedMap(pub(crate) std::collections::HashMap);" + writer.toString() shouldContain "pub struct ConstrainedMap(pub(crate) ::std::collections::HashMap<::std::string::String, ::std::string::String>);" } private fun render( diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt index 5a78574c93..3a34c7753c 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt @@ -127,7 +127,7 @@ class ConstrainedNumberGeneratorTest { @ParameterizedTest @ArgumentsSource(NoStructuralConstructorTestProvider::class) - fun `type should not be constructible without using a constructor`(args: Triple) { + fun `type should not be constructable without using a constructor`(args: Triple) { val (smithyType, shapeName, rustType) = args val model = """ namespace test diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt index 62a7d061c3..eb0ba5ed34 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt @@ -131,7 +131,7 @@ class ConstrainedStringGeneratorTest { } @Test - fun `type should not be constructible without using a constructor`() { + fun `type should not be constructable without using a constructor`() { val model = """ namespace test @@ -153,7 +153,7 @@ class ConstrainedStringGeneratorTest { ).render() // Check that the wrapped type is `pub(crate)`. - writer.toString() shouldContain "pub struct ConstrainedString(pub(crate) std::string::String);" + writer.toString() shouldContain "pub struct ConstrainedString(pub(crate) ::std::string::String);" } @Test From 49d10aecb5d768cece726b2aaab87a1136852040 Mon Sep 17 00:00:00 2001 From: John DiSanti Date: Fri, 12 May 2023 13:36:06 -0700 Subject: [PATCH 6/7] Incorporate feedback --- codegen-client-test/build.gradle.kts | 16 -- .../smithy/generators/ClientEnumGenerator.kt | 2 +- .../client/smithy/NamingObstacleCourseTest.kt | 35 ++++ .../naming-obstacle-course-prelude-ops.smithy | 92 ---------- ...ing-obstacle-course-prelude-structs.smithy | 125 ------------- .../rust/codegen/core/smithy/RuntimeType.kt | 12 +- .../core/smithy/generators/EnumGenerator.kt | 9 +- .../NamingObstacleCourseTestModels.kt | 172 ++++++++++++++++++ .../ConstrainedTraitForEnumGenerator.kt | 6 +- .../smithy/generators/ServerEnumGenerator.kt | 9 +- .../server/smithy/NamingObstacleCourseTest.kt | 32 ++++ 11 files changed, 265 insertions(+), 245 deletions(-) create mode 100644 codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/NamingObstacleCourseTest.kt delete mode 100644 codegen-core/common-test-models/naming-obstacle-course-prelude-ops.smithy delete mode 100644 codegen-core/common-test-models/naming-obstacle-course-prelude-structs.smithy create mode 100644 codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/NamingObstacleCourseTestModels.kt create mode 100644 codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/NamingObstacleCourseTest.kt diff --git a/codegen-client-test/build.gradle.kts b/codegen-client-test/build.gradle.kts index b833bfb195..f3796a6911 100644 --- a/codegen-client-test/build.gradle.kts +++ b/codegen-client-test/build.gradle.kts @@ -92,22 +92,6 @@ val allCodegenTests = "../codegen-core/common-test-models".let { commonModels -> """.trimIndent(), imports = listOf("$commonModels/naming-obstacle-course-structs.smithy"), ), - CodegenTest( - "crate#Config", - "naming_test_prelude_ops", - """ - , "codegen": { "renameErrors": false } - """.trimIndent(), - imports = listOf("$commonModels/naming-obstacle-course-prelude-ops.smithy"), - ), - CodegenTest( - "crate#Config", - "naming_test_prelude_structs", - """ - , "codegen": { "renameErrors": false } - """.trimIndent(), - imports = listOf("$commonModels/naming-obstacle-course-prelude-structs.smithy"), - ), CodegenTest("aws.protocoltests.json#TestService", "endpoint-rules"), CodegenTest("com.aws.example.rust#PokemonService", "pokemon-service-client", imports = listOf("$commonModels/pokemon.smithy", "$commonModels/pokemon-common.smithy")), CodegenTest("com.aws.example.rust#PokemonService", "pokemon-service-awsjson-client", imports = listOf("$commonModels/pokemon-awsjson.smithy", "$commonModels/pokemon-common.smithy")), 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 538e1df83b..64f6d9446b 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 @@ -66,7 +66,7 @@ data class InfallibleEnumType( impl ::std::str::FromStr for ${context.enumName} { type Err = ::std::convert::Infallible; - fn from_str(s: &str) -> #{Result} { + fn from_str(s: &str) -> #{Result}::Err> { #{Ok}(${context.enumName}::from(s)) } } diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/NamingObstacleCourseTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/NamingObstacleCourseTest.kt new file mode 100644 index 0000000000..aba0edc1a5 --- /dev/null +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/NamingObstacleCourseTest.kt @@ -0,0 +1,35 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.rust.codegen.client.smithy + +import org.junit.jupiter.api.Test +import software.amazon.smithy.rust.codegen.client.testutil.clientIntegrationTest +import software.amazon.smithy.rust.codegen.core.testutil.NamingObstacleCourseTestModels.rustPreludeEnumVariantsModel +import software.amazon.smithy.rust.codegen.core.testutil.NamingObstacleCourseTestModels.rustPreludeEnumsModel +import software.amazon.smithy.rust.codegen.core.testutil.NamingObstacleCourseTestModels.rustPreludeOperationsModel +import software.amazon.smithy.rust.codegen.core.testutil.NamingObstacleCourseTestModels.rustPreludeStructsModel + +class NamingObstacleCourseTest { + @Test + fun `test Rust prelude operation names compile`() { + clientIntegrationTest(rustPreludeOperationsModel()) { _, _ -> } + } + + @Test + fun `test Rust prelude structure names compile`() { + clientIntegrationTest(rustPreludeStructsModel()) { _, _ -> } + } + + @Test + fun `test Rust prelude enum names compile`() { + clientIntegrationTest(rustPreludeEnumsModel()) { _, _ -> } + } + + @Test + fun `test Rust prelude enum variant names compile`() { + clientIntegrationTest(rustPreludeEnumVariantsModel()) { _, _ -> } + } +} diff --git a/codegen-core/common-test-models/naming-obstacle-course-prelude-ops.smithy b/codegen-core/common-test-models/naming-obstacle-course-prelude-ops.smithy deleted file mode 100644 index 36b7ee61d3..0000000000 --- a/codegen-core/common-test-models/naming-obstacle-course-prelude-ops.smithy +++ /dev/null @@ -1,92 +0,0 @@ -$version: "1.0" -namespace crate - -use smithy.test#httpRequestTests -use smithy.test#httpResponseTests -use aws.protocols#awsJson1_1 -use aws.api#service -use smithy.framework#ValidationException - -/// Confounds model generation machinery by using operations named after every item in the Rust prelude -@awsJson1_1 -@service(sdkId: "Config") -service Config { - version: "2006-03-01", - operations: [ - // Rust Prelude - Copy, - Send, - Sized, - Sync, - Unpin, - Drop, - Fn, - FnMut, - FnOnce, - Box, - ToOwned, - Clone, - PartialEq, - PartialOrd, - Eq, - Ord, - AsRef, - AsMut, - Into, - From, - Default, - Iterator, - Extend, - IntoIterator, - DoubleEndedIterator, - ExactSizeIterator, - Option, - Some, - None, - Result, - Ok, - Err, - String, - ToString, - Vec, - ] -} - -structure Input {} -structure Output {} - -operation Copy { input: Input, output: Output } -operation Send { input: Input, output: Output } -operation Sized { input: Input, output: Output } -operation Sync { input: Input, output: Output } -operation Unpin { input: Input, output: Output } -operation Drop { input: Input, output: Output } -operation Fn { input: Input, output: Output } -operation FnMut { input: Input, output: Output } -operation FnOnce { input: Input, output: Output } -operation Box { input: Input, output: Output } -operation ToOwned { input: Input, output: Output } -operation Clone { input: Input, output: Output } -operation PartialEq { input: Input, output: Output } -operation PartialOrd { input: Input, output: Output } -operation Eq { input: Input, output: Output } -operation Ord { input: Input, output: Output } -operation AsRef { input: Input, output: Output } -operation AsMut { input: Input, output: Output } -operation Into { input: Input, output: Output } -operation From { input: Input, output: Output } -operation Default { input: Input, output: Output } -operation Iterator { input: Input, output: Output } -operation Extend { input: Input, output: Output } -operation IntoIterator { input: Input, output: Output } -operation DoubleEndedIterator { input: Input, output: Output } -operation ExactSizeIterator { input: Input, output: Output } -operation Option { input: Input, output: Output } -operation Some { input: Input, output: Output } -operation None { input: Input, output: Output } -operation Result { input: Input, output: Output } -operation Ok { input: Input, output: Output } -operation Err { input: Input, output: Output } -operation String { input: Input, output: Output } -operation ToString { input: Input, output: Output } -operation Vec { input: Input, output: Output } diff --git a/codegen-core/common-test-models/naming-obstacle-course-prelude-structs.smithy b/codegen-core/common-test-models/naming-obstacle-course-prelude-structs.smithy deleted file mode 100644 index 0047c182c3..0000000000 --- a/codegen-core/common-test-models/naming-obstacle-course-prelude-structs.smithy +++ /dev/null @@ -1,125 +0,0 @@ -$version: "1.0" -namespace crate - -use smithy.test#httpRequestTests -use smithy.test#httpResponseTests -use aws.protocols#awsJson1_1 -use aws.api#service -use smithy.framework#ValidationException - -/// Confounds model generation machinery by using structs named after every item in the Rust prelude -@awsJson1_1 -@service(sdkId: "Config") -service Config { - version: "2006-03-01", - operations: [ - UseCopy, - UseSend, - UseSized, - UseSync, - UseUnpin, - UseDrop, - UseFn, - UseFnMut, - UseFnOnce, - UseBox, - UseToOwned, - UseClone, - UsePartialEq, - UsePartialOrd, - UseEq, - UseOrd, - UseAsRef, - UseAsMut, - UseInto, - UseFrom, - UseDefault, - UseIterator, - UseExtend, - UseIntoIterator, - UseDoubleEndedIterator, - UseExactSizeIterator, - UseOption, - UseSome, - UseNone, - UseResult, - UseOk, - UseErr, - UseString, - UseToString, - UseVec, - ] -} - -// Rust Prelude -structure Copy {} -structure Send {} -structure Sized {} -structure Sync {} -structure Unpin {} -structure Drop {} -structure Fn {} -structure FnMut {} -structure FnOnce {} -structure Box {} -structure ToOwned {} -structure Clone {} -structure PartialEq {} -structure PartialOrd {} -structure Eq {} -structure Ord {} -structure AsRef {} -structure AsMut {} -structure Into {} -structure From {} -structure Default {} -structure Iterator {} -structure Extend {} -structure IntoIterator {} -structure DoubleEndedIterator {} -structure ExactSizeIterator {} -structure Option {} -structure Some {} -structure None {} -structure Result {} -structure Ok {} -structure Err {} -structure String {} -structure ToString {} -structure Vec {} - -operation UseCopy { input: Copy, output: Copy } -operation UseSend { input: Send, output: Send } -operation UseSized { input: Sized, output: Sized } -operation UseSync { input: Sync, output: Sync } -operation UseUnpin { input: Unpin, output: Unpin } -operation UseDrop { input: Drop, output: Drop } -operation UseFn { input: Fn, output: Fn } -operation UseFnMut { input: FnMut, output: FnMut } -operation UseFnOnce { input: FnOnce, output: FnOnce } -operation UseBox { input: Box, output: Box } -operation UseToOwned { input: ToOwned, output: ToOwned } -operation UseClone { input: Clone, output: Clone } -operation UsePartialEq { input: PartialEq, output: PartialEq } -operation UsePartialOrd { input: PartialOrd, output: PartialOrd } -operation UseEq { input: Eq, output: Eq } -operation UseOrd { input: Ord, output: Ord } -operation UseAsRef { input: AsRef, output: AsRef } -operation UseAsMut { input: AsMut, output: AsMut } -operation UseInto { input: Into, output: Into } -operation UseFrom { input: From, output: From } -operation UseDefault { input: Default, output: Default } -operation UseIterator { input: Iterator, output: Iterator } -operation UseExtend { input: Extend, output: Extend } -operation UseIntoIterator { input: IntoIterator, output: IntoIterator } -operation UseDoubleEndedIterator { input: DoubleEndedIterator, output: DoubleEndedIterator } -operation UseExactSizeIterator { input: ExactSizeIterator, output: ExactSizeIterator } -operation UseOption { input: Option, output: Option } -operation UseSome { input: Some, output: Some } -operation UseNone { input: None, output: None } -operation UseResult { input: Result, output: Result } -operation UseOk { input: Ok, output: Ok } -operation UseErr { input: Err, output: Err } -operation UseString { input: String, output: String } -operation UseToString { input: ToString, output: ToString } -operation UseVec { input: Vec, output: Vec } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt index 6616fdd96f..6e5b5ee8ff 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt @@ -193,9 +193,14 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null) * The companion object contains commonly used RuntimeTypes */ companion object { - /** Scope that contains all Rust prelude types, but not macros or functions */ + /** + * Scope that contains all Rust prelude types, but not macros or functions. + * + * Prelude docs: https://doc.rust-lang.org/std/prelude/index.html#prelude-contents + */ val preludeScope by lazy { arrayOf( + // Rust 1.0 "Copy" to std.resolve("marker::Copy"), "Send" to Send, "Sized" to std.resolve("marker::Sized"), @@ -231,6 +236,11 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null) "String" to String, "ToString" to std.resolve("string::ToString"), "Vec" to Vec, + + // 2021 Edition + "TryFrom" to std.resolve("convert::TryFrom"), + "TryInto" to std.resolve("convert::TryInto"), + "FromIterator" to std.resolve("iter::FromIterator"), ) } 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 d5565880f1..a84820ad26 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 @@ -27,6 +27,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.MaybeRenamed import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata import software.amazon.smithy.rust.codegen.core.smithy.renamedFrom @@ -208,14 +209,15 @@ open class EnumGenerator( } }, ) - rust( + rustTemplate( """ - impl AsRef for ${context.enumName} { + impl #{AsRef} for ${context.enumName} { fn as_ref(&self) -> &str { self.as_str() } } """, + *preludeScope, ) } @@ -238,8 +240,7 @@ open class EnumGenerator( } } """, - "From" to RuntimeType.From, - "AsRef" to RuntimeType.AsRef, + *preludeScope, ) } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/NamingObstacleCourseTestModels.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/NamingObstacleCourseTestModels.kt new file mode 100644 index 0000000000..c45a7d0992 --- /dev/null +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/NamingObstacleCourseTestModels.kt @@ -0,0 +1,172 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.rust.codegen.core.testutil + +import software.amazon.smithy.model.Model +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope + +object NamingObstacleCourseTestModels { + private val rustPrelude = preludeScope.map { pair -> pair.first } + + /** + * Test model that confounds the generation machinery by using operations named after every item + * in the Rust prelude. + */ + fun rustPreludeOperationsModel(): Model = StringBuilder().apply { + append( + """ + ${"$"}version: "2.0" + namespace crate + + use smithy.test#httpRequestTests + use smithy.test#httpResponseTests + use aws.protocols#awsJson1_1 + use aws.api#service + use smithy.framework#ValidationException + + structure InputAndOutput {} + + @awsJson1_1 + @service(sdkId: "Config") + service Config { + version: "2006-03-01", + rename: { "smithy.api#String": "PreludeString" }, + operations: [ + """, + ) + for (item in rustPrelude) { + append("$item,\n") + } + append( + """ + ] + } + """, + ) + for (item in rustPrelude) { + append("operation $item { input: InputAndOutput, output: InputAndOutput, errors: [ValidationException] }\n") + } + }.toString().asSmithyModel() + + fun rustPreludeStructsModel(): Model = StringBuilder().apply { + append( + """ + ${"$"}version: "2.0" + namespace crate + + use smithy.test#httpRequestTests + use smithy.test#httpResponseTests + use aws.protocols#awsJson1_1 + use aws.api#service + use smithy.framework#ValidationException + + structure InputAndOutput {} + + @awsJson1_1 + @service(sdkId: "Config") + service Config { + version: "2006-03-01", + rename: { "smithy.api#String": "PreludeString" }, + operations: [ + """, + ) + for (item in rustPrelude) { + append("Use$item,\n") + } + append( + """ + ] + } + """, + ) + for (item in rustPrelude) { + append("structure $item { $item: smithy.api#String }\n") + append("operation Use$item { input: $item, output: $item, errors: [ValidationException] }\n") + } + println(toString()) + }.toString().asSmithyModel() + + fun rustPreludeEnumsModel(): Model = StringBuilder().apply { + append( + """ + ${"$"}version: "2.0" + namespace crate + + use smithy.test#httpRequestTests + use smithy.test#httpResponseTests + use aws.protocols#awsJson1_1 + use aws.api#service + use smithy.framework#ValidationException + + structure InputAndOutput {} + + @awsJson1_1 + @service(sdkId: "Config") + service Config { + version: "2006-03-01", + rename: { "smithy.api#String": "PreludeString" }, + operations: [ + """, + ) + for (item in rustPrelude) { + append("Use$item,\n") + } + append( + """ + ] + } + """, + ) + for (item in rustPrelude) { + append("enum $item { $item }\n") + append("structure Struct$item { $item: $item }\n") + append("operation Use$item { input: Struct$item, output: Struct$item, errors: [ValidationException] }\n") + } + }.toString().asSmithyModel() + + fun rustPreludeEnumVariantsModel(): Model = StringBuilder().apply { + append( + """ + ${"$"}version: "2.0" + namespace crate + + use smithy.test#httpRequestTests + use smithy.test#httpResponseTests + use aws.protocols#awsJson1_1 + use aws.api#service + use smithy.framework#ValidationException + + @awsJson1_1 + @service(sdkId: "Config") + service Config { + version: "2006-03-01", + rename: { "smithy.api#String": "PreludeString" }, + operations: [EnumOp] + } + + operation EnumOp { + input: InputAndOutput, + output: InputAndOutput, + errors: [ValidationException], + } + + structure InputAndOutput { + the_enum: TheEnum, + } + + enum TheEnum { + """, + ) + for (item in rustPrelude) { + append("$item,\n") + } + append( + """ + } + """, + ) + }.toString().asSmithyModel() +} diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedTraitForEnumGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedTraitForEnumGenerator.kt index 44992f4a48..8e52d0d4da 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedTraitForEnumGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedTraitForEnumGenerator.kt @@ -11,6 +11,7 @@ import software.amazon.smithy.model.traits.EnumTrait import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained import software.amazon.smithy.rust.codegen.core.util.expectTrait @@ -30,7 +31,7 @@ class ConstrainedTraitForEnumGenerator( val symbol = symbolProvider.toSymbol(shape) val name = symbol.name - val unconstrainedType = "String" + val unconstrainedType = RuntimeType.String.fullyQualifiedName() writer.rustTemplate( """ @@ -38,12 +39,13 @@ class ConstrainedTraitForEnumGenerator( type Unconstrained = $unconstrainedType; } - impl From<$unconstrainedType> for #{MaybeConstrained} { + impl #{From}<$unconstrainedType> for #{MaybeConstrained} { fn from(value: $unconstrainedType) -> Self { Self::Unconstrained(value) } } """, + *preludeScope, "ConstrainedTrait" to RuntimeType.ConstrainedTrait, "MaybeConstrained" to symbol.makeMaybeConstrained(), ) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGenerator.kt index cc811b80f2..09a0d2d5cd 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGenerator.kt @@ -8,9 +8,11 @@ import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock +import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.generators.EnumGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.EnumGeneratorContext import software.amazon.smithy.rust.codegen.core.smithy.generators.EnumType @@ -65,7 +67,7 @@ open class ConstrainedEnum( } rustBlock("impl #T<&str> for ${context.enumName}", RuntimeType.TryFrom) { rust("type Error = #T;", constraintViolationSymbol) - rustBlock("fn try_from(s: &str) -> Result>::Error>", RuntimeType.TryFrom) { + rustBlockTemplate("fn try_from(s: &str) -> #{Result}>::Error>", *preludeScope) { rustBlock("match s") { context.sortedMembers.forEach { member -> rust("${member.value.dq()} => Ok(${context.enumName}::${member.derivedName()}),") @@ -78,13 +80,12 @@ open class ConstrainedEnum( """ impl #{TryFrom}<#{String}> for ${context.enumName} { type Error = #{ConstraintViolation}; - fn try_from(s: #{String}) -> std::result::Result>::Error> { + fn try_from(s: #{String}) -> #{Result}>::Error> { s.as_str().try_into() } } """, - "String" to RuntimeType.String, - "TryFrom" to RuntimeType.TryFrom, + *preludeScope, "ConstraintViolation" to constraintViolationSymbol, ) } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/NamingObstacleCourseTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/NamingObstacleCourseTest.kt new file mode 100644 index 0000000000..b0ae1c3473 --- /dev/null +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/NamingObstacleCourseTest.kt @@ -0,0 +1,32 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.rust.codegen.server.smithy + +import org.junit.jupiter.api.Test +import software.amazon.smithy.rust.codegen.core.testutil.NamingObstacleCourseTestModels +import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverIntegrationTest + +class NamingObstacleCourseTest { + @Test + fun `test Rust prelude operation names compile`() { + serverIntegrationTest(NamingObstacleCourseTestModels.rustPreludeOperationsModel()) { _, _ -> } + } + + @Test + fun `test Rust prelude structure names compile`() { + serverIntegrationTest(NamingObstacleCourseTestModels.rustPreludeStructsModel()) { _, _ -> } + } + + @Test + fun `test Rust prelude enum names compile`() { + serverIntegrationTest(NamingObstacleCourseTestModels.rustPreludeEnumsModel()) { _, _ -> } + } + + @Test + fun `test Rust prelude enum variant names compile`() { + serverIntegrationTest(NamingObstacleCourseTestModels.rustPreludeEnumVariantsModel()) { _, _ -> } + } +} From af6eea4c4e9d87772fe1d6c99902c3052e4c9a5e Mon Sep 17 00:00:00 2001 From: John DiSanti Date: Fri, 12 May 2023 15:22:40 -0700 Subject: [PATCH 7/7] Fix tests --- .../client/smithy/StreamingShapeSymbolProviderTest.kt | 4 ++-- .../smithy/rust/codegen/server/python/smithy/PythonType.kt | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/StreamingShapeSymbolProviderTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/StreamingShapeSymbolProviderTest.kt index a2e233c719..61d97317f2 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/StreamingShapeSymbolProviderTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/StreamingShapeSymbolProviderTest.kt @@ -43,13 +43,13 @@ internal class StreamingShapeSymbolProviderTest { modelWithOperationTraits.lookup("test.synthetic#GenerateSpeechOutput\$data").also { shape -> symbolProvider.toSymbol(shape).also { symbol -> symbol.name shouldBe "data" - symbol.rustType() shouldBe RustType.Opaque("ByteStream", "aws_smithy_http::byte_stream") + symbol.rustType() shouldBe RustType.Opaque("ByteStream", "::aws_smithy_http::byte_stream") } } modelWithOperationTraits.lookup("test.synthetic#GenerateSpeechInput\$data").also { shape -> symbolProvider.toSymbol(shape).also { symbol -> symbol.name shouldBe "data" - symbol.rustType() shouldBe RustType.Opaque("ByteStream", "aws_smithy_http::byte_stream") + symbol.rustType() shouldBe RustType.Opaque("ByteStream", "::aws_smithy_http::byte_stream") } } } diff --git a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonType.kt b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonType.kt index 42f878d6fc..8cdc481b39 100644 --- a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonType.kt +++ b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonType.kt @@ -111,6 +111,13 @@ sealed class PythonType { else -> it } } + // Most opaque types have a leading `::`, so strip that for Python as needed + .let { + when (it?.startsWith(".")) { + true -> it.substring(1) + else -> it + } + } } }