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() """,