Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Produce &[T] instead of Option<&[T]> for list fields #2995

Merged
merged 6 commits into from
Sep 28, 2023
Merged

Conversation

rcoh
Copy link
Collaborator

@rcoh rcoh commented Sep 21, 2023

Motivation and Context

When the returned field is a list, there is almost never a reason to know if the returned value was null or [] — this addresses the 99% case.

Before:

fn blah(&self) -> Option<&[T]> { self.blah.as_deref() }

After:

fn blah(&self) -> &[T] { self.blah.as_deref().unwrap_or_default() }

note: no impact on servers by default, see codegen diff.

Description

Update accessors for lists.

Testing

  • codegen diff audit (no server changes)
  • unit tests

Checklist

  • I have updated CHANGELOG.next.toml if I made changes to the smithy-rs codegen or runtime crates
  • I have updated CHANGELOG.next.toml if I made changes to the AWS SDK, generated SDK code, or SDK 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.

@rcoh rcoh requested review from a team as code owners September 21, 2023 16:59
@github-actions
Copy link

@rcoh rcoh force-pushed the auto-unwrap-or-default branch from 3af0d0c to 3a4e5f5 Compare September 21, 2023 18:25
@github-actions
Copy link

This improves API ergonomics when the output is a list
@github-actions
Copy link

@rcoh rcoh force-pushed the auto-unwrap-or-default branch from 91ae6e7 to 46631d7 Compare September 21, 2023 20:21
@github-actions
Copy link

@rcoh rcoh force-pushed the auto-unwrap-or-default branch from 46631d7 to ada8fcb Compare September 22, 2023 15:47
@rcoh rcoh added the breaking-change This will require a breaking change label Sep 22, 2023
@github-actions
Copy link

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@rcoh rcoh requested review from a team as code owners September 22, 2023 18:31
@rcoh rcoh requested a review from unexge September 22, 2023 18:31
@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@@ -22,6 +22,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider
import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderCustomization
import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderGenerator
import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderSection
import software.amazon.smithy.rust.codegen.core.smithy.generators.StructSettings
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: which namespace do the rest of the settings lie in? For example, we don't have a software.amazon.smithy.rust.codegen.core.smithy.generators.settings namespace?

@@ -194,7 +195,7 @@ fun StructureShape.renderWithModelBuilder(
) {
val struct = this
rustCrate.withModule(symbolProvider.moduleForShape(struct)) {
StructureGenerator(model, symbolProvider, this, struct, emptyList()).render()
StructureGenerator(model, symbolProvider, this, struct, emptyList(), StructSettings(true)).render()
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have a test someplace for StructSettings(false)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

actually no! let me add one, good catch. (Although all existing server tests are testing this)


fun fromNode(node: Optional<ObjectNode>): CoreCodegenConfig =
if (node.isPresent) {
CoreCodegenConfig(
formatTimeoutSeconds = node.get().getNumberMemberOrDefault("formatTimeoutSeconds", defaultFormatTimeoutSeconds).toInt(),
debugMode = node.get().getBooleanMemberOrDefault("debugMode", defaultDebugMode),
flattenCollectionAccessors = node.get().getBooleanMemberOrDefault("flattenCollectionAccessors", defaultFlattenMode),
Copy link
Contributor

Choose a reason for hiding this comment

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

Will this change allow someone on the server side to override how we generate accessor methods for collection types by setting "flattenCollectionAccessor" in smithy-build.json?

If the user cannot set this in the settings, then disregard the following:

Currently, on the server side that behavior is controlled by whether the field is marked as @required in the model.

This approach is fine for optional server inputs, where not sending a value for a collection (resulting in None) and sending an empty collection are treated the same by the business logic. However, there are scenarios where the server's output could make a meaningful distinction between an empty list and a None list. Additionally, using $memberName.is_none() on the client side to check whether the server sent an output will be unreliable if the server sends an empty list instead of None.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this is only the accessor method—it has absolutely no impact on serialization, it's just for convenience when reading the field.

Additionally, using $memberName.is_none() on the client side to check whether the server sent an output will be unreliable if the server sends an empty list instead of None.

The only reason to do that is explicitly if you are trying to tell the difference.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh yes! only the accessor gets changed. The underlying serialization format and the field remains the same.

@@ -294,6 +294,7 @@ open class ServerCodegenVisitor(
this,
shape,
codegenDecorator.structureCustomizations(codegenContext, emptyList()),
structSettings = codegenContext.structSettings(),
Copy link
Contributor

Choose a reason for hiding this comment

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

If there is no chance for the user to set this flag on the server side then this is okay. Otherwise, I think let's set this to: StructSettings(flattenVecAccessors = false) for now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Disregard. Only the accessor is getting changed so let's keep it the way you have it right now.

@@ -40,7 +40,7 @@ class PythonServerStructureGenerator(
private val codegenContext: ServerCodegenContext,
private val writer: RustWriter,
private val shape: StructureShape,
) : StructureGenerator(model, codegenContext.symbolProvider, writer, shape, emptyList()) {
) : StructureGenerator(model, codegenContext.symbolProvider, writer, shape, emptyList(), codegenContext.structSettings()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

If there is no chance for the user to set this flag on the server side then this is okay. Otherwise, I think let's set this to: StructSettings(flattenVecAccessors = false) for now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

a customer can set this on the server side with the smithy-build.json setting

Copy link
Contributor

Choose a reason for hiding this comment

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

Keep it like it is. I wrongly thought that the underlying field is also going to get changed. Only the accessor gets changed, so this is good.

@rcoh rcoh added this pull request to the merge queue Sep 28, 2023
Merged via the queue into main with commit aaf71c8 Sep 28, 2023
40 of 41 checks passed
@rcoh rcoh deleted the auto-unwrap-or-default branch September 28, 2023 16:23
DavidSouther added a commit to DavidSouther/aws-doc-sdk-examples that referenced this pull request Sep 28, 2023
DavidSouther added a commit to DavidSouther/aws-doc-sdk-examples that referenced this pull request Sep 29, 2023
Switch to sdk branch = next
Handle nullability change for smithy-lang/smithy-rs#2916
Handle nullability change for smithy-lang/smithy-rs#2995
DavidSouther added a commit to DavidSouther/aws-doc-sdk-examples that referenced this pull request Sep 29, 2023
Switch to sdk branch = next
Handle nullability change for smithy-lang/smithy-rs#2916
Handle nullability change for smithy-lang/smithy-rs#2995
DavidSouther added a commit to DavidSouther/aws-doc-sdk-examples that referenced this pull request Sep 29, 2023
Switch to sdk branch = next
Handle nullability change for smithy-lang/smithy-rs#2916
Handle nullability change for smithy-lang/smithy-rs#2995
meyertst-aws pushed a commit to DavidSouther/aws-doc-sdk-examples that referenced this pull request Sep 29, 2023
Switch to sdk branch = next
Handle nullability change for smithy-lang/smithy-rs#2916
Handle nullability change for smithy-lang/smithy-rs#2995
DavidSouther added a commit to DavidSouther/aws-doc-sdk-examples that referenced this pull request Oct 3, 2023
Switch to sdk branch = next
Handle nullability change for smithy-lang/smithy-rs#2916
Handle nullability change for smithy-lang/smithy-rs#2995
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking-change This will require a breaking change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants