internal/impl: split messageWrapper into different types

The previous implementation of messageWrapper implemented both
proto.Message and protoreflect.Message. This made it possible for users
to accidentally rely on this fact when it was actually an internal
implementation detail.

To avoid this, we split the wrapper type into two, ensuring that each
only implements one or the other. Doing so also revealed bugs in our
own code where we accidentally relied on this fact.

Change-Id: I0ff521b5c806b7dcb0b86942bd97e8319d8e8657
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/166938
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/impl/message.go b/internal/impl/message.go
index cf627df..dbf9816 100644
--- a/internal/impl/message.go
+++ b/internal/impl/message.go
@@ -145,7 +145,7 @@
 }
 
 func (mi *MessageType) MessageOf(p interface{}) pref.Message {
-	return (*messageWrapper)(mi.dataTypeOf(p))
+	return (*messageReflectWrapper)(mi.dataTypeOf(p))
 }
 
 func (mi *MessageType) dataTypeOf(p interface{}) *messageDataType {
@@ -182,34 +182,40 @@
 	mi *MessageType
 }
 
-type messageWrapper messageDataType
+type messageReflectWrapper messageDataType
 
-func (m *messageWrapper) Type() pref.MessageType {
+func (m *messageReflectWrapper) Type() pref.MessageType {
 	return m.mi.PBType
 }
-func (m *messageWrapper) KnownFields() pref.KnownFields {
+func (m *messageReflectWrapper) KnownFields() pref.KnownFields {
 	m.mi.init()
 	return (*knownFields)(m)
 }
-func (m *messageWrapper) UnknownFields() pref.UnknownFields {
+func (m *messageReflectWrapper) UnknownFields() pref.UnknownFields {
 	m.mi.init()
 	return m.mi.unknownFields((*messageDataType)(m))
 }
-func (m *messageWrapper) Interface() pref.ProtoMessage {
+func (m *messageReflectWrapper) Interface() pref.ProtoMessage {
 	if m, ok := m.ProtoUnwrap().(pref.ProtoMessage); ok {
 		return m
 	}
-	return m
+	return (*messageIfaceWrapper)(m)
 }
-func (m *messageWrapper) ProtoReflect() pref.Message {
-	return m
-}
-func (m *messageWrapper) ProtoUnwrap() interface{} {
+func (m *messageReflectWrapper) ProtoUnwrap() interface{} {
 	return m.p.AsIfaceOf(m.mi.GoType.Elem())
 }
-func (m *messageWrapper) ProtoMutable() {}
+func (m *messageReflectWrapper) ProtoMutable() {}
 
-var _ pvalue.Unwrapper = (*messageWrapper)(nil)
+var _ pvalue.Unwrapper = (*messageReflectWrapper)(nil)
+
+type messageIfaceWrapper messageDataType
+
+func (m *messageIfaceWrapper) ProtoReflect() pref.Message {
+	return (*messageReflectWrapper)(m)
+}
+func (m *messageIfaceWrapper) ProtoUnwrap() interface{} {
+	return m.p.AsIfaceOf(m.mi.GoType.Elem())
+}
 
 type knownFields messageDataType
 
diff --git a/internal/legacy/extension.go b/internal/legacy/extension.go
index 00db9ba..357dcb3 100644
--- a/internal/legacy/extension.go
+++ b/internal/legacy/extension.go
@@ -214,7 +214,7 @@
 			if xd.Kind() == pref.EnumKind {
 				return xt.ValueOf(Export{}.EnumOf(v))
 			} else {
-				return xt.ValueOf(Export{}.MessageOf(v))
+				return xt.ValueOf(Export{}.MessageOf(v).Interface())
 			}
 		}
 		xt2.interfaceOf = func(v pref.Value) interface{} {