Internal change

PiperOrigin-RevId: 478049530
diff --git a/doc/domains-reference.md b/doc/domains-reference.md
index b36a039..edc3b4b 100644
--- a/doc/domains-reference.md
+++ b/doc/domains-reference.md
@@ -318,26 +318,8 @@
 You can customize the domain for a subset of fields, for example all fields with
 message type `Date`, or all fields with "amount" in the field's name.
 
-IMPORTANT: Note that customization options can conflict each other. For any
-proto field, when multiple customization calls apply to that field, only the
-first call will have an effect on the field.
-
-Consider the following for example:
-
-```c++
-.WithInt32Fields(Just(0)).WithInt32Filed("zipcode", Just(11111))
-```
-
-Here, all int32 fields will be set to zero for the former customization, because
-the first customization applies to all int32 fields. To set "zipcode" field, its
-customization should appear first:
-
-```c++
-.WithInt32Filed("zipcode", Just(11111)).WithInt32Fields(Just(0))
-```
-
-When called in the opposite order, "zipcode" field will be set to 11111 and all
-other int32 fields will be zero.
+IMPORTANT: Note that customization options can conflict each other. In case of
+conflicts the latter customization always overrides the former.
 
 **Customizing Multiple Fields With Same Type:** You can set the domain for a
 subset of fields with the same type using `With<Type>Fields`. By default this
@@ -380,12 +362,12 @@
 }
 FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto)
     .WithDomains(Arbitrary<Moving>()
-    // Balance field can be negative.
-    .WihtInt32Field("balance", Arbitrary<int>())
-    // All zipcode fields which should have 5 digits.
-    .WithInt32Fields(IsZipcode, InRange(10000, 99999))
-    // All other int fields should be positive.
+    // All int fields should be positive
     .WithInt32Fields(Positive<int>())
+    // except balance field which can be negative
+    .WihtInt32Field("balance", Arbitrary<int>())
+    // and except all zipcode fields which should have 5 digits
+    .WithInt32Fields(IsZipcode, InRange(10000, 99999))
     // All Timestamp fields should have "nanos" field unset.
     .WithProtobufFields(IsTimestamp, Arbitrary<Timestamp>().WithInt32FieldUnset("nanos")));
 ```
@@ -402,11 +384,14 @@
 }
 FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto).
   WithDomains(Arbitrary<MyProto>()
-      .WithInt32Field("foo", InRange(0, 10))
-      .WithOptionalFieldsUnset(IsProtoType)
-      // Other optional fields should be set. We don't override the nullness for
-      // "foo" (which can be unset or unset), and all proto fields.
+      // Always set optional fields
       .WithOptionalFieldsAlwaysSet()
+      // except fields that contain nested protos.
+      .WithOptionalFieldsUnset(IsProtoType)
+      // and except "foo" field. We override the nullness by using the
+      // WithInt32Filed (instead of WithInt32FieldAlwaysSet()), which will
+      // enable the fuzzer make this field both set and unset.
+      .WithInt32Field("foo", Arbitrary<int>())
   );
 ```
 
@@ -420,14 +405,13 @@
 }
 FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto).
   WithDomains(Arbitrary<MyProto>()
-    // "additional_info" can be empty or arbitrary large.
-    .WithInt32Field("additional_info", VectorOf(String()))
-    // Citizenship fields which can size at most 2.
-    .WithRepeatedFieldsMaxSize(IsCitizenship, 2)
-    // Other Repeated fields should have size in range 1-10. We don't override
-    // the size for "additional_info", and all citizenship fields.
+    // Repeated fields should have size in range 1-10
     .WithRepeatedFieldsMinSize(1)
     .WithRepeatedFieldsMaxSize(10)
+    // except citizenship fields which can size at most 2.
+    .WithRepeatedFieldsMaxSize(IsCitizenship, 2)
+    // and except "additional_info" field which can be empty or arbitrary large
+    .WithInt32Field("additional_info", VectorOf(String()).WithMinSize(0))
   );
 ```
 
diff --git a/e2e_tests/functional_test.cc b/e2e_tests/functional_test.cc
index d3247a6..dfe5a2e 100644
--- a/e2e_tests/functional_test.cc
+++ b/e2e_tests/functional_test.cc
@@ -436,18 +436,18 @@
 }
 
 TEST(UnitTestModeTest,
-     DefaultOptionalPolicyAppliesToAllOptionalFieldsWithoutExplicitDomain) {
-  auto [status, std_out, std_err] = RunWith(
-      GetGTestFilterFlag("MySuite."
-                         "FieldBIsAlwaysSetAndAllOtherOptionalFieldsAreUnset"));
+     DefaultOptionalPolicyAppliesToAllOptionalFieldsWithoutOverwrittenDomain) {
+  auto [status, std_out, std_err] = RunWith(GetGTestFilterFlag(
+      "MySuite."
+      "FailsWhenAnyOptionalFieldsHaveValueButNotFieldsWithOverwrittenDomain"));
   EXPECT_THAT(status.ExitCode(), Eq(0));
 }
 
 TEST(UnitTestModeTest,
-     DefaultOptionalPolicyAppliesToAllFieldsWithoutAnAlreadyDefinedPolicy) {
+     DefaultOptionalPolicyAppliesToAllOptionalFieldsWithoutOverwrittenPolicy) {
   auto [status, std_out, std_err] = RunWith(GetGTestFilterFlag(
       "MySuite."
-      "BoolFieldsAreAlwaysSetAndAllOtherOptionalFieldsAreUnset"));
+      "FailsWhenAnyOptionalFieldsHaveValueButNotFieldsWithOverwrittenPolicy"));
   EXPECT_THAT(status.ExitCode(), Eq(0));
 }
 
@@ -459,10 +459,10 @@
 }
 
 TEST(UnitTestModeTest,
-     AvoidsFailureIfByDefaultPolicyNotPropagatedOnRecursiveStructures) {
+     AvoidsFailureIfSetByDefaultPolicyIsOverwrittenOnRecursiveStructures) {
   auto [status, std_out, std_err] = RunWith(GetGTestFilterFlag(
       "MySuite."
-      "InitializesRecursiveProtoIfInfiniteRecursivePolicyStopsPropagating"));
+      "InitializesRecursiveProtoIfInfiniteRecursivePolicyIsOverwritten"));
   EXPECT_THAT(status.ExitCode(), Eq(0));
 }
 
@@ -492,8 +492,8 @@
 }
 
 TEST(UnitTestModeTest, PoliciesApplyToFieldsInOrder) {
-  auto [status, std_out, std_err] =
-      RunWith(GetGTestFilterFlag("MySuite.Int32FieldsRespectCustomizations"));
+  auto [status, std_out, std_err] = RunWith(GetGTestFilterFlag(
+      "MySuite.FailsWhenI32FieldValuesDontRespectAllPolicies"));
   EXPECT_THAT(status.ExitCode(), Eq(0));
 }
 
diff --git a/e2e_tests/testdata/fuzz_tests_for_functional_testing.cc b/e2e_tests/testdata/fuzz_tests_for_functional_testing.cc
index 255a03a..298bd19 100644
--- a/e2e_tests/testdata/fuzz_tests_for_functional_testing.cc
+++ b/e2e_tests/testdata/fuzz_tests_for_functional_testing.cc
@@ -218,34 +218,36 @@
 FUZZ_TEST(MySuite, FailsWhenAnyOptionalFieldsHaveValue)
     .WithDomains(Arbitrary<TestProtobuf>().WithOptionalFieldsUnset());
 
-void FieldBIsAlwaysSetAndAllOtherOptionalFieldsAreUnset(
+void FailsWhenAnyOptionalFieldsHaveValueButNotFieldsWithOverwrittenDomain(
     const TestProtobuf& proto) {
   if (!proto.has_b() || AnyNonBooleanOptionalFieldIsSet(proto)) {
     std::abort();
   }
 }
-FUZZ_TEST(MySuite, FieldBIsAlwaysSetAndAllOtherOptionalFieldsAreUnset)
+FUZZ_TEST(MySuite,
+          FailsWhenAnyOptionalFieldsHaveValueButNotFieldsWithOverwrittenDomain)
     .WithDomains(Arbitrary<TestProtobuf>()
-                     .WithBoolFieldAlwaysSet("b", Arbitrary<bool>())
-                     .WithOptionalFieldsUnset());
+                     .WithOptionalFieldsUnset()
+                     .WithBoolFieldAlwaysSet("b", Arbitrary<bool>()));
 
-void BoolFieldsAreAlwaysSetAndAllOtherOptionalFieldsAreUnset(
+void FailsWhenAnyOptionalFieldsHaveValueButNotFieldsWithOverwrittenPolicy(
     const TestProtobuf& proto) {
   if (!proto.has_b() || AnyNonBooleanOptionalFieldIsSet(proto)) {
     std::abort();
   }
 }
-FUZZ_TEST(MySuite, BoolFieldsAreAlwaysSetAndAllOtherOptionalFieldsAreUnset)
+FUZZ_TEST(MySuite,
+          FailsWhenAnyOptionalFieldsHaveValueButNotFieldsWithOverwrittenPolicy)
     .WithDomains(
         Arbitrary<TestProtobuf>()
-            .WithOptionalFieldsUnset([](const FieldDescriptor* field) {
-              return field->type() == FieldDescriptor::TYPE_INT32;
-            })
+            .WithOptionalFieldsUnset()
             .WithOptionalFieldsAlwaysSet([](const FieldDescriptor* field) {
               return field->type() == FieldDescriptor::TYPE_BOOL ||
                      field->type() == FieldDescriptor::TYPE_INT32;
             })
-            .WithOptionalFieldsUnset());
+            .WithOptionalFieldsUnset([](const FieldDescriptor* field) {
+              return field->type() == FieldDescriptor::TYPE_INT32;
+            }));
 
 bool IsTestSubProtobuf(const FieldDescriptor* field) {
   return field->message_type()->full_name() ==
@@ -275,7 +277,7 @@
     .WithDomains(Arbitrary<TestProtobuf>().WithProtobufFields(
         IsTestSubProtobuf, Arbitrary<TestProtobufWithRecursion>()));
 
-void Int32FieldsRespectCustomizations(const TestProtobuf& proto) {
+void FailsWhenI32FieldValuesDontRespectAllPolicies(const TestProtobuf& proto) {
   if (!proto.has_i32() || proto.i32() != 1) {
     std::abort();
   }
@@ -302,15 +304,15 @@
 }
 bool IsRepeated(const FieldDescriptor* field) { return field->is_repeated(); }
 
-FUZZ_TEST(MySuite, Int32FieldsRespectCustomizations)
+FUZZ_TEST(MySuite, FailsWhenI32FieldValuesDontRespectAllPolicies)
     .WithDomains(Arbitrary<TestProtobuf>()
-                     .WithInt32FieldAlwaysSet("i32", fuzztest::Just(1))
-                     .WithInt32Fields(IsRepeated, fuzztest::Just(2))
-                     .WithInt32Fields(IsNotRequired, fuzztest::Just(3))
+                     .WithOptionalFieldsAlwaysSet(IsInt32)
+                     .WithRepeatedFieldsMinSize(IsInt32, 1)
                      .WithRepeatedInt32Field(
                          "rep_i32", VectorOf(fuzztest::Just(4)).WithMinSize(1))
-                     .WithOptionalFieldsAlwaysSet(IsInt32)
-                     .WithRepeatedFieldsMinSize(IsInt32, 1));
+                     .WithInt32Fields(IsNotRequired, fuzztest::Just(3))
+                     .WithInt32Fields(IsRepeated, fuzztest::Just(2))
+                     .WithInt32FieldAlwaysSet("i32", fuzztest::Just(1)));
 
 void FailsIfCantInitializeProto(const TestProtobufWithRecursion& proto) {}
 FUZZ_TEST(MySuite, FailsIfCantInitializeProto)
@@ -318,16 +320,16 @@
                      .WithOptionalFieldsAlwaysSet()
                      .WithStringField("id", Arbitrary<std::string>()));
 
-void InitializesRecursiveProtoIfInfiniteRecursivePolicyStopsPropagating(
+void InitializesRecursiveProtoIfInfiniteRecursivePolicyIsOverwritten(
     const TestProtobufWithRecursion& proto) {}
 FUZZ_TEST(MySuite,
-          InitializesRecursiveProtoIfInfiniteRecursivePolicyStopsPropagating)
+          InitializesRecursiveProtoIfInfiniteRecursivePolicyIsOverwritten)
     .WithDomains(Arbitrary<TestProtobufWithRecursion>()
+                     .WithOptionalFieldsAlwaysSet()
                      .WithProtobufField(
                          "child",
                          Arbitrary<TestProtobufWithRecursion::ChildProto>()
-                             .WithStringField("id", Arbitrary<std::string>()))
-                     .WithOptionalFieldsAlwaysSet());
+                             .WithStringField("id", Arbitrary<std::string>())));
 
 bool AreRepeatedFieldsSizesCorrect(absl::FunctionRef<bool(int)> is_size_correct,
                                    const TestProtobuf& proto) {
@@ -384,9 +386,9 @@
 FUZZ_TEST(MySuite,
           FailsIfRepeatedEnumsHaveZeroValueAndOptionalEnumHasNonZeroValue)
     .WithDomains(Arbitrary<TestProtobuf>()
+                     .WithEnumFieldsTransformed(IgnoreZero)
                      .WithEnumField("e",
-                                    fuzztest::Just<int>(TestProtobuf::Label1))
-                     .WithEnumFieldsTransformed(IgnoreZero));
+                                    fuzztest::Just<int>(TestProtobuf::Label1)));
 
 void FailsIfProtobufEnumEqualsLabel4(TestProtobuf::Enum e) {
   if (e == TestProtobuf::Enum::TestProtobuf_Enum_Label4) {
diff --git a/fuzztest/internal/protobuf_domain.h b/fuzztest/internal/protobuf_domain.h
index b895ba6..e8fa640 100644
--- a/fuzztest/internal/protobuf_domain.h
+++ b/fuzztest/internal/protobuf_domain.h
@@ -199,7 +199,9 @@
   using Filter = std::function<bool(const FieldDescriptor*)>;
 
  public:
-  ProtoPolicy() {}
+  ProtoPolicy()
+      : optional_policies_({{.filter = IncludeAll<FieldDescriptor>(),
+                             .value = OptionalPolicy::kWithNull}}) {}
 
   ProtoPolicy GetChildrenPolicy() const {
     ProtoPolicy children_policy;
@@ -296,7 +298,7 @@
         "GetOptionalPolicy should apply to optional fields only!");
     std::optional<OptionalPolicy> result =
         GetPolicyValue(optional_policies_, field);
-    if (!result.has_value()) return OptionalPolicy::kWithNull;
+    FUZZTEST_INTERNAL_CHECK(result.has_value(), "optional policy is not set!");
     return *result;
   }
 
@@ -340,8 +342,8 @@
   std::optional<T> GetPolicyValue(
       const std::vector<FilterToValue<T>>& filter_to_values,
       const FieldDescriptor* field) const {
-    // Return the first policy that applies.
-    for (int i = 0; i < filter_to_values.size(); ++i) {
+    // Return the policy that is not overwritten.
+    for (int i = filter_to_values.size() - 1; i >= 0; --i) {
       if (!filter_to_values[i].filter(field)) continue;
       if constexpr (std::is_same_v<T, Domain<std::unique_ptr<Message>>>) {
         absl::BitGen gen;