Skip to content

Commit

Permalink
Future-proof edition 2023 against feature value support windows.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mkruskal-google committed May 21, 2024
1 parent d2da463 commit fea6847
Show file tree
Hide file tree
Showing 8 changed files with 368 additions and 137 deletions.
298 changes: 169 additions & 129 deletions src/google/protobuf/descriptor.pb.cc

Large diffs are not rendered by default.

127 changes: 120 additions & 7 deletions src/google/protobuf/descriptor.pb.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/google/protobuf/descriptor.proto
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,9 @@ message EnumValueOptions {
// credentials.
optional bool debug_redact = 3 [default = false];

// Information about the support window of a feature value.
optional FieldOptions.FeatureSupport feature_support = 4;

// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;

Expand Down
16 changes: 16 additions & 0 deletions src/google/protobuf/feature_resolver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,22 @@ void CollectLifetimeResults(Edition edition, const Message& message,
continue;
}

if (field->enum_type() != nullptr) {
int number = message.GetReflection()->GetEnumValue(message, field);
auto value = field->enum_type()->FindValueByNumber(number);
if (value != nullptr) {
const FieldOptions::FeatureSupport& support =
value->options().feature_support();
if (value->options().has_feature_support() &&
support.edition_introduced() > edition) {
results.errors.emplace_back(
absl::StrCat("Feature ", value->full_name(),
" wasn't introduced until edition ",
support.edition_introduced()));
}
}
}

// Skip fields that don't have feature support specified.
if (!field->options().has_feature_support()) continue;

Expand Down
23 changes: 23 additions & 0 deletions src/google/protobuf/feature_resolver_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,29 @@ TEST(FeatureResolverLifetimesTest, DynamicPool) {
ElementsAre(HasSubstr("pb.TestFeatures.removed_feature")));
}

TEST(FeatureResolverLifetimesTest, EmptyValueSupportInvalid2023) {
FeatureSet features = ParseTextOrDie(R"pb(
[pb.test] { file_feature: VALUE_EMPTY_SUPPORT }
)pb");
auto results = FeatureResolver::ValidateFeatureLifetimes(EDITION_2023,
features, nullptr);
EXPECT_THAT(results.errors, IsEmpty());
EXPECT_THAT(results.warnings, IsEmpty());
}

TEST(FeatureResolverLifetimesTest, ValueSupportInvalid2023) {
FeatureSet features = ParseTextOrDie(R"pb(
[pb.test] { file_feature: VALUE_FUTURE }
)pb");
auto results = FeatureResolver::ValidateFeatureLifetimes(EDITION_2023,
features, nullptr);
EXPECT_THAT(results.errors,
ElementsAre(AllOf(
HasSubstr("pb.VALUE_FUTURE"),
HasSubstr("introduced until edition 99997_TEST_ONLY"))));
EXPECT_THAT(results.warnings, IsEmpty());
}

class FakeErrorCollector : public io::ErrorCollector {
public:
FakeErrorCollector() = default;
Expand Down
7 changes: 7 additions & 0 deletions src/google/protobuf/unittest_features.proto
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ enum EnumFeature {
VALUE13 = 13;
VALUE14 = 14;
VALUE15 = 15;
VALUE_EMPTY_SUPPORT = 98 [feature_support = {}];
VALUE_FUTURE = 99 [feature_support = {
edition_introduced: EDITION_99997_TEST_ONLY
edition_deprecated: EDITION_99998_TEST_ONLY
deprecation_warning: "Custom feature deprecation warning"
edition_removed: EDITION_99999_TEST_ONLY
}];
}

message TestFeatures {
Expand Down
3 changes: 2 additions & 1 deletion upb/reflection/stage0/google/protobuf/descriptor.upb.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,12 +273,13 @@ const upb_MiniTable* google__protobuf__EnumOptions_msg_init() {

const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init() {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$P/3/c~G";
static const char* mini_descriptor = "$P/3/3b~G";
if (mini_table) return mini_table;
mini_table =
upb_MiniTable_Build(mini_descriptor, strlen(mini_descriptor),
upb_BootstrapArena(), NULL);
upb_MiniTable_SetSubMessage(mini_table, (upb_MiniTableField*)upb_MiniTable_FindFieldByNumber(mini_table, 2), google__protobuf__FeatureSet_msg_init());
upb_MiniTable_SetSubMessage(mini_table, (upb_MiniTableField*)upb_MiniTable_FindFieldByNumber(mini_table, 4), google__protobuf__FieldOptions__FeatureSupport_msg_init());
upb_MiniTable_SetSubMessage(mini_table, (upb_MiniTableField*)upb_MiniTable_FindFieldByNumber(mini_table, 999), google__protobuf__UninterpretedOption_msg_init());
return mini_table;
}
Expand Down
28 changes: 28 additions & 0 deletions upb/reflection/stage0/google/protobuf/descriptor.upb.h
Original file line number Diff line number Diff line change
Expand Up @@ -4961,6 +4961,22 @@ UPB_INLINE bool google_protobuf_EnumValueOptions_has_debug_redact(const google_p
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 3);
return upb_Message_HasBaseField(UPB_UPCAST(msg), &field);
}
UPB_INLINE void google_protobuf_EnumValueOptions_clear_feature_support(google_protobuf_EnumValueOptions* msg) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 4);
upb_Message_ClearBaseField(UPB_UPCAST(msg), &field);
}
UPB_INLINE const google_protobuf_FieldOptions_FeatureSupport* google_protobuf_EnumValueOptions_feature_support(const google_protobuf_EnumValueOptions* msg) {
const google_protobuf_FieldOptions_FeatureSupport* default_val = NULL;
const google_protobuf_FieldOptions_FeatureSupport* ret;
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 4);
_upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field,
&default_val, &ret);
return ret;
}
UPB_INLINE bool google_protobuf_EnumValueOptions_has_feature_support(const google_protobuf_EnumValueOptions* msg) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 4);
return upb_Message_HasBaseField(UPB_UPCAST(msg), &field);
}
UPB_INLINE void google_protobuf_EnumValueOptions_clear_uninterpreted_option(google_protobuf_EnumValueOptions* msg) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 999);
upb_Message_ClearBaseField(UPB_UPCAST(msg), &field);
Expand Down Expand Up @@ -5014,6 +5030,18 @@ UPB_INLINE void google_protobuf_EnumValueOptions_set_debug_redact(google_protobu
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 3);
upb_Message_SetBaseField((upb_Message *)msg, &field, &value);
}
UPB_INLINE void google_protobuf_EnumValueOptions_set_feature_support(google_protobuf_EnumValueOptions *msg, google_protobuf_FieldOptions_FeatureSupport* value) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 4);
upb_Message_SetBaseField((upb_Message *)msg, &field, &value);
}
UPB_INLINE struct google_protobuf_FieldOptions_FeatureSupport* google_protobuf_EnumValueOptions_mutable_feature_support(google_protobuf_EnumValueOptions* msg, upb_Arena* arena) {
struct google_protobuf_FieldOptions_FeatureSupport* sub = (struct google_protobuf_FieldOptions_FeatureSupport*)google_protobuf_EnumValueOptions_feature_support(msg);
if (sub == NULL) {
sub = (struct google_protobuf_FieldOptions_FeatureSupport*)_upb_Message_New(google__protobuf__FieldOptions__FeatureSupport_msg_init(), arena);
if (sub) google_protobuf_EnumValueOptions_set_feature_support(msg, sub);
}
return sub;
}
UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions* msg, size_t* size) {
upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__EnumValueOptions_msg_init(), 999);
upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field);
Expand Down

0 comments on commit fea6847

Please sign in to comment.