Repository: smithy-lang/smithy
Pull request #2436 (2024-10-30 22:48:50)

Return Builders instead of SmithyBuilders
This commit updates all instances where a generic SmithyBuilder<> was returned to return the specific implementing Builder. This means users of these methods can easily use the Builder's functionality without using a cast.

---
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.



Patch:
diff --git a/smithy-aws-cloudformation-traits/src/main/java/software/amazon/smithy/aws/cloudformation/traits/CfnResourceTrait.java b/smithy-aws-cloudformation-traits/src/main/java/software/amazon/smithy/aws/cloudformation/traits/CfnResourceTrait.java
index f950c2752..75a2d48b1 100644
--- a/smithy-aws-cloudformation-traits/src/main/java/software/amazon/smithy/aws/cloudformation/traits/CfnResourceTrait.java
+++ b/smithy-aws-cloudformation-traits/src/main/java/software/amazon/smithy/aws/cloudformation/traits/CfnResourceTrait.java
@@ -25,7 +25,6 @@ import software.amazon.smithy.model.traits.AbstractTrait;
 import software.amazon.smithy.model.traits.AbstractTraitBuilder;
 import software.amazon.smithy.model.traits.Trait;
 import software.amazon.smithy.utils.ListUtils;
-import software.amazon.smithy.utils.SmithyBuilder;
 import software.amazon.smithy.utils.ToSmithyBuilder;
 
 /**
@@ -75,7 +74,7 @@ public final class CfnResourceTrait extends AbstractTrait
     }
 
     @Override
-    public SmithyBuilder<CfnResourceTrait> toBuilder() {
+    public Builder toBuilder() {
         return builder().sourceLocation(getSourceLocation()).name(name).additionalSchemas(additionalSchemas);
     }
 
diff --git a/smithy-aws-cloudformation/src/main/java/software/amazon/smithy/aws/cloudformation/schema/model/Handler.java b/smithy-aws-cloudformation/src/main/java/software/amazon/smithy/aws/cloudformation/schema/model/Handler.java
index e6262733f..9c1e6fe6b 100644
--- a/smithy-aws-cloudformation/src/main/java/software/amazon/smithy/aws/cloudformation/schema/model/Handler.java
+++ b/smithy-aws-cloudformation/src/main/java/software/amazon/smithy/aws/cloudformation/schema/model/Handler.java
@@ -61,7 +61,7 @@ public final class Handler implements ToNode, ToSmithyBuilder<Handler> {
     }
 
     @Override
-    public SmithyBuilder<Handler> toBuilder() {
+    public Builder toBuilder() {
         return builder()
                 .permissions(permissions);
     }
diff --git a/smithy-aws-cloudformation/src/main/java/software/amazon/smithy/aws/cloudformation/schema/model/Property.java b/smithy-aws-cloudformation/src/main/java/software/amazon/smithy/aws/cloudformation/schema/model/Property.java
index 0fe013bd9..61ccade1e 100644
--- a/smithy-aws-cloudformation/src/main/java/software/amazon/smithy/aws/cloudformation/schema/model/Property.java
+++ b/smithy-aws-cloudformation/src/main/java/software/amazon/smithy/aws/cloudformation/schema/model/Property.java
@@ -62,7 +62,7 @@ public final class Property implements ToNode, ToSmithyBuilder<Property> {
     }
 
     @Override
-    public SmithyBuilder<Property> toBuilder() {
+    public Builder toBuilder() {
         return builder()
                 .insertionOrder(insertionOrder)
                 .dependencies(dependencies)
diff --git a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/language/functions/partition/Partition.java b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/language/functions/partition/Partition.java
index f0af599a7..163913310 100644
--- a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/language/functions/partition/Partition.java
+++ b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/language/functions/partition/Partition.java
@@ -16,7 +16,6 @@ import software.amazon.smithy.model.node.ToNode;
 import software.amazon.smithy.rulesengine.language.RulesComponentBuilder;
 import software.amazon.smithy.utils.BuilderRef;
 import software.amazon.smithy.utils.ListUtils;
-import software.amazon.smithy.utils.SmithyBuilder;
 import software.amazon.smithy.utils.SmithyUnstableApi;
 import software.amazon.smithy.utils.ToSmithyBuilder;
 
@@ -117,7 +116,7 @@ public final class Partition implements ToSmithyBuilder<Partition>, FromSourceLo
     }
 
     @Override
-    public SmithyBuilder<Partition> toBuilder() {
+    public Builder toBuilder() {
         return new Builder(getSourceLocation())
                 .id(id)
                 .regionRegex(regionRegex)
diff --git a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/language/functions/partition/PartitionOutputs.java b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/language/functions/partition/PartitionOutputs.java
index 821f4da1d..7896ab6e0 100644
--- a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/language/functions/partition/PartitionOutputs.java
+++ b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/language/functions/partition/PartitionOutputs.java
@@ -15,7 +15,6 @@ import software.amazon.smithy.model.node.ObjectNode;
 import software.amazon.smithy.model.node.ToNode;
 import software.amazon.smithy.rulesengine.language.RulesComponentBuilder;
 import software.amazon.smithy.utils.ListUtils;
-import software.amazon.smithy.utils.SmithyBuilder;
 import software.amazon.smithy.utils.SmithyUnstableApi;
 import software.amazon.smithy.utils.ToSmithyBuilder;
 
@@ -142,7 +141,7 @@ public final class PartitionOutputs implements ToSmithyBuilder<PartitionOutputs>
     }
 
     @Override
-    public SmithyBuilder<PartitionOutputs> toBuilder() {
+    public Builder toBuilder() {
         return new Builder(getSourceLocation())
                 .name(name)
                 .dnsSuffix(dnsSuffix)
diff --git a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/language/functions/partition/RegionOverride.java b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/language/functions/partition/RegionOverride.java
index 1fe3d4209..8cb4cf572 100644
--- a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/language/functions/partition/RegionOverride.java
+++ b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/language/functions/partition/RegionOverride.java
@@ -10,7 +10,6 @@ import software.amazon.smithy.model.SourceLocation;
 import software.amazon.smithy.model.node.Node;
 import software.amazon.smithy.model.node.ToNode;
 import software.amazon.smithy.rulesengine.language.RulesComponentBuilder;
-import software.amazon.smithy.utils.SmithyBuilder;
 import software.amazon.smithy.utils.SmithyUnstableApi;
 import software.amazon.smithy.utils.ToSmithyBuilder;
 
@@ -54,7 +53,7 @@ public final class RegionOverride implements ToSmithyBuilder<RegionOverride>, Fr
     }
 
     @Override
-    public SmithyBuilder<RegionOverride> toBuilder() {
+    public Builder toBuilder() {
         return new Builder(getSourceLocation());
     }
 
diff --git a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/PartitionEndpointSpecialCase.java b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/PartitionEndpointSpecialCase.java
index 3adaefb13..530ff50a7 100644
--- a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/PartitionEndpointSpecialCase.java
+++ b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/PartitionEndpointSpecialCase.java
@@ -86,7 +86,7 @@ public final class PartitionEndpointSpecialCase
     }
 
     @Override
-    public SmithyBuilder<PartitionEndpointSpecialCase> toBuilder() {
+    public Builder toBuilder() {
         return new Builder()
             .endpoint(endpoint)
             .region(region)
diff --git a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/PartitionSpecialCase.java b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/PartitionSpecialCase.java
index 1dc0c9a83..2fa7c5988 100644
--- a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/PartitionSpecialCase.java
+++ b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/PartitionSpecialCase.java
@@ -72,7 +72,7 @@ public final class PartitionSpecialCase implements FromSourceLocation, ToNode, T
     }
 
     @Override
-    public SmithyBuilder<PartitionSpecialCase> toBuilder() {
+    public Builder toBuilder() {
         return new Builder()
             .dualStack(dualStack)
             .endpoint(endpoint)
diff --git a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/RegionSpecialCase.java b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/RegionSpecialCase.java
index 742c551ff..d075e2135 100644
--- a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/RegionSpecialCase.java
+++ b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/RegionSpecialCase.java
@@ -83,7 +83,7 @@ public final class RegionSpecialCase implements FromSourceLocation, ToNode, ToSm
     }
 
     @Override
-    public SmithyBuilder<RegionSpecialCase> toBuilder() {
+    public Builder toBuilder() {
         return new Builder()
             .dualStack(dualStack)
             .endpoint(endpoint)
diff --git a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/StandardPartitionalEndpointsTrait.java b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/StandardPartitionalEndpointsTrait.java
index d20319f89..558aae739 100644
--- a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/StandardPartitionalEndpointsTrait.java
+++ b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/StandardPartitionalEndpointsTrait.java
@@ -17,7 +17,6 @@ import software.amazon.smithy.model.traits.AbstractTrait;
 import software.amazon.smithy.model.traits.AbstractTraitBuilder;
 import software.amazon.smithy.model.traits.Trait;
 import software.amazon.smithy.utils.BuilderRef;
-import software.amazon.smithy.utils.SmithyBuilder;
 import software.amazon.smithy.utils.ToSmithyBuilder;
 
 /**
@@ -78,7 +77,7 @@ public final class StandardPartitionalEndpointsTrait extends AbstractTrait
     }
 
     @Override
-    public SmithyBuilder<StandardPartitionalEndpointsTrait> toBuilder() {
+    public Builder toBuilder() {
         return new Builder()
                 .partitionEndpointSpecialCases(partitionEndpointSpecialCases)
                 .endpointPatternType(endpointPatternType);
diff --git a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/StandardRegionalEndpointsTrait.java b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/StandardRegionalEndpointsTrait.java
index 52d9b5dd1..50cbabe55 100644
--- a/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/StandardRegionalEndpointsTrait.java
+++ b/smithy-aws-endpoints/src/main/java/software/amazon/smithy/rulesengine/aws/traits/StandardRegionalEndpointsTrait.java
@@ -16,7 +16,6 @@ import software.amazon.smithy.model.traits.AbstractTrait;
 import software.amazon.smithy.model.traits.AbstractTraitBuilder;
 import software.amazon.smithy.model.traits.Trait;
 import software.amazon.smithy.utils.BuilderRef;
-import software.amazon.smithy.utils.SmithyBuilder;
 import software.amazon.smithy.utils.ToSmithyBuilder;
 
 /**
@@ -84,7 +83,7 @@ public final class StandardRegionalEndpointsTrait extends AbstractTrait
     }
 
     @Override
-    public SmithyBuilder<StandardRegionalEndpointsTrait> toBuilder() {
+    public Builder toBuilder() {
         return new Builder()
                 .partitionSpecialCases(partitionSpecialCases)
                 .regionSpecialCases(regionSpecialCases);
diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/HttpChecksumTrait.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/HttpChecksumTrait.java
index 679792d5c..e53456ec4 100644
--- a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/HttpChecksumTrait.java
+++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/HttpChecksumTrait.java
@@ -27,7 +27,6 @@ import software.amazon.smithy.model.traits.AbstractTraitBuilder;
 import software.amazon.smithy.model.traits.Trait;
 import software.amazon.smithy.utils.BuilderRef;
 import software.amazon.smithy.utils.ListUtils;
-import software.amazon.smithy.utils.SmithyBuilder;
 import software.amazon.smithy.utils.SmithyUnstableApi;
 import software.amazon.smithy.utils.ToSmithyBuilder;
 
@@ -66,7 +65,7 @@ public final class HttpChecksumTrait extends AbstractTrait implements ToSmithyBu
     }
 
     @Override
-    public SmithyBuilder<HttpChecksumTrait> toBuilder() {
+    public Builder toBuilder() {
         return new Builder()
                 .sourceLocation(getSourceLocation())
                 .requestChecksumRequired(requestChecksumRequired)
diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/clientendpointdiscovery/ClientDiscoveredEndpointTrait.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/clientendpointdiscovery/ClientDiscoveredEndpointTrait.java
index b2d671840..97b649d5d 100644
--- a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/clientendpointdiscovery/ClientDiscoveredEndpointTrait.java
+++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/clientendpointdiscovery/ClientDiscoveredEndpointTrait.java
@@ -20,7 +20,6 @@ import software.amazon.smithy.model.node.ObjectNode;
 import software.amazon.smithy.model.shapes.ShapeId;
 import software.amazon.smithy.model.traits.AbstractTrait;
 import software.amazon.smithy.model.traits.AbstractTraitBuilder;
-import software.amazon.smithy.utils.SmithyBuilder;
 import software.amazon.smithy.utils.ToSmithyBuilder;
 
 /**
@@ -63,7 +62,7 @@ public final class ClientDiscoveredEndpointTrait extends AbstractTrait
     }
 
     @Override
-    public SmithyBuilder<ClientDiscoveredEndpointTrait> toBuilder() {
+    public Builder toBuilder() {
         return builder().sourceLocation(getSourceLocation()).required(required);
     }
 
diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsQueryErrorTrait.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsQueryErrorTrait.java
index 1f4430656..7fed70d1a 100644
--- a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsQueryErrorTrait.java
+++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/AwsQueryErrorTrait.java
@@ -74,7 +74,7 @@ public final class AwsQueryErrorTrait extends AbstractTrait implements ToSmithyB
     }
 
     @Override
-    public SmithyBuilder<AwsQueryErrorTrait> toBuilder() {
+    public Builder toBuilder() {
         return builder().code(code).httpResponseCode(httpResponseCode).sourceLocation(getSourceLocation());
     }
 
diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/node/ArrayNode.java b/smithy-model/src/main/java/software/amazon/smithy/model/node/ArrayNode.java
index cbc2ad79e..66eaad8c8 100644
--- a/smithy-model/src/main/java/software/amazon/smithy/model/node/ArrayNode.java
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/node/ArrayNode.java
@@ -73,7 +73,7 @@ public final class ArrayNode extends Node implements Iterable<Node>, ToSmithyBui
     }
 
     @Override
-    public SmithyBuilder<ArrayNode> toBuilder() {
+    public Builder toBuilder() {
         return new Builder().sourceLocation(getSourceLocation()).merge(this);
     }
 
diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/EnumValueTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/EnumValueTrait.java
index 5a8517814..8d4cc498d 100644
--- a/smithy-model/src/main/java/software/amazon/smithy/model/traits/EnumValueTrait.java
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/EnumValueTrait.java
@@ -21,7 +21,6 @@ import software.amazon.smithy.model.node.Node;
 import software.amazon.smithy.model.node.NumberNode;
 import software.amazon.smithy.model.node.StringNode;
 import software.amazon.smithy.model.shapes.ShapeId;
-import software.amazon.smithy.utils.SmithyBuilder;
 import software.amazon.smithy.utils.ToSmithyBuilder;
 
 /**
@@ -101,7 +100,7 @@ public final class EnumValueTrait extends AbstractTrait implements ToSmithyBuild
     }
 
     @Override
-    public SmithyBuilder<EnumValueTrait> toBuilder() {
+    public Builder toBuilder() {
         Builder builder = builder().sourceLocation(getSourceLocation());
         builder.value = value;
         return builder;
diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/ExamplesTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/ExamplesTrait.java
index 486c51fcd..d5d9103f2 100644
--- a/smithy-model/src/main/java/software/amazon/smithy/model/traits/ExamplesTrait.java
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/ExamplesTrait.java
@@ -310,7 +310,7 @@ public final class ExamplesTrait extends AbstractTrait implements ToSmithyBuilde
         }
 
         @Override
-        public SmithyBuilder<ErrorExample> toBuilder() {
+        public Builder toBuilder() {
             return builder().content(content).shapeId(shapeId);
         }
 
diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/RequestCompressionTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/RequestCompressionTrait.java
index c8c70c0c7..67e8d0165 100644
--- a/smithy-model/src/main/java/software/amazon/smithy/model/traits/RequestCompressionTrait.java
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/RequestCompressionTrait.java
@@ -23,7 +23,6 @@ import software.amazon.smithy.model.node.StringNode;
 import software.amazon.smithy.model.shapes.ShapeId;
 import software.amazon.smithy.utils.BuilderRef;
 import software.amazon.smithy.utils.SetUtils;
-import software.amazon.smithy.utils.SmithyBuilder;
 import software.amazon.smithy.utils.ToSmithyBuilder;
 
 /**
@@ -85,7 +84,7 @@ public final class RequestCompressionTrait extends AbstractTrait implements ToSm
     }
 
     @Override
-    public SmithyBuilder<RequestCompressionTrait> toBuilder() {
+    public Builder toBuilder() {
         return new Builder()
                 .sourceLocation(getSourceLocation())
                 .encodings(encodings);
diff --git a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/ExpectedEndpoint.java b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/ExpectedEndpoint.java
index 5c6f80c28..baca5f3e6 100644
--- a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/ExpectedEndpoint.java
+++ b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/ExpectedEndpoint.java
@@ -56,7 +56,7 @@ public final class ExpectedEndpoint implements FromSourceLocation, ToSmithyBuild
     }
 
     @Override
-    public SmithyBuilder<ExpectedEndpoint> toBuilder() {
+    public Builder toBuilder() {
         return builder()
                 .sourceLocation(sourceLocation)
                 .url(url)
diff --git a/smithy-waiters/src/main/java/software/amazon/smithy/waiters/WaitableTrait.java b/smithy-waiters/src/main/java/software/amazon/smithy/waiters/WaitableTrait.java
index 8138f85f7..21c0b3937 100644
--- a/smithy-waiters/src/main/java/software/amazon/smithy/waiters/WaitableTrait.java
+++ b/smithy-waiters/src/main/java/software/amazon/smithy/waiters/WaitableTrait.java
@@ -24,7 +24,6 @@ import software.amazon.smithy.model.traits.AbstractTraitBuilder;
 import software.amazon.smithy.model.traits.Trait;
 import software.amazon.smithy.model.traits.TraitService;
 import software.amazon.smithy.utils.BuilderRef;
-import software.amazon.smithy.utils.SmithyBuilder;
 import software.amazon.smithy.utils.ToSmithyBuilder;
 
 /**
@@ -47,7 +46,7 @@ public final class WaitableTrait extends AbstractTrait implements ToSmithyBuilde
     }
 
     @Override
-    public SmithyBuilder<WaitableTrait> toBuilder() {
+    public Builder toBuilder() {
         return new Builder().sourceLocation(getSourceLocation()).replace(waiters);
     }
 
diff --git a/smithy-waiters/src/main/java/software/amazon/smithy/waiters/Waiter.java b/smithy-waiters/src/main/java/software/amazon/smithy/waiters/Waiter.java
index 0564bbbd1..ae928c48d 100644
--- a/smithy-waiters/src/main/java/software/amazon/smithy/waiters/Waiter.java
+++ b/smithy-waiters/src/main/java/software/amazon/smithy/waiters/Waiter.java
@@ -69,7 +69,7 @@ public final class Waiter implements Tagged, ToNode, ToSmithyBuilder<Waiter> {
     }
 
     @Override
-    public SmithyBuilder<Waiter> toBuilder() {
+    public Builder toBuilder() {
         return builder()
                 .documentation(getDocumentation().orElse(null))
                 .acceptors(getAcceptors())


Test patch:
diff --git a/smithy-aws-protocol-tests/model/restJson1/http-headers.smithy b/smithy-aws-protocol-tests/model/restJson1/http-headers.smithy
index 78fd9c909..2b5115004 100644
--- a/smithy-aws-protocol-tests/model/restJson1/http-headers.smithy
+++ b/smithy-aws-protocol-tests/model/restJson1/http-headers.smithy
@@ -412,7 +412,7 @@ structure InputAndOutputWithHeadersIO {
     headerIntegerEnumList: IntegerEnumList,
 }
 
-/// Null and empty headers are not sent over the wire.
+/// Null headers are not sent over the wire, empty headers are serialized to ""
 @readonly
 @http(uri: "/NullAndEmptyHeadersClient", method: "GET")
 @tags(["client-only"])
@@ -443,7 +443,7 @@ apply NullAndEmptyHeadersClient @httpRequestTests([
     },
 ])
 
-/// Null and empty headers are not sent over the wire.
+/// Null headers are not sent over the wire, empty headers are serialized to ""
 @readonly
 @http(uri: "/NullAndEmptyHeadersServer", method: "GET")
 @tags(["server-only"])
@@ -455,10 +455,14 @@ operation NullAndEmptyHeadersServer {
 apply NullAndEmptyHeadersServer @httpResponseTests([
     {
         id: "RestJsonNullAndEmptyHeaders",
-        documentation: "Do not send null or empty headers",
+        documentation: "Do not send null values, but do send empty strings and empty lists over the wire in headers",
         protocol: restJson1,
         code: 200,
-        forbidHeaders: ["X-A", "X-B", "X-C"],
+        forbidHeaders: ["X-A"],
+        headers: {
+            "X-B": ""
+            "X-C": ""
+        }
         params: {
             a: null,
             b: "",
diff --git a/smithy-aws-protocol-tests/model/restXml/http-headers.smithy b/smithy-aws-protocol-tests/model/restXml/http-headers.smithy
index 2bf49ffc9..6fc91964d 100644
--- a/smithy-aws-protocol-tests/model/restXml/http-headers.smithy
+++ b/smithy-aws-protocol-tests/model/restXml/http-headers.smithy
@@ -355,7 +355,7 @@ structure InputAndOutputWithHeadersIO {
     headerEnumList: FooEnumList,
 }
 
-/// Null and empty headers are not sent over the wire.
+/// Null headers are not sent over the wire, empty headers are serialized to ""
 @readonly
 @http(uri: "/NullAndEmptyHeadersClient", method: "GET")
 @tags(["client-only"])
@@ -386,7 +386,7 @@ apply NullAndEmptyHeadersClient @httpRequestTests([
     },
 ])
 
-/// Null and empty headers are not sent over the wire.
+/// Null headers are not sent over the wire, empty headers are serialized to ""
 @readonly
 @http(uri: "/NullAndEmptyHeadersServer", method: "GET")
 @tags(["server-only"])
@@ -398,10 +398,14 @@ operation NullAndEmptyHeadersServer {
 apply NullAndEmptyHeadersServer @httpResponseTests([
     {
         id: "NullAndEmptyHeaders",
-        documentation: "Do not send null or empty headers",
+        documentation: "Do not send null values, but do send empty strings and empty lists over the wire in headers",
         protocol: restXml,
         code: 200,
-        forbidHeaders: ["X-A", "X-B", "X-C"],
+        forbidHeaders: ["X-A"],
+        headers: {
+            "X-B": ""
+            "X-C": ""
+        }
         body: "",
         params: {
             a: null,
diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/node/NodeMapperTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/node/NodeMapperTest.java
index d1d15729b..66a731648 100644
--- a/smithy-model/src/test/java/software/amazon/smithy/model/node/NodeMapperTest.java
+++ b/smithy-model/src/test/java/software/amazon/smithy/model/node/NodeMapperTest.java
@@ -1351,7 +1351,7 @@ public class NodeMapperTest {
         }
 
         @Override
-        public SmithyBuilder<SourceLocationBearerTrait> toBuilder() {
+        public Builder toBuilder() {
             return new Builder().sourceLocation(getSourceLocation());
         }
 
diff --git a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/EndpointTestOperationInput.java b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/EndpointTestOperationInput.java
index 906268a84..e7edcc58e 100644
--- a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/EndpointTestOperationInput.java
+++ b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/EndpointTestOperationInput.java
@@ -79,7 +79,7 @@ public final class EndpointTestOperationInput implements FromSourceLocation,
     }
 
     @Override
-    public SmithyBuilder<EndpointTestOperationInput> toBuilder() {
+    public Builder toBuilder() {
         return builder()
                 .sourceLocation(sourceLocation)
                 .operationName(operationName)