reflect/protoreflect: add Descriptor specific methods

Added methods:
	Enum.Descriptor
	Message.Descriptor
	EnumType.Descriptor
	MessageType.Descriptor
	ExtensionType.Descriptor
	Message.New

All functionality is switched over to use those methods instead of
implicitly relying on the fact that {Enum,Message}Type implicitly
implement the associated descriptor interface.

This CL does not yet remove {Enum,Message}.Type or prevent
{Enum,Message,Extension}Type from implementating a descriptor.
That is a subsequent CL.

The Message.New method is also added to replace functionality
that will be lost when the Type methods are removed.

Change-Id: I7fefde1673bbd40bfdac489aca05cec9a6c98eb1
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/174918
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Herbie Ong <herbie@google.com>
diff --git a/encoding/jsonpb/decode.go b/encoding/jsonpb/decode.go
index 0a08e4f..7e142c5 100644
--- a/encoding/jsonpb/decode.go
+++ b/encoding/jsonpb/decode.go
@@ -135,7 +135,7 @@
 func (o UnmarshalOptions) unmarshalMessage(m pref.Message, skipTypeURL bool) error {
 	var nerr errors.NonFatal
 
-	if isCustomType(m.Type().FullName()) {
+	if isCustomType(m.Descriptor().FullName()) {
 		return o.unmarshalCustomType(m)
 	}
 
@@ -160,9 +160,9 @@
 	var seenNums set.Ints
 	var seenOneofs set.Ints
 
-	msgType := m.Type()
+	messageDesc := m.Descriptor()
 	knownFields := m.KnownFields()
-	fieldDescs := msgType.Fields()
+	fieldDescs := messageDesc.Fields()
 	xtTypes := knownFields.ExtensionTypes()
 
 Loop:
@@ -208,7 +208,9 @@
 					xtTypes.Register(xt)
 				}
 			}
-			fd = xt
+			if xt != nil {
+				fd = xt.Descriptor()
+			}
 		} else {
 			// The name can either be the JSON name or the proto field name.
 			fd = fieldDescs.ByJSONName(name)
@@ -225,13 +227,13 @@
 				}
 				continue
 			}
-			return newError("%v contains unknown field %s", msgType.FullName(), jval)
+			return newError("%v contains unknown field %s", messageDesc.FullName(), jval)
 		}
 
 		// Do not allow duplicate fields.
 		num := uint64(fd.Number())
 		if seenNums.Has(num) {
-			return newError("%v contains repeated field %s", msgType.FullName(), jval)
+			return newError("%v contains repeated field %s", messageDesc.FullName(), jval)
 		}
 		seenNums.Set(num)
 
diff --git a/encoding/jsonpb/decode_test.go b/encoding/jsonpb/decode_test.go
index 8f92209..05e619d 100644
--- a/encoding/jsonpb/decode_test.go
+++ b/encoding/jsonpb/decode_test.go
@@ -13,6 +13,7 @@
 	"github.com/golang/protobuf/v2/encoding/jsonpb"
 	"github.com/golang/protobuf/v2/encoding/testprotos/pb2"
 	"github.com/golang/protobuf/v2/encoding/testprotos/pb3"
+	pimpl "github.com/golang/protobuf/v2/internal/impl"
 	"github.com/golang/protobuf/v2/internal/scalar"
 	"github.com/golang/protobuf/v2/proto"
 	preg "github.com/golang/protobuf/v2/reflect/protoregistry"
@@ -1976,7 +1977,7 @@
 	}, {
 		desc: "Any with non-custom message",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2005,7 +2006,7 @@
 	}, {
 		desc: "Any with empty embedded message",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText:    `{"@type": "foo/pb2.Nested"}`,
@@ -2019,7 +2020,7 @@
 	}, {
 		desc: "Any with missing required error",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&pb2.PartialRequired{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2038,7 +2039,7 @@
 				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
 			}
 			return &knownpb.Any{
-				TypeUrl: string(m.ProtoReflect().Type().FullName()),
+				TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
 				Value:   b,
 			}
 		}(),
@@ -2047,7 +2048,7 @@
 		desc: "Any with partial required and AllowPartial",
 		umo: jsonpb.UnmarshalOptions{
 			AllowPartial: true,
-			Resolver:     preg.NewTypes((&pb2.PartialRequired{}).ProtoReflect().Type()),
+			Resolver:     preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2066,14 +2067,14 @@
 				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
 			}
 			return &knownpb.Any{
-				TypeUrl: string(m.ProtoReflect().Type().FullName()),
+				TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
 				Value:   b,
 			}
 		}(),
 	}, {
 		desc: "Any with invalid UTF8",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2097,7 +2098,7 @@
 	}, {
 		desc: "Any with BoolValue",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.BoolValue{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.BoolValue{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2118,7 +2119,7 @@
 	}, {
 		desc: "Any with Empty",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Empty{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Empty{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2131,7 +2132,7 @@
 	}, {
 		desc: "Any with missing Empty",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Empty{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Empty{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2141,7 +2142,7 @@
 	}, {
 		desc: "Any with StringValue containing invalid UTF8",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.StringValue{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.StringValue{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2163,7 +2164,7 @@
 	}, {
 		desc: "Any with Int64Value",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Int64Value{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Int64Value{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2184,7 +2185,7 @@
 	}, {
 		desc: "Any with invalid Int64Value",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Int64Value{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Int64Value{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2195,7 +2196,7 @@
 	}, {
 		desc: "Any with invalid UInt64Value",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.UInt64Value{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.UInt64Value{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2206,7 +2207,7 @@
 	}, {
 		desc: "Any with Duration",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Duration{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Duration{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2227,7 +2228,7 @@
 	}, {
 		desc: "Any with Value of StringValue",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Value{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Value{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2249,7 +2250,7 @@
 	}, {
 		desc: "Any with Value of NullValue",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Value{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Value{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2271,11 +2272,11 @@
 		desc: "Any with Struct",
 		umo: jsonpb.UnmarshalOptions{
 			Resolver: preg.NewTypes(
-				(&knownpb.Struct{}).ProtoReflect().Type(),
-				(&knownpb.Value{}).ProtoReflect().Type(),
-				(&knownpb.BoolValue{}).ProtoReflect().Type(),
-				knownpb.NullValue_NULL_VALUE.Type(),
-				(&knownpb.StringValue{}).ProtoReflect().Type(),
+				pimpl.Export{}.MessageTypeOf(&knownpb.Struct{}),
+				pimpl.Export{}.MessageTypeOf(&knownpb.Value{}),
+				pimpl.Export{}.MessageTypeOf(&knownpb.BoolValue{}),
+				pimpl.Export{}.EnumTypeOf(knownpb.NullValue_NULL_VALUE),
+				pimpl.Export{}.MessageTypeOf(&knownpb.StringValue{}),
 			),
 		},
 		inputMessage: &knownpb.Any{},
@@ -2335,8 +2336,8 @@
 		desc: "Any with duplicate @type",
 		umo: jsonpb.UnmarshalOptions{
 			Resolver: preg.NewTypes(
-				(&pb2.Nested{}).ProtoReflect().Type(),
-				(&knownpb.StringValue{}).ProtoReflect().Type(),
+				pimpl.Export{}.MessageTypeOf(&pb2.Nested{}),
+				pimpl.Export{}.MessageTypeOf(&knownpb.StringValue{}),
 			),
 		},
 		inputMessage: &knownpb.Any{},
@@ -2349,7 +2350,7 @@
 	}, {
 		desc: "Any with duplicate value",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.StringValue{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.StringValue{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2361,7 +2362,7 @@
 	}, {
 		desc: "Any with unknown field",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2374,9 +2375,9 @@
 		desc: "Any with embedded type containing Any",
 		umo: jsonpb.UnmarshalOptions{
 			Resolver: preg.NewTypes(
-				(&pb2.KnownTypes{}).ProtoReflect().Type(),
-				(&knownpb.Any{}).ProtoReflect().Type(),
-				(&knownpb.StringValue{}).ProtoReflect().Type(),
+				pimpl.Export{}.MessageTypeOf(&pb2.KnownTypes{}),
+				pimpl.Export{}.MessageTypeOf(&knownpb.Any{}),
+				pimpl.Export{}.MessageTypeOf(&knownpb.StringValue{}),
 			),
 		},
 		inputMessage: &knownpb.Any{},
@@ -2411,7 +2412,7 @@
 	}, {
 		desc: "well known types as field values",
 		umo: jsonpb.UnmarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Empty{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Empty{})),
 		},
 		inputMessage: &pb2.KnownTypes{},
 		inputText: `{
@@ -2566,7 +2567,7 @@
 		desc: "DiscardUnknown: Any",
 		umo: jsonpb.UnmarshalOptions{
 			DiscardUnknown: true,
-			Resolver:       preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
+			Resolver:       preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
@@ -2580,7 +2581,7 @@
 		desc: "DiscardUnknown: Any with Empty",
 		umo: jsonpb.UnmarshalOptions{
 			DiscardUnknown: true,
-			Resolver:       preg.NewTypes((&knownpb.Empty{}).ProtoReflect().Type()),
+			Resolver:       preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Empty{})),
 		},
 		inputMessage: &knownpb.Any{},
 		inputText: `{
diff --git a/encoding/jsonpb/encode.go b/encoding/jsonpb/encode.go
index 9375091..90767ce 100644
--- a/encoding/jsonpb/encode.go
+++ b/encoding/jsonpb/encode.go
@@ -71,7 +71,7 @@
 func (o MarshalOptions) marshalMessage(m pref.Message) error {
 	var nerr errors.NonFatal
 
-	if isCustomType(m.Type().FullName()) {
+	if isCustomType(m.Descriptor().FullName()) {
 		return o.marshalCustomType(m)
 	}
 
@@ -87,7 +87,7 @@
 // marshalFields marshals the fields in the given protoreflect.Message.
 func (o MarshalOptions) marshalFields(m pref.Message) error {
 	var nerr errors.NonFatal
-	fieldDescs := m.Type().Fields()
+	fieldDescs := m.Descriptor().Fields()
 	knownFields := m.KnownFields()
 
 	// Marshal out known fields.
@@ -280,13 +280,13 @@
 	// Get a sorted list based on field key first.
 	entries := make([]xtEntry, 0, xtTypes.Len())
 	xtTypes.Range(func(xt pref.ExtensionType) bool {
-		name := xt.FullName()
+		name := xt.Descriptor().FullName()
 		// If extended type is a MessageSet, set field name to be the message type name.
 		if isMessageSetExtension(xt) {
-			name = xt.Message().FullName()
+			name = xt.Descriptor().Message().FullName()
 		}
 
-		num := xt.Number()
+		num := xt.Descriptor().Number()
 		if knownFields.Has(num) {
 			// Use [name] format for JSON field name.
 			pval := knownFields.Get(num)
@@ -313,7 +313,7 @@
 		if err := o.encoder.WriteName("[" + entry.key + "]"); !nerr.Merge(err) {
 			return err
 		}
-		if err := o.marshalValue(entry.value, entry.xtType); !nerr.Merge(err) {
+		if err := o.marshalValue(entry.value, entry.xtType.Descriptor()); !nerr.Merge(err) {
 			return err
 		}
 	}
@@ -322,16 +322,17 @@
 
 // isMessageSetExtension reports whether extension extends a message set.
 func isMessageSetExtension(xt pref.ExtensionType) bool {
-	if xt.Name() != "message_set_extension" {
+	xd := xt.Descriptor()
+	if xd.Name() != "message_set_extension" {
 		return false
 	}
-	md := xt.Message()
+	md := xd.Message()
 	if md == nil {
 		return false
 	}
-	if xt.FullName().Parent() != md.FullName() {
+	if xd.FullName().Parent() != md.FullName() {
 		return false
 	}
-	xmd, ok := xt.Extendee().(interface{ IsMessageSet() bool })
+	xmd, ok := xd.Extendee().(interface{ IsMessageSet() bool })
 	return ok && xmd.IsMessageSet()
 }
diff --git a/encoding/jsonpb/encode_test.go b/encoding/jsonpb/encode_test.go
index b0e3973..c2dd2d2 100644
--- a/encoding/jsonpb/encode_test.go
+++ b/encoding/jsonpb/encode_test.go
@@ -14,6 +14,7 @@
 	"github.com/golang/protobuf/v2/encoding/jsonpb"
 	"github.com/golang/protobuf/v2/internal/encoding/pack"
 	"github.com/golang/protobuf/v2/internal/encoding/wire"
+	pimpl "github.com/golang/protobuf/v2/internal/impl"
 	"github.com/golang/protobuf/v2/internal/scalar"
 	"github.com/golang/protobuf/v2/proto"
 	preg "github.com/golang/protobuf/v2/reflect/protoregistry"
@@ -1531,7 +1532,7 @@
 	}, {
 		desc: "Any with non-custom message",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
 		},
 		input: func() proto.Message {
 			m := &pb2.Nested{
@@ -1559,7 +1560,7 @@
 	}, {
 		desc: "Any with empty embedded message",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
 		},
 		input: &knownpb.Any{TypeUrl: "foo/pb2.Nested"},
 		want: `{
@@ -1573,7 +1574,7 @@
 	}, {
 		desc: "Any with missing required error",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&pb2.PartialRequired{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
 		},
 		input: func() proto.Message {
 			m := &pb2.PartialRequired{
@@ -1587,7 +1588,7 @@
 				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
 			}
 			return &knownpb.Any{
-				TypeUrl: string(m.ProtoReflect().Type().FullName()),
+				TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
 				Value:   b,
 			}
 		}(),
@@ -1600,7 +1601,7 @@
 		desc: "Any with partial required and AllowPartial",
 		mo: jsonpb.MarshalOptions{
 			AllowPartial: true,
-			Resolver:     preg.NewTypes((&pb2.PartialRequired{}).ProtoReflect().Type()),
+			Resolver:     preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
 		},
 		input: func() proto.Message {
 			m := &pb2.PartialRequired{
@@ -1614,7 +1615,7 @@
 				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
 			}
 			return &knownpb.Any{
-				TypeUrl: string(m.ProtoReflect().Type().FullName()),
+				TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
 				Value:   b,
 			}
 		}(),
@@ -1625,7 +1626,7 @@
 	}, {
 		desc: "Any with invalid UTF8",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
 		},
 		input: func() proto.Message {
 			m := &pb2.Nested{
@@ -1648,7 +1649,7 @@
 	}, {
 		desc: "Any with invalid value",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
 		},
 		input: &knownpb.Any{
 			TypeUrl: "foo/pb2.Nested",
@@ -1658,7 +1659,7 @@
 	}, {
 		desc: "Any with BoolValue",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.BoolValue{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.BoolValue{})),
 		},
 		input: func() proto.Message {
 			m := &knownpb.BoolValue{Value: true}
@@ -1678,7 +1679,7 @@
 	}, {
 		desc: "Any with Empty",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Empty{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Empty{})),
 		},
 		input: func() proto.Message {
 			m := &knownpb.Empty{}
@@ -1698,7 +1699,7 @@
 	}, {
 		desc: "Any with StringValue containing invalid UTF8",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.StringValue{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.StringValue{})),
 		},
 		input: func() proto.Message {
 			m := &knownpb.StringValue{Value: "abcd"}
@@ -1719,7 +1720,7 @@
 	}, {
 		desc: "Any with Int64Value",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Int64Value{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Int64Value{})),
 		},
 		input: func() proto.Message {
 			m := &knownpb.Int64Value{Value: 42}
@@ -1739,7 +1740,7 @@
 	}, {
 		desc: "Any with Duration",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Duration{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Duration{})),
 		},
 		input: func() proto.Message {
 			m := &knownpb.Duration{}
@@ -1759,7 +1760,7 @@
 	}, {
 		desc: "Any with empty Value",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Value{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Value{})),
 		},
 		input: func() proto.Message {
 			m := &knownpb.Value{}
@@ -1776,7 +1777,7 @@
 	}, {
 		desc: "Any with Value of StringValue",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Value{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Value{})),
 		},
 		input: func() proto.Message {
 			m := &knownpb.Value{Kind: &knownpb.Value_StringValue{"abcd"}}
@@ -1797,7 +1798,7 @@
 	}, {
 		desc: "Any with Value of NullValue",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Value{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Value{})),
 		},
 		input: func() proto.Message {
 			m := &knownpb.Value{Kind: &knownpb.Value_NullValue{}}
@@ -1818,11 +1819,11 @@
 		desc: "Any with Struct",
 		mo: jsonpb.MarshalOptions{
 			Resolver: preg.NewTypes(
-				(&knownpb.Struct{}).ProtoReflect().Type(),
-				(&knownpb.Value{}).ProtoReflect().Type(),
-				(&knownpb.BoolValue{}).ProtoReflect().Type(),
-				knownpb.NullValue_NULL_VALUE.Type(),
-				(&knownpb.StringValue{}).ProtoReflect().Type(),
+				pimpl.Export{}.MessageTypeOf(&knownpb.Struct{}),
+				pimpl.Export{}.MessageTypeOf(&knownpb.Value{}),
+				pimpl.Export{}.MessageTypeOf(&knownpb.BoolValue{}),
+				pimpl.Export{}.EnumTypeOf(knownpb.NullValue_NULL_VALUE),
+				pimpl.Export{}.MessageTypeOf(&knownpb.StringValue{}),
 			),
 		},
 		input: func() proto.Message {
@@ -1865,7 +1866,7 @@
 	}, {
 		desc: "Any with missing type_url",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.BoolValue{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.BoolValue{})),
 		},
 		input: func() proto.Message {
 			m := &knownpb.BoolValue{Value: true}
@@ -1881,7 +1882,7 @@
 	}, {
 		desc: "well known types as field values",
 		mo: jsonpb.MarshalOptions{
-			Resolver: preg.NewTypes((&knownpb.Empty{}).ProtoReflect().Type()),
+			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&knownpb.Empty{})),
 		},
 		input: &pb2.KnownTypes{
 			OptBool:      &knownpb.BoolValue{Value: false},
diff --git a/encoding/jsonpb/well_known_types.go b/encoding/jsonpb/well_known_types.go
index a7a30c1..ddd7e97 100644
--- a/encoding/jsonpb/well_known_types.go
+++ b/encoding/jsonpb/well_known_types.go
@@ -49,7 +49,7 @@
 // JSON conversion rules. It needs to be a message type where isCustomType
 // returns true, else it will panic.
 func (o MarshalOptions) marshalCustomType(m pref.Message) error {
-	name := m.Type().FullName()
+	name := m.Descriptor().FullName()
 	switch name {
 	case "google.protobuf.Any":
 		return o.marshalAny(m)
@@ -94,7 +94,7 @@
 // special JSON conversion rules. It needs to be a message type where
 // isCustomType returns true, else it will panic.
 func (o UnmarshalOptions) unmarshalCustomType(m pref.Message) error {
-	name := m.Type().FullName()
+	name := m.Descriptor().FullName()
 	switch name {
 	case "google.protobuf.Any":
 		return o.unmarshalAny(m)
@@ -142,7 +142,7 @@
 // field `value` which holds the custom JSON in addition to the `@type` field.
 
 func (o MarshalOptions) marshalAny(m pref.Message) error {
-	msgType := m.Type()
+	messageDesc := m.Descriptor()
 	knownFields := m.KnownFields()
 
 	// Start writing the JSON object.
@@ -155,7 +155,7 @@
 			return nil
 		} else {
 			// Return error if type_url field is not set, but value is set.
-			return errors.New("%s: type_url is not set", msgType.FullName())
+			return errors.New("%s: type_url is not set", messageDesc.FullName())
 		}
 	}
 
@@ -173,7 +173,7 @@
 	// Resolve the type in order to unmarshal value field.
 	emt, err := o.Resolver.FindMessageByURL(typeURL)
 	if !nerr.Merge(err) {
-		return errors.New("%s: unable to resolve %q: %v", msgType.FullName(), typeURL, err)
+		return errors.New("%s: unable to resolve %q: %v", messageDesc.FullName(), typeURL, err)
 	}
 
 	em := emt.New()
@@ -185,13 +185,13 @@
 		AllowPartial: o.AllowPartial,
 	}.Unmarshal(valueVal.Bytes(), em.Interface())
 	if !nerr.Merge(err) {
-		return errors.New("%s: unable to unmarshal %q: %v", msgType.FullName(), typeURL, err)
+		return errors.New("%s: unable to unmarshal %q: %v", messageDesc.FullName(), typeURL, err)
 	}
 
 	// If type of value has custom JSON encoding, marshal out a field "value"
 	// with corresponding custom JSON encoding of the embedded message as a
 	// field.
-	if isCustomType(emt.FullName()) {
+	if isCustomType(emt.Descriptor().FullName()) {
 		o.encoder.WriteName("value")
 		return o.marshalCustomType(em)
 	}
@@ -238,7 +238,7 @@
 
 	// Create new message for the embedded message type and unmarshal into it.
 	em := emt.New()
-	if isCustomType(emt.FullName()) {
+	if isCustomType(emt.Descriptor().FullName()) {
 		// If embedded message is a custom type, unmarshal the JSON "value" field
 		// into it.
 		if err := o.unmarshalAnyValue(em); !nerr.Merge(err) {
@@ -441,32 +441,23 @@
 
 // Wrapper types are encoded as JSON primitives like string, number or boolean.
 
-func (o MarshalOptions) marshalWrapperType(m pref.Message) error {
-	msgType := m.Type()
-	fieldDescs := msgType.Fields()
-	knownFields := m.KnownFields()
+// The "value" field has the same field number for all wrapper types.
+const wrapperFieldNumber = fieldnum.BoolValue_Value
 
-	// The "value" field has the same field number for all wrapper types.
-	const num = fieldnum.BoolValue_Value
-	fd := fieldDescs.ByNumber(num)
-	val := knownFields.Get(num)
+func (o MarshalOptions) marshalWrapperType(m pref.Message) error {
+	fd := m.Descriptor().Fields().ByNumber(wrapperFieldNumber)
+	val := m.KnownFields().Get(wrapperFieldNumber)
 	return o.marshalSingular(val, fd)
 }
 
 func (o UnmarshalOptions) unmarshalWrapperType(m pref.Message) error {
-	var nerr errors.NonFatal
-	msgType := m.Type()
-	fieldDescs := msgType.Fields()
-	knownFields := m.KnownFields()
-
-	// The "value" field has the same field number for all wrapper types.
-	const num = fieldnum.BoolValue_Value
-	fd := fieldDescs.ByNumber(num)
+	fd := m.Descriptor().Fields().ByNumber(wrapperFieldNumber)
 	val, err := o.unmarshalScalar(fd)
+	var nerr errors.NonFatal
 	if !nerr.Merge(err) {
 		return err
 	}
-	knownFields.Set(num, val)
+	m.KnownFields().Set(wrapperFieldNumber, val)
 	return nerr.E
 }
 
@@ -517,22 +508,14 @@
 // Struct.fields map and follows the serialization rules for a map.
 
 func (o MarshalOptions) marshalStruct(m pref.Message) error {
-	msgType := m.Type()
-	fieldDescs := msgType.Fields()
-	knownFields := m.KnownFields()
-
-	fd := fieldDescs.ByNumber(fieldnum.Struct_Fields)
-	val := knownFields.Get(fieldnum.Struct_Fields)
+	fd := m.Descriptor().Fields().ByNumber(fieldnum.Struct_Fields)
+	val := m.KnownFields().Get(fieldnum.Struct_Fields)
 	return o.marshalMap(val.Map(), fd)
 }
 
 func (o UnmarshalOptions) unmarshalStruct(m pref.Message) error {
-	msgType := m.Type()
-	fieldDescs := msgType.Fields()
-	knownFields := m.KnownFields()
-
-	fd := fieldDescs.ByNumber(fieldnum.Struct_Fields)
-	val := knownFields.Get(fieldnum.Struct_Fields)
+	fd := m.Descriptor().Fields().ByNumber(fieldnum.Struct_Fields)
+	val := m.KnownFields().Get(fieldnum.Struct_Fields)
 	return o.unmarshalMap(val.Map(), fd)
 }
 
@@ -541,22 +524,14 @@
 // repeated field.
 
 func (o MarshalOptions) marshalListValue(m pref.Message) error {
-	msgType := m.Type()
-	fieldDescs := msgType.Fields()
-	knownFields := m.KnownFields()
-
-	fd := fieldDescs.ByNumber(fieldnum.ListValue_Values)
-	val := knownFields.Get(fieldnum.ListValue_Values)
+	fd := m.Descriptor().Fields().ByNumber(fieldnum.ListValue_Values)
+	val := m.KnownFields().Get(fieldnum.ListValue_Values)
 	return o.marshalList(val.List(), fd)
 }
 
 func (o UnmarshalOptions) unmarshalListValue(m pref.Message) error {
-	msgType := m.Type()
-	fieldDescs := msgType.Fields()
-	knownFields := m.KnownFields()
-
-	fd := fieldDescs.ByNumber(fieldnum.ListValue_Values)
-	val := knownFields.Get(fieldnum.ListValue_Values)
+	fd := m.Descriptor().Fields().ByNumber(fieldnum.ListValue_Values)
+	val := m.KnownFields().Get(fieldnum.ListValue_Values)
 	return o.unmarshalList(val.List(), fd)
 }
 
@@ -565,15 +540,15 @@
 // Value message needs to be a oneof field set, else it is an error.
 
 func (o MarshalOptions) marshalKnownValue(m pref.Message) error {
-	msgType := m.Type()
+	messageDesc := m.Descriptor()
 	knownFields := m.KnownFields()
 	num := knownFields.WhichOneof("kind")
 	if num == 0 {
 		// Return error if none of the fields is set.
-		return errors.New("%s: none of the oneof fields is set", msgType.FullName())
+		return errors.New("%s: none of the oneof fields is set", messageDesc.FullName())
 	}
 
-	fd := msgType.Fields().ByNumber(num)
+	fd := messageDesc.Fields().ByNumber(num)
 	val := knownFields.Get(num)
 	return o.marshalSingular(val, fd)
 }
@@ -669,7 +644,7 @@
 )
 
 func (o MarshalOptions) marshalDuration(m pref.Message) error {
-	msgType := m.Type()
+	messageDesc := m.Descriptor()
 	knownFields := m.KnownFields()
 
 	secsVal := knownFields.Get(fieldnum.Duration_Seconds)
@@ -677,13 +652,13 @@
 	secs := secsVal.Int()
 	nanos := nanosVal.Int()
 	if secs < -maxSecondsInDuration || secs > maxSecondsInDuration {
-		return errors.New("%s: seconds out of range %v", msgType.FullName(), secs)
+		return errors.New("%s: seconds out of range %v", messageDesc.FullName(), secs)
 	}
 	if nanos < -secondsInNanos || nanos > secondsInNanos {
-		return errors.New("%s: nanos out of range %v", msgType.FullName(), nanos)
+		return errors.New("%s: nanos out of range %v", messageDesc.FullName(), nanos)
 	}
 	if (secs > 0 && nanos < 0) || (secs < 0 && nanos > 0) {
-		return errors.New("%s: signs of seconds and nanos do not match", msgType.FullName())
+		return errors.New("%s: signs of seconds and nanos do not match", messageDesc.FullName())
 	}
 	// Generated output always contains 0, 3, 6, or 9 fractional digits,
 	// depending on required precision, followed by the suffix "s".
@@ -712,16 +687,16 @@
 		return unexpectedJSONError{jval}
 	}
 
-	msgType := m.Type()
+	messageDesc := m.Descriptor()
 	input := jval.String()
 	secs, nanos, ok := parseDuration(input)
 	if !ok {
-		return errors.New("%s: invalid duration value %q", msgType.FullName(), input)
+		return errors.New("%s: invalid duration value %q", messageDesc.FullName(), input)
 	}
 	// Validate seconds. No need to validate nanos because parseDuration would
 	// have covered that already.
 	if secs < -maxSecondsInDuration || secs > maxSecondsInDuration {
-		return errors.New("%s: out of range %q", msgType.FullName(), input)
+		return errors.New("%s: out of range %q", messageDesc.FullName(), input)
 	}
 
 	knownFields := m.KnownFields()
@@ -859,7 +834,7 @@
 )
 
 func (o MarshalOptions) marshalTimestamp(m pref.Message) error {
-	msgType := m.Type()
+	messageDesc := m.Descriptor()
 	knownFields := m.KnownFields()
 
 	secsVal := knownFields.Get(fieldnum.Timestamp_Seconds)
@@ -867,10 +842,10 @@
 	secs := secsVal.Int()
 	nanos := nanosVal.Int()
 	if secs < minTimestampSeconds || secs > maxTimestampSeconds {
-		return errors.New("%s: seconds out of range %v", msgType.FullName(), secs)
+		return errors.New("%s: seconds out of range %v", messageDesc.FullName(), secs)
 	}
 	if nanos < 0 || nanos > secondsInNanos {
-		return errors.New("%s: nanos out of range %v", msgType.FullName(), nanos)
+		return errors.New("%s: nanos out of range %v", messageDesc.FullName(), nanos)
 	}
 	// Uses RFC 3339, where generated output will be Z-normalized and uses 0, 3,
 	// 6 or 9 fractional digits.
@@ -893,17 +868,17 @@
 		return unexpectedJSONError{jval}
 	}
 
-	msgType := m.Type()
+	messageDesc := m.Descriptor()
 	input := jval.String()
 	t, err := time.Parse(time.RFC3339Nano, input)
 	if err != nil {
-		return errors.New("%s: invalid timestamp value %q", msgType.FullName(), input)
+		return errors.New("%s: invalid timestamp value %q", messageDesc.FullName(), input)
 	}
 	// Validate seconds. No need to validate nanos because time.Parse would have
 	// covered that already.
 	secs := t.Unix()
 	if secs < minTimestampSeconds || secs > maxTimestampSeconds {
-		return errors.New("%s: out of range %q", msgType.FullName(), input)
+		return errors.New("%s: out of range %q", messageDesc.FullName(), input)
 	}
 
 	knownFields := m.KnownFields()
@@ -918,11 +893,7 @@
 // end up differently after a round-trip.
 
 func (o MarshalOptions) marshalFieldMask(m pref.Message) error {
-	msgType := m.Type()
-	knownFields := m.KnownFields()
-	name := msgType.FullName()
-
-	val := knownFields.Get(fieldnum.FieldMask_Paths)
+	val := m.KnownFields().Get(fieldnum.FieldMask_Paths)
 	list := val.List()
 	paths := make([]string, 0, list.Len())
 
@@ -931,7 +902,7 @@
 		// Return error if conversion to camelCase is not reversible.
 		cc := camelCase(s)
 		if s != snakeCase(cc) {
-			return errors.New("%s.paths contains irreversible value %q", name, s)
+			return errors.New("%s.paths contains irreversible value %q", m.Descriptor().FullName(), s)
 		}
 		paths = append(paths, cc)
 	}
@@ -955,8 +926,7 @@
 	}
 	paths := strings.Split(str, ",")
 
-	knownFields := m.KnownFields()
-	val := knownFields.Get(fieldnum.FieldMask_Paths)
+	val := m.KnownFields().Get(fieldnum.FieldMask_Paths)
 	list := val.List()
 
 	for _, s := range paths {