cmd/protoc-gen-go: centralize presence and lazy logic into filedesc

With this change, the generator and runtime use the same logic
to decide whether a presence bitmap entry is necessary,
instead of two (possibly diverging) copies of the logic.

I have verified Google-internally that sharing the logic
yields exactly the same results as the old logic on all our .protos
(see Google-internal CL 755276656 for details).

Change-Id: I21ed069b7efbc8114b23331b441e35ce86e5d38a
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/670516
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Lasse Folger <lassefolger@google.com>
diff --git a/cmd/protoc-gen-go/internal_gengo/opaque.go b/cmd/protoc-gen-go/internal_gengo/opaque.go
index 999a251..45749ed 100644
--- a/cmd/protoc-gen-go/internal_gengo/opaque.go
+++ b/cmd/protoc-gen-go/internal_gengo/opaque.go
@@ -11,6 +11,7 @@
 	"unicode/utf8"
 
 	"google.golang.org/protobuf/compiler/protogen"
+	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/internal/genid"
 	"google.golang.org/protobuf/reflect/protoreflect"
 
@@ -279,8 +280,7 @@
 	}
 
 	// Was the field marked as [lazy = true] in the .proto file?
-	fopts := field.Desc.Options().(*descriptorpb.FieldOptions)
-	return fopts.GetLazy()
+	return field.Desc.(interface{ IsLazy() bool }).IsLazy()
 }
 
 // opaqueGenGet generates a Get method for a field.
@@ -573,16 +573,8 @@
 	if !message.isOpaque() {
 		return false
 	}
-	return opaqueFieldNeedsPresenceArray(message, field)
-}
-
-func opaqueFieldNeedsPresenceArray(message *messageInfo, field *protogen.Field) bool {
-	// Non optional fields need presence if truly lazy field, i.e. are message fields.
-	if isLazy(field) {
-		return true
-	}
-	isNotOneof := field.Desc.ContainingOneof() == nil || field.Desc.ContainingOneof().IsSynthetic()
-	return field.Desc.HasPresence() && field.Message == nil && isNotOneof
+	usePresence, _ := filedesc.UsePresenceForField(field.Desc)
+	return usePresence
 }
 
 // opaqueGenHas generates a Has method for a field.
@@ -832,7 +824,7 @@
 		return false
 	}
 	for _, field := range message.Fields {
-		if opaqueFieldNeedsPresenceArray(message, field) {
+		if usePresence, _ := filedesc.UsePresenceForField(field.Desc); usePresence {
 			return true
 		}
 	}