proto: add MessageName helper

The MessageName returns the full name of a message.
It is a shorthand for:

	var name protoreflect.FullName
	if m != nil {
		name = m.ProtoReflect().Descriptor().FullName()

Generally, we avoid the addition of helper functions unless
their use is justified. Arguments for this helper:

• The legacy proto.MessageName is widely used.
  For example, inside Google, there are thousands of usages of it.
  It is commonly used in logging and error construction to
  report the name of a protobuf message.

• The fact that a nil-check may be neccessary means that users
  either forget the nil-check and risk a nil-panic in production code,
  or users have to write cumbersome logic to check for it.

  For example, compare use with the helper:
      return fmt.Errorf("invalid message type: %v", proto.MessageName(m))
  to use without the helper:
      var messageName protoreflect.FullName
      if m != nil {
          messageName = m.ProtoReflect().Descriptor().FullName()
      return fmt.Errorf("invalid message type: %v", messageName)

A point of consideration is whether this should return a string
or a protoreflect.FullName. This CL returns the latter type:

• Most uses of it are for logging via log.Printf or error construction
  via fmt.Errorf where it does not matter what the exact string type is
  since its formatted the same way.

• Another use of it is to check for message type equality by doing
  something similar to:
      if proto.MessageName(got) != proto.MessageName(want) {
  in which case it still does not matter what the exact string type is.

• The other major use of proto.MessageName is to call proto APIs
  that actually do expect a protoreflect.FullName
  (e.g., protoregistry.GlobalTypes.FindExtensionByNumber) where
  the user currently type-casts the legacy proto.MessageName
  to a protoreflect.FullName anyways.

As such, there does not seem to be much justified use for MessageName
as a string. The rare cases that need a string can trivially type cast
it to a string.

Change-Id: I840758df828eef72e7e63620569363a496366afa
Reviewed-by: Damien Neil <>
diff --git a/proto/proto.go b/proto/proto.go
index ca14b09..1f0d183 100644
--- a/proto/proto.go
+++ b/proto/proto.go
@@ -32,3 +32,12 @@
 func init() {
 	Error = errors.Error
+// MessageName returns the full name of m.
+// If m is nil, it returns an empty string.
+func MessageName(m Message) protoreflect.FullName {
+	if m == nil {
+		return ""
+	}
+	return m.ProtoReflect().Descriptor().FullName()