internal/impl: abstract away ExtensionDescV1 as the underlying descriptor

Add ExtensionField.{SetType,GetType} to hide the fact that the underlying
descriptor is actually an ExtensionDescV1.

Change-Id: I1d0595484ced0a88d2df0852a732fdf0fe9aa232
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/180538
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/impl/codec_extension.go b/internal/impl/codec_extension.go
index 714dec7..69d5a96 100644
--- a/internal/impl/codec_extension.go
+++ b/internal/impl/codec_extension.go
@@ -5,7 +5,11 @@
 package impl
 
 import (
+	"sync"
+	"sync/atomic"
+
 	"google.golang.org/protobuf/internal/encoding/wire"
+	pref "google.golang.org/protobuf/reflect/protoreflect"
 	piface "google.golang.org/protobuf/runtime/protoiface"
 )
 
@@ -15,29 +19,109 @@
 	funcs   ifaceCoderFuncs
 }
 
-func (mi *MessageInfo) extensionFieldInfo(desc *piface.ExtensionDescV1) *extensionFieldInfo {
+func (mi *MessageInfo) extensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo {
 	// As of this time (Go 1.12, linux/amd64), an RWMutex benchmarks as faster
 	// than a sync.Map.
 	mi.extensionFieldInfosMu.RLock()
-	e, ok := mi.extensionFieldInfos[desc]
+	e, ok := mi.extensionFieldInfos[xt]
 	mi.extensionFieldInfosMu.RUnlock()
 	if ok {
 		return e
 	}
 
-	etype := extensionTypeFromDesc(desc)
-	wiretag := wire.EncodeTag(etype.Number(), wireTypes[etype.Kind()])
+	wiretag := wire.EncodeTag(xt.Number(), wireTypes[xt.Kind()])
 	e = &extensionFieldInfo{
 		wiretag: wiretag,
 		tagsize: wire.SizeVarint(wiretag),
-		funcs:   encoderFuncsForValue(etype, etype.GoType()),
+		funcs:   encoderFuncsForValue(xt, xt.GoType()),
 	}
 
 	mi.extensionFieldInfosMu.Lock()
 	if mi.extensionFieldInfos == nil {
-		mi.extensionFieldInfos = make(map[*piface.ExtensionDescV1]*extensionFieldInfo)
+		mi.extensionFieldInfos = make(map[pref.ExtensionType]*extensionFieldInfo)
 	}
-	mi.extensionFieldInfos[desc] = e
+	mi.extensionFieldInfos[xt] = e
 	mi.extensionFieldInfosMu.Unlock()
 	return e
 }
+
+type ExtensionField struct {
+	// Desc is the descriptor information for the extension field.
+	// It must be populated if value is populated.
+	Desc *piface.ExtensionDescV1 // TODO: unexport and switch to protoreflect.ExtensionType
+
+	// value is either the value of GetValue,
+	// or a *lazyExtensionValue that then returns the value of GetValue.
+	value interface{} // TODO: switch to protoreflect.Value
+}
+
+func (f ExtensionField) HasType() bool {
+	return f.Desc != nil
+}
+func (f ExtensionField) GetType() pref.ExtensionType {
+	return legacyExtensionTypeFromDesc(f.Desc)
+}
+func (f *ExtensionField) SetType(t pref.ExtensionType) {
+	f.Desc = legacyExtensionDescFromType(t)
+}
+
+// HasValue reports whether a value is set for the extension field.
+// This may be called concurrently.
+func (f ExtensionField) HasValue() bool {
+	return f.value != nil
+}
+
+// GetValue returns the concrete value for the extension field.
+// Let the type of Desc.ExtensionType be the "API type" and
+// the type of GetValue be the "storage type".
+// The API type and storage type are the same except:
+//	* for scalars (except []byte), where the API type uses *T,
+//	while the storage type uses T.
+//	* for repeated fields, where the API type uses []T,
+//	while the storage type uses *[]T.
+//
+// The reason for the divergence is so that the storage type more naturally
+// matches what is expected of when retrieving the values through the
+// protobuf reflection APIs.
+//
+// GetValue is only populated if Desc is also populated.
+// This may be called concurrently.
+//
+// TODO: switch interface{} to protoreflect.Value
+func (f ExtensionField) GetValue() interface{} {
+	if f, ok := f.value.(*lazyExtensionValue); ok {
+		return f.GetValue()
+	}
+	return f.value
+}
+
+// SetEagerValue sets the current value of the extension.
+// This must not be called concurrently.
+func (f *ExtensionField) SetEagerValue(v interface{}) {
+	f.value = v
+}
+
+// SetLazyValue sets a value that is to be lazily evaluated upon first use.
+// The returned value must not be nil.
+// This must not be called concurrently.
+func (f *ExtensionField) SetLazyValue(v func() interface{}) {
+	f.value = &lazyExtensionValue{value: v}
+}
+
+type lazyExtensionValue struct {
+	once  uint32      // atomically set if value is valid
+	mu    sync.Mutex  // protects value
+	value interface{} // either the value itself or a func() interface{}
+}
+
+func (v *lazyExtensionValue) GetValue() interface{} {
+	if atomic.LoadUint32(&v.once) == 0 {
+		v.mu.Lock()
+		if f, ok := v.value.(func() interface{}); ok {
+			v.value = f()
+		}
+		atomic.StoreUint32(&v.once, 1)
+		v.mu.Unlock()
+	}
+	return v.value
+}
diff --git a/internal/impl/encode.go b/internal/impl/encode.go
index e3ba7cf..52ad799 100644
--- a/internal/impl/encode.go
+++ b/internal/impl/encode.go
@@ -130,21 +130,21 @@
 	return b, nerr.E
 }
 
-func (mi *MessageInfo) sizeExtensions(ext *legacyExtensionMap, opts marshalOptions) (n int) {
+func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marshalOptions) (n int) {
 	if ext == nil {
 		return 0
 	}
-	for _, e := range *ext {
-		ei := mi.extensionFieldInfo(e.Desc)
-		if ei.funcs.size == nil {
+	for _, x := range *ext {
+		xi := mi.extensionFieldInfo(x.GetType())
+		if xi.funcs.size == nil {
 			continue
 		}
-		n += ei.funcs.size(e.value, ei.tagsize, opts)
+		n += xi.funcs.size(x.GetValue(), xi.tagsize, opts)
 	}
 	return n
 }
 
-func (mi *MessageInfo) appendExtensions(b []byte, ext *legacyExtensionMap, opts marshalOptions) ([]byte, error) {
+func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField, opts marshalOptions) ([]byte, error) {
 	if ext == nil {
 		return b, nil
 	}
@@ -155,9 +155,9 @@
 	case 1:
 		// Fast-path for one extension: Don't bother sorting the keys.
 		var err error
-		for _, e := range *ext {
-			ei := mi.extensionFieldInfo(e.Desc)
-			b, err = ei.funcs.marshal(b, e.value, ei.wiretag, opts)
+		for _, x := range *ext {
+			xi := mi.extensionFieldInfo(x.GetType())
+			b, err = xi.funcs.marshal(b, x.GetValue(), xi.wiretag, opts)
 		}
 		return b, err
 	default:
@@ -171,9 +171,9 @@
 		var err error
 		var nerr errors.NonFatal
 		for _, k := range keys {
-			e := (*ext)[int32(k)]
-			ei := mi.extensionFieldInfo(e.Desc)
-			b, err = ei.funcs.marshal(b, e.value, ei.wiretag, opts)
+			x := (*ext)[int32(k)]
+			xi := mi.extensionFieldInfo(x.GetType())
+			b, err = xi.funcs.marshal(b, x.GetValue(), xi.wiretag, opts)
 			if !nerr.Merge(err) {
 				return b, err
 			}
diff --git a/internal/impl/legacy_extension_test.go b/internal/impl/legacy_extension_test.go
index 13a2c6d..6ccfa40 100644
--- a/internal/impl/legacy_extension_test.go
+++ b/internal/impl/legacy_extension_test.go
@@ -18,7 +18,7 @@
 
 type legacyExtendedMessage struct {
 	XXX_unrecognized       []byte
-	XXX_InternalExtensions map[int32]pimpl.ExtensionFieldV1
+	XXX_InternalExtensions map[int32]pimpl.ExtensionField
 }
 
 func (*legacyExtendedMessage) Reset()         {}
diff --git a/internal/impl/legacy_test.go b/internal/impl/legacy_test.go
index d6ca941..c1ba55e 100644
--- a/internal/impl/legacy_test.go
+++ b/internal/impl/legacy_test.go
@@ -27,7 +27,7 @@
 
 type legacyTestMessage struct {
 	XXX_unrecognized       []byte
-	XXX_InternalExtensions map[int32]pimpl.ExtensionFieldV1
+	XXX_InternalExtensions map[int32]pimpl.ExtensionField
 }
 
 func (*legacyTestMessage) Reset()         {}
diff --git a/internal/impl/message.go b/internal/impl/message.go
index d64ee7f..6db60f1 100644
--- a/internal/impl/message.go
+++ b/internal/impl/message.go
@@ -48,7 +48,7 @@
 	sizecacheOffset       offset
 	unknownOffset         offset
 	extensionFieldInfosMu sync.RWMutex
-	extensionFieldInfos   map[*piface.ExtensionDescV1]*extensionFieldInfo
+	extensionFieldInfos   map[pref.ExtensionType]*extensionFieldInfo
 }
 
 var prefMessageType = reflect.TypeOf((*pref.Message)(nil)).Elem()
diff --git a/internal/impl/message_field_extension.go b/internal/impl/message_field_extension.go
index 3c403af..b537775 100644
--- a/internal/impl/message_field_extension.go
+++ b/internal/impl/message_field_extension.go
@@ -6,11 +6,8 @@
 
 import (
 	"reflect"
-	"sync"
-	"sync/atomic"
 
 	pref "google.golang.org/protobuf/reflect/protoreflect"
-	piface "google.golang.org/protobuf/runtime/protoiface"
 )
 
 func makeLegacyExtensionFieldsFunc(t reflect.Type) func(p *messageDataType) pref.KnownFields {
@@ -26,7 +23,7 @@
 	}
 }
 
-var extType = reflect.TypeOf(map[int32]ExtensionFieldV1{})
+var extType = reflect.TypeOf(map[int32]ExtensionField{})
 
 func makeLegacyExtensionMapFunc(t reflect.Type) func(*messageDataType) *legacyExtensionMap {
 	fx, _ := t.FieldByName("XXX_extensions")
@@ -40,7 +37,7 @@
 	fieldOffset := offsetOf(fx)
 	return func(p *messageDataType) *legacyExtensionMap {
 		v := p.p.Apply(fieldOffset).AsValueOf(fx.Type).Interface()
-		return (*legacyExtensionMap)(v.(*map[int32]ExtensionFieldV1))
+		return (*legacyExtensionMap)(v.(*map[int32]ExtensionField))
 	}
 }
 
@@ -50,7 +47,7 @@
 }
 
 func (p legacyExtensionFields) Len() (n int) {
-	p.x.Range(func(num pref.FieldNumber, _ ExtensionFieldV1) bool {
+	p.x.Range(func(num pref.FieldNumber, _ ExtensionField) bool {
 		if p.Has(pref.FieldNumber(num)) {
 			n++
 		}
@@ -64,7 +61,7 @@
 	if !x.HasValue() {
 		return false
 	}
-	t := extensionTypeFromDesc(x.Desc)
+	t := x.GetType()
 	d := t.Descriptor()
 	if d.IsList() {
 		return t.ValueOf(x.GetValue()).List().Len() > 0
@@ -74,10 +71,10 @@
 
 func (p legacyExtensionFields) Get(n pref.FieldNumber) pref.Value {
 	x := p.x.Get(n)
-	if x.Desc == nil {
+	if !x.HasType() {
 		return pref.Value{}
 	}
-	t := extensionTypeFromDesc(x.Desc)
+	t := x.GetType()
 	d := t.Descriptor()
 	if !x.HasValue() {
 		// NOTE: x.Value is never nil for Lists since they are always populated
@@ -92,20 +89,20 @@
 
 func (p legacyExtensionFields) Set(n pref.FieldNumber, v pref.Value) {
 	x := p.x.Get(n)
-	if x.Desc == nil {
+	if !x.HasType() {
 		panic("no extension descriptor registered")
 	}
-	t := extensionTypeFromDesc(x.Desc)
+	t := x.GetType()
 	x.SetEagerValue(t.InterfaceOf(v))
 	p.x.Set(n, x)
 }
 
 func (p legacyExtensionFields) Clear(n pref.FieldNumber) {
 	x := p.x.Get(n)
-	if x.Desc == nil {
+	if !x.HasType() {
 		return
 	}
-	t := extensionTypeFromDesc(x.Desc)
+	t := x.GetType()
 	d := t.Descriptor()
 	if d.IsList() {
 		t.ValueOf(x.GetValue()).List().Truncate(0)
@@ -120,7 +117,7 @@
 }
 
 func (p legacyExtensionFields) Range(f func(pref.FieldNumber, pref.Value) bool) {
-	p.x.Range(func(n pref.FieldNumber, x ExtensionFieldV1) bool {
+	p.x.Range(func(n pref.FieldNumber, x ExtensionField) bool {
 		if p.Has(n) {
 			return f(n, p.Get(n))
 		}
@@ -130,10 +127,10 @@
 
 func (p legacyExtensionFields) NewMessage(n pref.FieldNumber) pref.Message {
 	x := p.x.Get(n)
-	if x.Desc == nil {
+	if !x.HasType() {
 		panic("no extension descriptor registered")
 	}
-	xt := extensionTypeFromDesc(x.Desc)
+	xt := x.GetType()
 	return xt.New().Message()
 }
 
@@ -144,8 +141,8 @@
 type legacyExtensionTypes legacyExtensionFields
 
 func (p legacyExtensionTypes) Len() (n int) {
-	p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
-		if x.Desc != nil {
+	p.x.Range(func(_ pref.FieldNumber, x ExtensionField) bool {
+		if x.HasType() {
 			n++
 		}
 		return true
@@ -162,10 +159,10 @@
 		panic("invalid extension field number")
 	}
 	x := p.x.Get(d.Number())
-	if x.Desc != nil {
+	if x.HasType() {
 		panic("extension descriptor already registered")
 	}
-	x.Desc = extensionDescFromType(t)
+	x.SetType(t)
 	if d.IsList() {
 		// If the field is repeated, initialize the entry with an empty list
 		// so that future Get operations can return a mutable and concrete list.
@@ -195,16 +192,16 @@
 
 func (p legacyExtensionTypes) ByNumber(n pref.FieldNumber) pref.ExtensionType {
 	x := p.x.Get(n)
-	if x.Desc != nil {
-		return extensionTypeFromDesc(x.Desc)
+	if x.HasType() {
+		return x.GetType()
 	}
 	return nil
 }
 
 func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) {
-	p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
-		if x.Desc != nil && x.Desc.Name == string(s) {
-			t = extensionTypeFromDesc(x.Desc)
+	p.x.Range(func(_ pref.FieldNumber, x ExtensionField) bool {
+		if x.HasType() && x.GetType().FullName() == s {
+			t = x.GetType()
 			return false
 		}
 		return true
@@ -213,9 +210,9 @@
 }
 
 func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) {
-	p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
-		if x.Desc != nil {
-			if !f(extensionTypeFromDesc(x.Desc)) {
+	p.x.Range(func(_ pref.FieldNumber, x ExtensionField) bool {
+		if x.HasType() {
+			if !f(x.GetType()) {
 				return false
 			}
 		}
@@ -223,106 +220,7 @@
 	})
 }
 
-func extensionDescFromType(typ pref.ExtensionType) *piface.ExtensionDescV1 {
-	if xt, ok := typ.(interface {
-		ProtoLegacyExtensionDesc() *piface.ExtensionDescV1
-	}); ok {
-		if desc := xt.ProtoLegacyExtensionDesc(); desc != nil {
-			return desc
-		}
-	}
-	return Export{}.ExtensionDescFromType(typ)
-}
-
-func extensionTypeFromDesc(desc *piface.ExtensionDescV1) pref.ExtensionType {
-	if desc.Type != nil {
-		return desc.Type
-	}
-	return Export{}.ExtensionTypeFromDesc(desc)
-}
-
-type ExtensionFieldV1 struct {
-	// TODO: We should turn this into a type alias to an unnamed type,
-	// which means that v1 can have the same struct, and we no longer have to
-	// export this from the v2 API.
-
-	// When an extension is stored in a message using SetExtension
-	// only desc and value are set. When the message is marshaled
-	// Raw will be set to the encoded form of the message.
-	//
-	// When a message is unmarshaled and contains extensions, each
-	// extension will have only Raw set. When such an extension is
-	// accessed using GetExtension (or GetExtensions) desc and value
-	// will be set.
-	Desc *piface.ExtensionDescV1 // TODO: switch to protoreflect.ExtensionType
-
-	// value is either the value of GetValue,
-	// or a *lazyExtensionValue that then returns the value of GetValue.
-	value interface{}
-}
-
-// HasValue reports whether a value is set for the extension field.
-// This may be called concurrently.
-func (f ExtensionFieldV1) HasValue() bool {
-	return f.value != nil
-}
-
-// GetValue returns the concrete value for the extension field.
-// Let the type of Desc.ExtensionType be the "API type" and
-// the type of GetValue be the "storage type".
-// The API type and storage type are the same except:
-//	* for scalars (except []byte), where the API type uses *T,
-//	while the storage type uses T.
-//	* for repeated fields, where the API type uses []T,
-//	while the storage type uses *[]T.
-//
-// The reason for the divergence is so that the storage type more naturally
-// matches what is expected of when retrieving the values through the
-// protobuf reflection APIs.
-//
-// GetValue is only populated if Desc is also populated.
-// This may be called concurrently.
-//
-// TODO: switch interface{} to protoreflect.Value
-func (f ExtensionFieldV1) GetValue() interface{} {
-	if f, ok := f.value.(*lazyExtensionValue); ok {
-		return f.GetValue()
-	}
-	return f.value
-}
-
-// SetEagerValue sets the current value of the extension.
-// This must not be called concurrently.
-func (f *ExtensionFieldV1) SetEagerValue(v interface{}) {
-	f.value = v
-}
-
-// SetLazyValue sets a value that is to be lazily evaluated upon first use.
-// The returned value must not be nil.
-// This must not be called concurrently.
-func (f *ExtensionFieldV1) SetLazyValue(v func() interface{}) {
-	f.value = &lazyExtensionValue{value: v}
-}
-
-type lazyExtensionValue struct {
-	once  uint32      // atomically set if value is valid
-	mu    sync.Mutex  // protects value
-	value interface{} // either the value itself or a func() interface{}
-}
-
-func (v *lazyExtensionValue) GetValue() interface{} {
-	if atomic.LoadUint32(&v.once) == 0 {
-		v.mu.Lock()
-		if f, ok := v.value.(func() interface{}); ok {
-			v.value = f()
-		}
-		atomic.StoreUint32(&v.once, 1)
-		v.mu.Unlock()
-	}
-	return v.value
-}
-
-type legacyExtensionMap map[int32]ExtensionFieldV1
+type legacyExtensionMap map[int32]ExtensionField
 
 func (m legacyExtensionMap) Len() int {
 	return len(m)
@@ -331,19 +229,19 @@
 	_, ok := m[int32(n)]
 	return ok
 }
-func (m legacyExtensionMap) Get(n pref.FieldNumber) ExtensionFieldV1 {
+func (m legacyExtensionMap) Get(n pref.FieldNumber) ExtensionField {
 	return m[int32(n)]
 }
-func (m *legacyExtensionMap) Set(n pref.FieldNumber, x ExtensionFieldV1) {
+func (m *legacyExtensionMap) Set(n pref.FieldNumber, x ExtensionField) {
 	if *m == nil {
-		*m = make(map[int32]ExtensionFieldV1)
+		*m = make(map[int32]ExtensionField)
 	}
 	(*m)[int32(n)] = x
 }
 func (m *legacyExtensionMap) Clear(n pref.FieldNumber) {
 	delete(*m, int32(n))
 }
-func (m legacyExtensionMap) Range(f func(pref.FieldNumber, ExtensionFieldV1) bool) {
+func (m legacyExtensionMap) Range(f func(pref.FieldNumber, ExtensionField) bool) {
 	for n, x := range m {
 		if !f(pref.FieldNumber(n), x) {
 			return
diff --git a/internal/impl/pointer_reflect.go b/internal/impl/pointer_reflect.go
index b851b1b..207c20b 100644
--- a/internal/impl/pointer_reflect.go
+++ b/internal/impl/pointer_reflect.go
@@ -98,8 +98,8 @@
 func (p pointer) StringSlice() *[]string   { return p.v.Interface().(*[]string) }
 func (p pointer) Bytes() *[]byte           { return p.v.Interface().(*[]byte) }
 func (p pointer) BytesSlice() *[][]byte    { return p.v.Interface().(*[][]byte) }
-func (p pointer) Extensions() *legacyExtensionMap {
-	return (*legacyExtensionMap)(p.v.Interface().(*map[int32]ExtensionFieldV1))
+func (p pointer) Extensions() *map[int32]ExtensionField {
+	return p.v.Interface().(*map[int32]ExtensionField)
 }
 
 func (p pointer) Elem() pointer {
diff --git a/internal/impl/pointer_unsafe.go b/internal/impl/pointer_unsafe.go
index f04a561..39f1995 100644
--- a/internal/impl/pointer_unsafe.go
+++ b/internal/impl/pointer_unsafe.go
@@ -73,33 +73,33 @@
 	return p.AsValueOf(t).Interface()
 }
 
-func (p pointer) Bool() *bool                     { return (*bool)(p.p) }
-func (p pointer) BoolPtr() **bool                 { return (**bool)(p.p) }
-func (p pointer) BoolSlice() *[]bool              { return (*[]bool)(p.p) }
-func (p pointer) Int32() *int32                   { return (*int32)(p.p) }
-func (p pointer) Int32Ptr() **int32               { return (**int32)(p.p) }
-func (p pointer) Int32Slice() *[]int32            { return (*[]int32)(p.p) }
-func (p pointer) Int64() *int64                   { return (*int64)(p.p) }
-func (p pointer) Int64Ptr() **int64               { return (**int64)(p.p) }
-func (p pointer) Int64Slice() *[]int64            { return (*[]int64)(p.p) }
-func (p pointer) Uint32() *uint32                 { return (*uint32)(p.p) }
-func (p pointer) Uint32Ptr() **uint32             { return (**uint32)(p.p) }
-func (p pointer) Uint32Slice() *[]uint32          { return (*[]uint32)(p.p) }
-func (p pointer) Uint64() *uint64                 { return (*uint64)(p.p) }
-func (p pointer) Uint64Ptr() **uint64             { return (**uint64)(p.p) }
-func (p pointer) Uint64Slice() *[]uint64          { return (*[]uint64)(p.p) }
-func (p pointer) Float32() *float32               { return (*float32)(p.p) }
-func (p pointer) Float32Ptr() **float32           { return (**float32)(p.p) }
-func (p pointer) Float32Slice() *[]float32        { return (*[]float32)(p.p) }
-func (p pointer) Float64() *float64               { return (*float64)(p.p) }
-func (p pointer) Float64Ptr() **float64           { return (**float64)(p.p) }
-func (p pointer) Float64Slice() *[]float64        { return (*[]float64)(p.p) }
-func (p pointer) String() *string                 { return (*string)(p.p) }
-func (p pointer) StringPtr() **string             { return (**string)(p.p) }
-func (p pointer) StringSlice() *[]string          { return (*[]string)(p.p) }
-func (p pointer) Bytes() *[]byte                  { return (*[]byte)(p.p) }
-func (p pointer) BytesSlice() *[][]byte           { return (*[][]byte)(p.p) }
-func (p pointer) Extensions() *legacyExtensionMap { return (*legacyExtensionMap)(p.p) }
+func (p pointer) Bool() *bool                           { return (*bool)(p.p) }
+func (p pointer) BoolPtr() **bool                       { return (**bool)(p.p) }
+func (p pointer) BoolSlice() *[]bool                    { return (*[]bool)(p.p) }
+func (p pointer) Int32() *int32                         { return (*int32)(p.p) }
+func (p pointer) Int32Ptr() **int32                     { return (**int32)(p.p) }
+func (p pointer) Int32Slice() *[]int32                  { return (*[]int32)(p.p) }
+func (p pointer) Int64() *int64                         { return (*int64)(p.p) }
+func (p pointer) Int64Ptr() **int64                     { return (**int64)(p.p) }
+func (p pointer) Int64Slice() *[]int64                  { return (*[]int64)(p.p) }
+func (p pointer) Uint32() *uint32                       { return (*uint32)(p.p) }
+func (p pointer) Uint32Ptr() **uint32                   { return (**uint32)(p.p) }
+func (p pointer) Uint32Slice() *[]uint32                { return (*[]uint32)(p.p) }
+func (p pointer) Uint64() *uint64                       { return (*uint64)(p.p) }
+func (p pointer) Uint64Ptr() **uint64                   { return (**uint64)(p.p) }
+func (p pointer) Uint64Slice() *[]uint64                { return (*[]uint64)(p.p) }
+func (p pointer) Float32() *float32                     { return (*float32)(p.p) }
+func (p pointer) Float32Ptr() **float32                 { return (**float32)(p.p) }
+func (p pointer) Float32Slice() *[]float32              { return (*[]float32)(p.p) }
+func (p pointer) Float64() *float64                     { return (*float64)(p.p) }
+func (p pointer) Float64Ptr() **float64                 { return (**float64)(p.p) }
+func (p pointer) Float64Slice() *[]float64              { return (*[]float64)(p.p) }
+func (p pointer) String() *string                       { return (*string)(p.p) }
+func (p pointer) StringPtr() **string                   { return (**string)(p.p) }
+func (p pointer) StringSlice() *[]string                { return (*[]string)(p.p) }
+func (p pointer) Bytes() *[]byte                        { return (*[]byte)(p.p) }
+func (p pointer) BytesSlice() *[][]byte                 { return (*[][]byte)(p.p) }
+func (p pointer) Extensions() *map[int32]ExtensionField { return (*map[int32]ExtensionField)(p.p) }
 
 func (p pointer) Elem() pointer {
 	return pointer{p: *(*unsafe.Pointer)(p.p)}
diff --git a/runtime/protoimpl/impl.go b/runtime/protoimpl/impl.go
index fac3cfc..e28bfc2 100644
--- a/runtime/protoimpl/impl.go
+++ b/runtime/protoimpl/impl.go
@@ -62,11 +62,11 @@
 	FileBuilder = fileinit.FileBuilder
 
 	// TODO: Change these to more efficient data structures.
-	ExtensionFields = map[int32]impl.ExtensionFieldV1
+	ExtensionFields = map[int32]impl.ExtensionField
 	UnknownFields   = []byte
 	SizeCache       = int32
 
-	ExtensionFieldV1 = impl.ExtensionFieldV1
+	ExtensionFieldV1 = impl.ExtensionField
 )
 
 var X impl.Export