Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .changelog/hints-mostly-unused.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
applies_to:
- aws-sdk-rust
- client
authors:
- landonxjames
references:
- smithy-rs#4208
breaking: false
new_feature: true
bug_fix: false
---
Add the ability to insert `hints.mostly-unused = true` in Cargo.toml. Enable this hint for the below crates:
- aws-sd-cloudformation
- aws-sdk-dynamodb
- aws-sdk-ec2
- aws-sdk-s3
- aws-sdk-sns
- aws-sdk-sqs
- aws-sdk-ssm
- aws-sdk-sts

See more information about this hint at https://blog.rust-lang.org/inside-rust/2025/07/15/call-for-testing-hint-mostly-unused/
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package software.amazon.smithy.rustsdk

import software.amazon.smithy.rust.codegen.client.smithy.customizations.DocsRsMetadataDecorator
import software.amazon.smithy.rust.codegen.client.smithy.customizations.DocsRsMetadataSettings
import software.amazon.smithy.rust.codegen.client.smithy.customizations.ManifestHintsDecorator
import software.amazon.smithy.rust.codegen.client.smithy.customizations.ManifestHintsSettings
import software.amazon.smithy.rust.codegen.client.smithy.customize.ClientCodegenDecorator
import software.amazon.smithy.rust.codegen.client.smithy.customize.CombinedClientCodegenDecorator
import software.amazon.smithy.rustsdk.customize.AwsDisableStalledStreamProtection
Expand All @@ -22,6 +24,7 @@ import software.amazon.smithy.rustsdk.customize.dsql.DsqlDecorator
import software.amazon.smithy.rustsdk.customize.ec2.Ec2Decorator
import software.amazon.smithy.rustsdk.customize.glacier.GlacierDecorator
import software.amazon.smithy.rustsdk.customize.onlyApplyTo
import software.amazon.smithy.rustsdk.customize.onlyApplyToList
import software.amazon.smithy.rustsdk.customize.rds.RdsDecorator
import software.amazon.smithy.rustsdk.customize.route53.Route53Decorator
import software.amazon.smithy.rustsdk.customize.s3.S3Decorator
Expand Down Expand Up @@ -109,6 +112,18 @@ val DECORATORS: List<ClientCodegenDecorator> =
),
),
),
ManifestHintsDecorator(ManifestHintsSettings(mostlyUnused = true)).onlyApplyToList(
listOf(
"com.amazonaws.cloudformation#CloudFormation",
"com.amazonaws.dynamodb#DynamoDB_20120810",
"com.amazonaws.ec2#AmazonEC2",
"com.amazonaws.s3#AmazonS3",
"com.amazonaws.sns#AmazonSimpleNotificationService",
"com.amazonaws.sqs#AmazonSQS",
"com.amazonaws.ssm#AmazonSSM",
"com.amazonaws.sts#AWSSecurityTokenServiceV20110615",
),
),
).flatten()

class AwsCodegenDecorator : CombinedClientCodegenDecorator(DECORATORS) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ fun ClientCodegenDecorator.onlyApplyTo(serviceId: String): List<ClientCodegenDec
},
)

/** Only apply this decorator to the given list of service IDs */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't end up needing this after I moved the service list to gradle.properties, but seemed like it could be a useful utility in the future, so I left it.

fun ClientCodegenDecorator.onlyApplyToList(serviceIds: List<String>): List<ClientCodegenDecorator> =
serviceIds.map {
ConditionalDecorator(this) { _, serviceShapeId ->
serviceShapeId == ShapeId.from(it)
}
}

/** Apply this decorator to all services but the one identified by ID */
fun ClientCodegenDecorator.applyExceptFor(serviceId: String): List<ClientCodegenDecorator> =
listOf(
Expand Down
4 changes: 2 additions & 2 deletions aws/sdk/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -494,8 +494,8 @@ fun Project.registerDowngradeFor(
val crateNameToLastKnownWorkingVersions =
mapOf(
"minicbor" to "0.24.2",
"libfuzzer-sys" to "0.4.7" // TODO(https://github.com/rust-fuzz/libfuzzer/issues/126)
)
"libfuzzer-sys" to "0.4.7", // TODO(https://github.com/rust-fuzz/libfuzzer/issues/126)
)

crateNameToLastKnownWorkingVersions.forEach { (crate, version) ->
// doesn't matter even if the specified crate does not exist in the lockfile
Expand Down
10 changes: 9 additions & 1 deletion aws/sdk/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,13 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
#

aws.services=
aws.services.hints.mostlyUnused=\
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably want to remove this.

aws-sd-cloudformation,\
aws-sdk-dynamodb,\
aws-sdk-ec2,\
aws-sdk-s3,\
aws-sdk-sns,\
aws-sdk-sqs,\
aws-sdk-ssm,\
aws-sdk-sts
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,29 @@ data class ClientCodegenConfig(
) = if (node.isPresent) {
ClientCodegenConfig(
formatTimeoutSeconds = coreCodegenConfig.formatTimeoutSeconds,
flattenCollectionAccessors = node.get().getBooleanMemberOrDefault("flattenCollectionAccessors", DEFAULT_FLATTEN_ACCESSORS),
flattenCollectionAccessors =
node.get()
.getBooleanMemberOrDefault("flattenCollectionAccessors", DEFAULT_FLATTEN_ACCESSORS),
debugMode = coreCodegenConfig.debugMode,
renameExceptions = node.get().getBooleanMemberOrDefault("renameErrors", DEFAULT_RENAME_EXCEPTIONS),
includeFluentClient = node.get().getBooleanMemberOrDefault("includeFluentClient", DEFAULT_INCLUDE_FLUENT_CLIENT),
addMessageToErrors = node.get().getBooleanMemberOrDefault("addMessageToErrors", DEFAULT_ADD_MESSAGE_TO_ERRORS),
includeEndpointUrlConfig = node.get().getBooleanMemberOrDefault("includeEndpointUrlConfig", DEFAULT_INCLUDE_ENDPOINT_URL_CONFIG),
enableUserConfigurableRuntimePlugins = node.get().getBooleanMemberOrDefault("enableUserConfigurableRuntimePlugins", DEFAULT_ENABLE_USER_CONFIGURABLE_RUNTIME_PLUGINS),
nullabilityCheckMode = NullableIndex.CheckMode.valueOf(node.get().getStringMemberOrDefault("nullabilityCheckMode", DEFAULT_NULLABILITY_CHECK_MODE)),
includeFluentClient =
node.get()
.getBooleanMemberOrDefault("includeFluentClient", DEFAULT_INCLUDE_FLUENT_CLIENT),
addMessageToErrors =
node.get()
.getBooleanMemberOrDefault("addMessageToErrors", DEFAULT_ADD_MESSAGE_TO_ERRORS),
includeEndpointUrlConfig =
node.get()
.getBooleanMemberOrDefault("includeEndpointUrlConfig", DEFAULT_INCLUDE_ENDPOINT_URL_CONFIG),
enableUserConfigurableRuntimePlugins =
node.get().getBooleanMemberOrDefault(
"enableUserConfigurableRuntimePlugins",
DEFAULT_ENABLE_USER_CONFIGURABLE_RUNTIME_PLUGINS,
),
nullabilityCheckMode =
NullableIndex.CheckMode.valueOf(
node.get().getStringMemberOrDefault("nullabilityCheckMode", DEFAULT_NULLABILITY_CHECK_MODE),
),
)
} else {
ClientCodegenConfig(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.rust.codegen.client.smithy.customizations

import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext
import software.amazon.smithy.rust.codegen.client.smithy.customize.ClientCodegenDecorator
import software.amazon.smithy.rust.codegen.core.smithy.generators.ManifestCustomizations

/**
* See https://blog.rust-lang.org/inside-rust/2025/07/15/call-for-testing-hint-mostly-unused/ for more information
*/
data class ManifestHintsSettings(
val mostlyUnused: Boolean? = null,
)

fun ManifestHintsSettings.asMap(): Map<String, Any> {
val inner =
listOfNotNull(
mostlyUnused?.let { "mostly-unused" to it },
).toMap()
return mapOf("hints" to inner)
}

/**
* Write compilation hints metdata settings into Cargo.toml.
*
* # Notes
* This decorator is not used by default, code generators must manually configure and include it in their builds.
*/
class ManifestHintsDecorator(private val manifestHintsSettings: ManifestHintsSettings) : ClientCodegenDecorator {
override val name: String = "ManifestHintsDecorator"
override val order: Byte = 0

override fun crateManifestCustomizations(codegenContext: ClientCodegenContext): ManifestCustomizations {
return manifestHintsSettings.asMap()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,13 @@ open class CoreCodegenConfig(
fun fromNode(node: Optional<ObjectNode>): CoreCodegenConfig =
if (node.isPresent) {
CoreCodegenConfig(
formatTimeoutSeconds = node.get().getNumberMemberOrDefault("formatTimeoutSeconds", DEFAULT_FORMAT_TIMEOUT_SECONDS).toInt(),
formatTimeoutSeconds =
node.get()
.getNumberMemberOrDefault("formatTimeoutSeconds", DEFAULT_FORMAT_TIMEOUT_SECONDS).toInt(),
debugMode = node.get().getBooleanMemberOrDefault("debugMode", DEFAULT_DEBUG_MODE),
flattenCollectionAccessors = node.get().getBooleanMemberOrDefault("flattenCollectionAccessors", DEFAULT_FLATTEN_MODE),
flattenCollectionAccessors =
node.get()
.getBooleanMemberOrDefault("flattenCollectionAccessors", DEFAULT_FLATTEN_MODE),
)
} else {
CoreCodegenConfig(
Expand Down Expand Up @@ -123,12 +127,14 @@ open class CoreRustSettings(
"contain any service shapes",
)
}

services.size > 1 -> {
throw CodegenException(
"Cannot infer service to generate because the model contains " +
"multiple service shapes: " + services,
)
}

else -> {
val service = services[0]
LOGGER.info("Inferring service to generate as: $service")
Expand Down
Loading