From 28742d5097a81ddef8ef26b4b5ca09d7b2efe1c3 Mon Sep 17 00:00:00 2001 From: John DiSanti Date: Fri, 12 May 2023 15:47:31 -0700 Subject: [PATCH] Fix client operation name collisions with the standard library prelude (#2696) ## Motivation and Context 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). ## Checklist - [x] I have updated `CHANGELOG.next.toml` if I made changes to the smithy-rs codegen or runtime crates ---- _By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice._ --- CHANGELOG.next.toml | 6 + .../rustsdk/AwsFluentClientDecorator.kt | 9 +- .../smithy/rustsdk/AwsPresigningDecorator.kt | 3 +- .../rustsdk/customize/s3/S3Decorator.kt | 3 +- .../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 +- .../client/smithy/NamingObstacleCourseTest.kt | 35 ++++ .../StreamingShapeSymbolProviderTest.kt | 4 +- .../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 | 18 +- .../rust/codegen/core/smithy/RuntimeType.kt | 66 ++++++- .../smithy/generators/BuilderGenerator.kt | 23 ++- .../core/smithy/generators/EnumGenerator.kt | 11 +- .../core/smithy/generators/Instantiator.kt | 15 +- .../core/smithy/generators/UnionGenerator.kt | 18 +- .../generators/error/ErrorImplGenerator.kt | 6 +- .../parse/EventStreamUnmarshallerGenerator.kt | 2 +- .../NamingObstacleCourseTestModels.kt | 172 ++++++++++++++++++ .../codegen/core/rustlang/RustTypeTest.kt | 24 +-- .../codegen/core/rustlang/RustWriterTest.kt | 4 +- .../codegen/core/rustlang/WritableTest.kt | 4 +- .../SmithyTypesPubUseExtraTest.kt | 20 +- .../server/python/smithy/PythonType.kt | 7 + .../PythonServerSymbolProviderTest.kt | 4 +- .../ConstrainedCollectionGenerator.kt | 2 +- .../ConstrainedTraitForEnumGenerator.kt | 6 +- .../smithy/generators/ServerEnumGenerator.kt | 9 +- .../server/smithy/NamingObstacleCourseTest.kt | 32 ++++ .../UnconstrainedShapeSymbolProviderTest.kt | 2 +- .../ConstrainedBlobGeneratorTest.kt | 4 +- .../ConstrainedCollectionGeneratorTest.kt | 4 +- .../generators/ConstrainedMapGeneratorTest.kt | 4 +- .../ConstrainedNumberGeneratorTest.kt | 2 +- .../ConstrainedStringGeneratorTest.kt | 4 +- 48 files changed, 619 insertions(+), 225 deletions(-) create mode 100644 codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/NamingObstacleCourseTest.kt 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/CHANGELOG.next.toml b/CHANGELOG.next.toml index 7267f1f4e3..06b3ab3d54 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -29,3 +29,9 @@ message = "Avoid extending IMDS credentials' expiry unconditionally, which may i references = ["smithy-rs#2687", "smithy-rs#2694"] meta = { "breaking" = false, "tada" = false, "bug" = true } author = "ysaito1001" + +[[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" 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..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 @@ -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/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..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 @@ -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}::Err> { + #{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 8a9ea8f765..d00af9b66b 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 @@ -65,6 +66,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"), @@ -90,17 +93,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 #{InterceptorRegistrar}) -> Result<(), #{BoxError}> { + fn configure(&self, cfg: &mut #{ConfigBag}, _interceptors: &mut #{InterceptorRegistrar}) -> #{Result}<(), #{BoxError}> { use #{ConfigBagAccessors}; // HACK: Put the handle into the config bag to work around config not being fully implemented yet @@ -112,7 +115,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())); @@ -123,9 +126,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-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-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-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..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 @@ -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,21 @@ fun > T.conditionalBlock( return this } +fun RustWriter.conditionalBlockTemplate( + textBeforeNewLine: String, + textAfterNewLine: String, + conditional: Boolean = true, + vararg args: Pair, + block: RustWriter.() -> Unit, +): RustWriter { + withTemplate(textBeforeNewLine.trim(), args) { beforeNewLine -> + withTemplate(textAfterNewLine.trim(), args) { afterNewLine -> + conditionalBlock(beforeNewLine, afterNewLine, conditional = conditional, block = block) + } + } + return this +} + /** * Convenience wrapper that tells Intellij that the contents of this block are Rust */ @@ -608,7 +624,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..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,14 +193,67 @@ 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. + * + * 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"), + "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, + + // 2021 Edition + "TryFrom" to std.resolve("convert::TryFrom"), + "TryInto" to std.resolve("convert::TryInto"), + "FromIterator" to std.resolve("iter::FromIterator"), + ) + } + // 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 +263,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..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, ) } @@ -295,7 +296,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..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 @@ -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 @@ -204,21 +205,23 @@ 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. - 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() """, 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-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/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 + } + } } } 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`() { 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/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()) { _, _ -> } + } +} 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