internal/impl: handle irregular messages implementing proto.Message

When encountering a type that does not have a MessageInfo, don't assume
that it's a legacy message that doesn't implement proto.Message. Add a
set of test messages exercising this case (panics prior to the
internal/impl change).

Change-Id: Ic1ec5ecfbe92278fbef44284ff52a0e0622a158c
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/182477
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/internal/impl/encode_field.go b/internal/impl/encode_field.go
index 53a8eda..a6580ce 100644
--- a/internal/impl/encode_field.go
+++ b/internal/impl/encode_field.go
@@ -82,11 +82,11 @@
 	} else {
 		return pointerCoderFuncs{
 			size: func(p pointer, tagsize int, opts marshalOptions) int {
-				m := legacyWrapMessage(p.AsValueOf(ft).Elem())
+				m := asMessage(p.AsValueOf(ft).Elem())
 				return sizeMessage(m, tagsize, opts)
 			},
 			marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
-				m := legacyWrapMessage(p.AsValueOf(ft).Elem())
+				m := asMessage(p.AsValueOf(ft).Elem())
 				return appendMessage(b, m, wiretag, opts)
 			},
 		}
@@ -141,11 +141,11 @@
 	} else {
 		return pointerCoderFuncs{
 			size: func(p pointer, tagsize int, opts marshalOptions) int {
-				m := legacyWrapMessage(p.AsValueOf(ft).Elem())
+				m := asMessage(p.AsValueOf(ft).Elem())
 				return sizeGroup(m, tagsize, opts)
 			},
 			marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
-				m := legacyWrapMessage(p.AsValueOf(ft).Elem())
+				m := asMessage(p.AsValueOf(ft).Elem())
 				return appendGroup(b, m, wiretag, opts)
 			},
 		}
@@ -492,3 +492,10 @@
 	size:    sizeStringIfaceValidateUTF8,
 	marshal: appendStringIfaceValidateUTF8,
 }
+
+func asMessage(v reflect.Value) pref.ProtoMessage {
+	if m, ok := v.Interface().(pref.ProtoMessage); ok {
+		return m
+	}
+	return legacyWrapMessage(v)
+}