cmd/protoc-gen-go: correlate v1 ExtensionDesc with v2 ExtensionType
Unfortunately a good amount of code uses pointer comparisons on the
v1 ExtensionDesc to determine exactly which extension field is set,
rather than checking whether the extension descriptor semantically
describes the field that they are interested in.
To preserve this behavior in v1, we need a 1:1 mapping between
a v2 ExtensionType and a specific v1 ExtensionDesc.
Change-Id: I852b3cefb4585bd656e48e5adad6cc28795d02df
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/167759
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/fileinit/desc.go b/internal/fileinit/desc.go
index 8c49f3c..550cae1 100644
--- a/internal/fileinit/desc.go
+++ b/internal/fileinit/desc.go
@@ -13,6 +13,7 @@
"reflect"
"sync"
+ papi "github.com/golang/protobuf/protoapi"
pragma "github.com/golang/protobuf/v2/internal/pragma"
ptype "github.com/golang/protobuf/v2/internal/prototype"
pfmt "github.com/golang/protobuf/v2/internal/typefmt"
@@ -95,6 +96,13 @@
// TODO: Provide a list of extension types for options extensions.
// OptionDependencies []pref.ExtensionType
+ // LegacyExtensions are a list of legacy extension descriptors.
+ // If provided, the pointer to the v1 ExtensionDesc will be stored into the
+ // associated v2 ExtensionType and accessible via a pseudo-internal API.
+ // Also, the v2 ExtensionType will be stored into each v1 ExtensionDesc.
+ // If non-nil, len(LegacyExtensions) must equal len(ExtensionOutputTypes).
+ LegacyExtensions []papi.ExtensionDesc
+
// EnumOutputTypes is where Init stores all initialized enum types
// in "flattened ordering".
EnumOutputTypes []pref.EnumType
@@ -116,6 +124,13 @@
func (fb FileBuilder) Init() pref.FileDescriptor {
fd := newFileDesc(fb)
+ if fb.LegacyExtensions != nil {
+ for i := range fd.allExtensions {
+ fd.allExtensions[i].legacyDesc = &fb.LegacyExtensions[i]
+ fb.LegacyExtensions[i].Type = &fd.allExtensions[i]
+ }
+ }
+
for i := range fd.allEnums {
fb.EnumOutputTypes[i] = &fd.allEnums[i]
}
@@ -341,6 +356,8 @@
number pref.FieldNumber
extendedType pref.MessageDescriptor
+ legacyDesc *papi.ExtensionDesc
+
lazy *extensionLazy // protected by fileDesc.once
}
extensionLazy struct {
@@ -397,6 +414,10 @@
return xd.lazy
}
+// ProtoLegacyExtensionDesc is a pseudo-internal API for allowing the v1 code
+// to be able to retrieve a v1 ExtensionDesc.
+func (xd *extensionDesc) ProtoLegacyExtensionDesc() *papi.ExtensionDesc { return xd.legacyDesc }
+
type (
serviceDesc struct {
baseDesc