reflect/protoreflect: add {Message,List,Map}.IsValid

Various protoreflect methods can return an "empty, read-only" message,
list, or map value. Provide a method to test if a value is one of these.

Fixes golang/protobuf#966

Change-Id: I793d8426d6e2201755983c06f024412a7e09bc4c
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/209018
Reviewed-by: Joe Tsai <joetsai@google.com>
diff --git a/internal/impl/convert_list.go b/internal/impl/convert_list.go
index d17676b..bec1d1d 100644
--- a/internal/impl/convert_list.go
+++ b/internal/impl/convert_list.go
@@ -125,6 +125,9 @@
 func (ls *listReflect) NewElement() pref.Value {
 	return ls.conv.New()
 }
+func (ls *listReflect) IsValid() bool {
+	return !ls.v.IsNil()
+}
 func (ls *listReflect) protoUnwrap() interface{} {
 	return ls.v.Interface()
 }
diff --git a/internal/impl/convert_map.go b/internal/impl/convert_map.go
index 2ddfc78..a05b131 100644
--- a/internal/impl/convert_map.go
+++ b/internal/impl/convert_map.go
@@ -102,6 +102,9 @@
 func (ms *mapReflect) NewValue() pref.Value {
 	return ms.valConv.New()
 }
+func (ms *mapReflect) IsValid() bool {
+	return !ms.v.IsNil()
+}
 func (ms *mapReflect) protoUnwrap() interface{} {
 	return ms.v.Interface()
 }
diff --git a/internal/impl/legacy_message.go b/internal/impl/legacy_message.go
index 3d0a921..1bded31 100644
--- a/internal/impl/legacy_message.go
+++ b/internal/impl/legacy_message.go
@@ -457,6 +457,12 @@
 func (m aberrantMessage) SetUnknown(pref.RawFields) {
 	// SetUnknown discards its input on messages which don't support unknown field storage.
 }
+func (m aberrantMessage) IsValid() bool {
+	// An invalid message is a read-only, empty message. Since we don't know anything
+	// about the alleged contents of this message, we can't say with confidence that
+	// it is invalid in this sense. Therefore, report it as valid.
+	return true
+}
 func (m aberrantMessage) ProtoMethods() *piface.Methods {
 	return legacyProtoMethods
 }
diff --git a/internal/impl/message_reflect_gen.go b/internal/impl/message_reflect_gen.go
index 1c56375..e894659 100644
--- a/internal/impl/message_reflect_gen.go
+++ b/internal/impl/message_reflect_gen.go
@@ -124,6 +124,9 @@
 	m.messageInfo().init()
 	m.messageInfo().setUnknown(m.pointer(), b)
 }
+func (m *messageState) IsValid() bool {
+	return m.pointer().IsNil()
+}
 
 func (m *messageReflectWrapper) Descriptor() protoreflect.MessageDescriptor {
 	return m.messageInfo().Desc
@@ -241,3 +244,6 @@
 	m.messageInfo().init()
 	m.messageInfo().setUnknown(m.pointer(), b)
 }
+func (m *messageReflectWrapper) IsValid() bool {
+	return m.pointer().IsNil()
+}