Skip to content

Commit fea6847

Browse files
Future-proof edition 2023 against feature value support windows.
This "feature" hasn't been implemented yet, but this puts a placeholder down to prevent compatibility issues in future editions. Once we provide versioning support on individual feature values, we don't want them becoming usable from edition 2023 protos PiperOrigin-RevId: 635609614
1 parent d2da463 commit fea6847

8 files changed

Lines changed: 368 additions & 137 deletions

File tree

src/google/protobuf/descriptor.pb.cc

Lines changed: 169 additions & 129 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/google/protobuf/descriptor.pb.h

Lines changed: 120 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/google/protobuf/descriptor.proto

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,9 @@ message EnumValueOptions {
859859
// credentials.
860860
optional bool debug_redact = 3 [default = false];
861861

862+
// Information about the support window of a feature value.
863+
optional FieldOptions.FeatureSupport feature_support = 4;
864+
862865
// The parser stores options it doesn't recognize here. See above.
863866
repeated UninterpretedOption uninterpreted_option = 999;
864867

src/google/protobuf/feature_resolver.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,22 @@ void CollectLifetimeResults(Edition edition, const Message& message,
293293
continue;
294294
}
295295

296+
if (field->enum_type() != nullptr) {
297+
int number = message.GetReflection()->GetEnumValue(message, field);
298+
auto value = field->enum_type()->FindValueByNumber(number);
299+
if (value != nullptr) {
300+
const FieldOptions::FeatureSupport& support =
301+
value->options().feature_support();
302+
if (value->options().has_feature_support() &&
303+
support.edition_introduced() > edition) {
304+
results.errors.emplace_back(
305+
absl::StrCat("Feature ", value->full_name(),
306+
" wasn't introduced until edition ",
307+
support.edition_introduced()));
308+
}
309+
}
310+
}
311+
296312
// Skip fields that don't have feature support specified.
297313
if (!field->options().has_feature_support()) continue;
298314

src/google/protobuf/feature_resolver_test.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,29 @@ TEST(FeatureResolverLifetimesTest, DynamicPool) {
657657
ElementsAre(HasSubstr("pb.TestFeatures.removed_feature")));
658658
}
659659

660+
TEST(FeatureResolverLifetimesTest, EmptyValueSupportInvalid2023) {
661+
FeatureSet features = ParseTextOrDie(R"pb(
662+
[pb.test] { file_feature: VALUE_EMPTY_SUPPORT }
663+
)pb");
664+
auto results = FeatureResolver::ValidateFeatureLifetimes(EDITION_2023,
665+
features, nullptr);
666+
EXPECT_THAT(results.errors, IsEmpty());
667+
EXPECT_THAT(results.warnings, IsEmpty());
668+
}
669+
670+
TEST(FeatureResolverLifetimesTest, ValueSupportInvalid2023) {
671+
FeatureSet features = ParseTextOrDie(R"pb(
672+
[pb.test] { file_feature: VALUE_FUTURE }
673+
)pb");
674+
auto results = FeatureResolver::ValidateFeatureLifetimes(EDITION_2023,
675+
features, nullptr);
676+
EXPECT_THAT(results.errors,
677+
ElementsAre(AllOf(
678+
HasSubstr("pb.VALUE_FUTURE"),
679+
HasSubstr("introduced until edition 99997_TEST_ONLY"))));
680+
EXPECT_THAT(results.warnings, IsEmpty());
681+
}
682+
660683
class FakeErrorCollector : public io::ErrorCollector {
661684
public:
662685
FakeErrorCollector() = default;

src/google/protobuf/unittest_features.proto

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ enum EnumFeature {
4343
VALUE13 = 13;
4444
VALUE14 = 14;
4545
VALUE15 = 15;
46+
VALUE_EMPTY_SUPPORT = 98 [feature_support = {}];
47+
VALUE_FUTURE = 99 [feature_support = {
48+
edition_introduced: EDITION_99997_TEST_ONLY
49+
edition_deprecated: EDITION_99998_TEST_ONLY
50+
deprecation_warning: "Custom feature deprecation warning"
51+
edition_removed: EDITION_99999_TEST_ONLY
52+
}];
4653
}
4754

4855
message TestFeatures {

upb/reflection/stage0/google/protobuf/descriptor.upb.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,13 @@ const upb_MiniTable* google__protobuf__EnumOptions_msg_init() {
273273

274274
const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init() {
275275
static upb_MiniTable* mini_table = NULL;
276-
static const char* mini_descriptor = "$P/3/c~G";
276+
static const char* mini_descriptor = "$P/3/3b~G";
277277
if (mini_table) return mini_table;
278278
mini_table =
279279
upb_MiniTable_Build(mini_descriptor, strlen(mini_descriptor),
280280
upb_BootstrapArena(), NULL);
281281
upb_MiniTable_SetSubMessage(mini_table, (upb_MiniTableField*)upb_MiniTable_FindFieldByNumber(mini_table, 2), google__protobuf__FeatureSet_msg_init());
282+
upb_MiniTable_SetSubMessage(mini_table, (upb_MiniTableField*)upb_MiniTable_FindFieldByNumber(mini_table, 4), google__protobuf__FieldOptions__FeatureSupport_msg_init());
282283
upb_MiniTable_SetSubMessage(mini_table, (upb_MiniTableField*)upb_MiniTable_FindFieldByNumber(mini_table, 999), google__protobuf__UninterpretedOption_msg_init());
283284
return mini_table;
284285
}

upb/reflection/stage0/google/protobuf/descriptor.upb.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4961,6 +4961,22 @@ UPB_INLINE bool google_protobuf_EnumValueOptions_has_debug_redact(const google_p
49614961
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 3);
49624962
return upb_Message_HasBaseField(UPB_UPCAST(msg), &field);
49634963
}
4964+
UPB_INLINE void google_protobuf_EnumValueOptions_clear_feature_support(google_protobuf_EnumValueOptions* msg) {
4965+
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 4);
4966+
upb_Message_ClearBaseField(UPB_UPCAST(msg), &field);
4967+
}
4968+
UPB_INLINE const google_protobuf_FieldOptions_FeatureSupport* google_protobuf_EnumValueOptions_feature_support(const google_protobuf_EnumValueOptions* msg) {
4969+
const google_protobuf_FieldOptions_FeatureSupport* default_val = NULL;
4970+
const google_protobuf_FieldOptions_FeatureSupport* ret;
4971+
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 4);
4972+
_upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field,
4973+
&default_val, &ret);
4974+
return ret;
4975+
}
4976+
UPB_INLINE bool google_protobuf_EnumValueOptions_has_feature_support(const google_protobuf_EnumValueOptions* msg) {
4977+
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 4);
4978+
return upb_Message_HasBaseField(UPB_UPCAST(msg), &field);
4979+
}
49644980
UPB_INLINE void google_protobuf_EnumValueOptions_clear_uninterpreted_option(google_protobuf_EnumValueOptions* msg) {
49654981
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 999);
49664982
upb_Message_ClearBaseField(UPB_UPCAST(msg), &field);
@@ -5014,6 +5030,18 @@ UPB_INLINE void google_protobuf_EnumValueOptions_set_debug_redact(google_protobu
50145030
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 3);
50155031
upb_Message_SetBaseField((upb_Message *)msg, &field, &value);
50165032
}
5033+
UPB_INLINE void google_protobuf_EnumValueOptions_set_feature_support(google_protobuf_EnumValueOptions *msg, google_protobuf_FieldOptions_FeatureSupport* value) {
5034+
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 4);
5035+
upb_Message_SetBaseField((upb_Message *)msg, &field, &value);
5036+
}
5037+
UPB_INLINE struct google_protobuf_FieldOptions_FeatureSupport* google_protobuf_EnumValueOptions_mutable_feature_support(google_protobuf_EnumValueOptions* msg, upb_Arena* arena) {
5038+
struct google_protobuf_FieldOptions_FeatureSupport* sub = (struct google_protobuf_FieldOptions_FeatureSupport*)google_protobuf_EnumValueOptions_feature_support(msg);
5039+
if (sub == NULL) {
5040+
sub = (struct google_protobuf_FieldOptions_FeatureSupport*)_upb_Message_New(google__protobuf__FieldOptions__FeatureSupport_msg_init(), arena);
5041+
if (sub) google_protobuf_EnumValueOptions_set_feature_support(msg, sub);
5042+
}
5043+
return sub;
5044+
}
50175045
UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions* msg, size_t* size) {
50185046
upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 999);
50195047
upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field);

0 commit comments

Comments
 (0)