Unverified Commit 040d0e42 authored by John DiSanti's avatar John DiSanti Committed by GitHub
Browse files

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._
parent 92b26df4
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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"
+5 −4
Original line number Diff line number Diff line
@@ -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<T, E>(self) -> Result<T, SdkError<E>>
            pub async fn send<T, E>(self) -> #{Result}<T, #{SdkError}<E>>
            where
                E: std::error::Error + Send + Sync + 'static,
                O: #{ParseHttpResponse}<Output = Result<T, E>> + Send + Sync + Clone + 'static,
                Retry: #{ClassifyRetry}<#{SdkSuccess}<T>, #{SdkError}<E>> + Send + Sync + Clone,
                E: std::error::Error + #{Send} + #{Sync} + 'static,
                O: #{ParseHttpResponse}<Output = #{Result}<T, E>> + #{Send} + #{Sync} + #{Clone} + 'static,
                Retry: #{ClassifyRetry}<#{SdkSuccess}<T>, #{SdkError}<E>> + #{Send} + #{Sync} + #{Clone},
            {
                self.handle.client.call(self.operation).await
            }
+2 −1
Original line number Diff line number Diff line
@@ -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,
+2 −1
Original line number Diff line number Diff line
@@ -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(
+7 −1
Original line number Diff line number Diff line
@@ -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)
        )
    }
}
Loading