Quellcode durchsuchen

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>
Joe Tsai vor 7 Jahren
Ursprung
Commit
22b1ebd068
2 geänderte Dateien mit 20 neuen und 14 gelöschten Zeilen
  1. 19 13
      internal/impl/message.go
  2. 1 1
      internal/legacy/extension.go

+ 19 - 13
internal/impl/message.go

@@ -145,7 +145,7 @@ func (mi *MessageType) makeExtensionFieldsFunc(t reflect.Type) {
 }
 
 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 @@ type messageDataType struct {
 	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 = (*messageReflectWrapper)(nil)
+
+type messageIfaceWrapper messageDataType
 
-var _ pvalue.Unwrapper = (*messageWrapper)(nil)
+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
 

+ 1 - 1
internal/legacy/extension.go

@@ -214,7 +214,7 @@ func extensionTypeOf(xd pref.ExtensionDescriptor, t reflect.Type) pref.Extension
 			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{} {