all: make use of the protoapi package in v1

The new v1 protoapi package enables:
* Referencing types in the protoapi package instead of protoV1, which further
reduces the number of situations where we need to depend on protoV1.
This is for the goal of eventually breaking all cases where the v2 implementation
relies on v1, so that in the near future, proto v1 can rely on proto v2 instead.
* Removes the need for legacy_extension_hack.go since that functionality has now
been exported into the protoapi package.

Change-Id: If71002d9ec711bfabfe494636829df9abf19e23e
Reviewed-on: https://go-review.googlesource.com/c/151403
Reviewed-by: Herbie Ong <herbie@google.com>
diff --git a/go.mod b/go.mod
index 23dca6e..8304ac7 100644
--- a/go.mod
+++ b/go.mod
@@ -1,7 +1,7 @@
 module github.com/golang/protobuf/v2
 
 require (
-	github.com/golang/protobuf v1.2.1-0.20181127190454-8d0c54c12466
+	github.com/golang/protobuf v1.2.1-0.20181129223256-87f1426e5305
 	github.com/google/go-cmp v0.2.1-0.20181101181452-745b8ec83783
-	golang.org/x/tools v0.0.0-20180904205237-0aa4b8830f48
+	golang.org/x/tools v0.0.0-20180928181343-b3c0be4c978b
 )
diff --git a/go.sum b/go.sum
index 605ce4b..f84c3f4 100644
--- a/go.sum
+++ b/go.sum
@@ -1,11 +1,12 @@
-github.com/golang/protobuf v1.2.1-0.20181127190454-8d0c54c12466 h1:Kz9p8XEhFbEfi4ka99LEEwIXF4jqyIdB5fuh7UbMFj4=
+github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
 github.com/golang/protobuf v1.2.1-0.20181127190454-8d0c54c12466/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
-github.com/google/go-cmp v0.2.1-0.20181101181452-745b8ec83783 h1:wVZ6laEGf86tNDTpR5mxFyFIclJJiXCxuJhcQKnsOHk=
+github.com/golang/protobuf v1.2.1-0.20181129223256-87f1426e5305 h1:L8Akf3H3kki1x1DO8Yb3O47G/DspWKG8l8FPNP+Figk=
+github.com/golang/protobuf v1.2.1-0.20181129223256-87f1426e5305/go.mod h1:asK8yRb/+zxJTE0SbTESCku/4OjiDfbPwk4rEyIatUA=
+github.com/golang/protobuf/v2 v2.0.0-20181127193627-d7e97bc71bcb/go.mod h1:MgUD+N3FwzDmj2CdMsT5ap7K7jx+c9cQDQ7fVhmH+Xw=
 github.com/google/go-cmp v0.2.1-0.20181101181452-745b8ec83783/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
-golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
+golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/tools v0.0.0-20180904205237-0aa4b8830f48 h1:PIz+xUHW4G/jqfFWeKhQ96ZV/t2HDsXfWj923rV0bZY=
 golang.org/x/tools v0.0.0-20180904205237-0aa4b8830f48/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180928181343-b3c0be4c978b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
diff --git a/internal/impl/legacy_extension.go b/internal/impl/legacy_extension.go
index a7a28cf..86d1bac 100644
--- a/internal/impl/legacy_extension.go
+++ b/internal/impl/legacy_extension.go
@@ -8,7 +8,7 @@
 	"fmt"
 	"reflect"
 
-	protoV1 "github.com/golang/protobuf/proto"
+	papi "github.com/golang/protobuf/protoapi"
 	ptag "github.com/golang/protobuf/v2/internal/encoding/tag"
 	pvalue "github.com/golang/protobuf/v2/internal/value"
 	pref "github.com/golang/protobuf/v2/reflect/protoreflect"
@@ -25,14 +25,40 @@
 	}
 }
 
+var (
+	extTypeA = reflect.TypeOf(map[int32]papi.ExtensionField(nil))
+	extTypeB = reflect.TypeOf(papi.XXX_InternalExtensions{})
+)
+
+func makeLegacyExtensionMapFunc(t reflect.Type) func(*messageDataType) papi.ExtensionFields {
+	fx1, _ := t.FieldByName("XXX_extensions")
+	fx2, _ := t.FieldByName("XXX_InternalExtensions")
+	switch {
+	case fx1.Type == extTypeA:
+		fieldOffset := offsetOf(fx1)
+		return func(p *messageDataType) papi.ExtensionFields {
+			v := p.p.apply(fieldOffset).asType(fx1.Type).Interface()
+			return papi.ExtensionFieldsOf(v)
+		}
+	case fx2.Type == extTypeB:
+		fieldOffset := offsetOf(fx2)
+		return func(p *messageDataType) papi.ExtensionFields {
+			v := p.p.apply(fieldOffset).asType(fx2.Type).Interface()
+			return papi.ExtensionFieldsOf(v)
+		}
+	default:
+		return nil
+	}
+}
+
 type legacyExtensionFields struct {
 	mi *MessageType
-	x  legacyExtensionIface
+	x  papi.ExtensionFields
 }
 
 func (p legacyExtensionFields) Len() (n int) {
-	p.x.Range(func(num pref.FieldNumber, _ legacyExtensionEntry) bool {
-		if p.Has(num) {
+	p.x.Range(func(num pref.FieldNumber, _ papi.ExtensionField) bool {
+		if p.Has(pref.FieldNumber(num)) {
 			n++
 		}
 		return true
@@ -42,73 +68,73 @@
 
 func (p legacyExtensionFields) Has(n pref.FieldNumber) bool {
 	x := p.x.Get(n)
-	if x.val == nil {
+	if x.Value == nil {
 		return false
 	}
-	t := legacyExtensionTypeOf(x.desc)
+	t := legacyExtensionTypeOf(x.Desc)
 	if t.Cardinality() == pref.Repeated {
-		return t.ValueOf(x.val).List().Len() > 0
+		return t.ValueOf(x.Value).List().Len() > 0
 	}
 	return true
 }
 
 func (p legacyExtensionFields) Get(n pref.FieldNumber) pref.Value {
 	x := p.x.Get(n)
-	if x.desc == nil {
+	if x.Desc == nil {
 		return pref.Value{}
 	}
-	t := legacyExtensionTypeOf(x.desc)
-	if x.val == nil {
-		// NOTE: x.val is never nil for Lists since they are always populated
+	t := legacyExtensionTypeOf(x.Desc)
+	if x.Value == nil {
+		// NOTE: x.Value is never nil for Lists since they are always populated
 		// during ExtensionFieldTypes.Register.
 		if t.Kind() == pref.MessageKind || t.Kind() == pref.GroupKind {
 			return pref.Value{}
 		}
 		return t.Default()
 	}
-	return t.ValueOf(x.val)
+	return t.ValueOf(x.Value)
 }
 
 func (p legacyExtensionFields) Set(n pref.FieldNumber, v pref.Value) {
 	x := p.x.Get(n)
-	if x.desc == nil {
+	if x.Desc == nil {
 		panic("no extension descriptor registered")
 	}
-	t := legacyExtensionTypeOf(x.desc)
-	x.val = t.InterfaceOf(v)
+	t := legacyExtensionTypeOf(x.Desc)
+	x.Value = 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.Desc == nil {
 		return
 	}
-	t := legacyExtensionTypeOf(x.desc)
+	t := legacyExtensionTypeOf(x.Desc)
 	if t.Cardinality() == pref.Repeated {
-		t.ValueOf(x.val).List().Truncate(0)
+		t.ValueOf(x.Value).List().Truncate(0)
 		return
 	}
-	x.val = nil
+	x.Value = nil
 	p.x.Set(n, x)
 }
 
 func (p legacyExtensionFields) Mutable(n pref.FieldNumber) pref.Mutable {
 	x := p.x.Get(n)
-	if x.desc == nil {
+	if x.Desc == nil {
 		panic("no extension descriptor registered")
 	}
-	t := legacyExtensionTypeOf(x.desc)
-	if x.val == nil {
+	t := legacyExtensionTypeOf(x.Desc)
+	if x.Value == nil {
 		v := t.ValueOf(t.New())
-		x.val = t.InterfaceOf(v)
+		x.Value = t.InterfaceOf(v)
 		p.x.Set(n, x)
 	}
-	return t.ValueOf(x.val).Interface().(pref.Mutable)
+	return t.ValueOf(x.Value).Interface().(pref.Mutable)
 }
 
 func (p legacyExtensionFields) Range(f func(pref.FieldNumber, pref.Value) bool) {
-	p.x.Range(func(n pref.FieldNumber, x legacyExtensionEntry) bool {
+	p.x.Range(func(n pref.FieldNumber, x papi.ExtensionField) bool {
 		if p.Has(n) {
 			return f(n, p.Get(n))
 		}
@@ -123,8 +149,8 @@
 type legacyExtensionTypes legacyExtensionFields
 
 func (p legacyExtensionTypes) Len() (n int) {
-	p.x.Range(func(_ pref.FieldNumber, x legacyExtensionEntry) bool {
-		if x.desc != nil {
+	p.x.Range(func(_ pref.FieldNumber, x papi.ExtensionField) bool {
+		if x.Desc != nil {
 			n++
 		}
 		return true
@@ -140,14 +166,14 @@
 		panic("invalid extension field number")
 	}
 	x := p.x.Get(t.Number())
-	if x.desc != nil {
+	if x.Desc != nil {
 		panic("extension descriptor already registered")
 	}
-	x.desc = legacyExtensionDescOf(t, p.mi.goType)
+	x.Desc = legacyExtensionDescOf(t, p.mi.goType)
 	if t.Cardinality() == pref.Repeated {
 		// If the field is repeated, initialize the entry with an empty list
 		// so that future Get operations can return a mutable and concrete list.
-		x.val = t.InterfaceOf(t.ValueOf(t.New()))
+		x.Value = t.InterfaceOf(t.ValueOf(t.New()))
 	}
 	p.x.Set(t.Number(), x)
 }
@@ -159,16 +185,16 @@
 	x := p.x.Get(t.Number())
 	if t.Cardinality() == pref.Repeated {
 		// Treat an empty repeated field as unpopulated.
-		v := reflect.ValueOf(x.val)
-		if x.val == nil || v.IsNil() || v.Elem().Len() == 0 {
-			x.val = nil
+		v := reflect.ValueOf(x.Value)
+		if x.Value == nil || v.IsNil() || v.Elem().Len() == 0 {
+			x.Value = nil
 		}
 	}
-	if x.val != nil {
+	if x.Value != nil {
 		panic("value for extension descriptor still populated")
 	}
-	x.desc = nil
-	if len(x.raw) == 0 {
+	x.Desc = nil
+	if len(x.Raw) == 0 {
 		p.x.Clear(t.Number())
 	} else {
 		p.x.Set(t.Number(), x)
@@ -177,16 +203,16 @@
 
 func (p legacyExtensionTypes) ByNumber(n pref.FieldNumber) pref.ExtensionType {
 	x := p.x.Get(n)
-	if x.desc != nil {
-		return legacyExtensionTypeOf(x.desc)
+	if x.Desc != nil {
+		return legacyExtensionTypeOf(x.Desc)
 	}
 	return nil
 }
 
 func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) {
-	p.x.Range(func(_ pref.FieldNumber, x legacyExtensionEntry) bool {
-		if x.desc != nil && x.desc.Name == string(s) {
-			t = legacyExtensionTypeOf(x.desc)
+	p.x.Range(func(_ pref.FieldNumber, x papi.ExtensionField) bool {
+		if x.Desc != nil && x.Desc.Name == string(s) {
+			t = legacyExtensionTypeOf(x.Desc)
 			return false
 		}
 		return true
@@ -195,9 +221,9 @@
 }
 
 func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) {
-	p.x.Range(func(_ pref.FieldNumber, x legacyExtensionEntry) bool {
-		if x.desc != nil {
-			if !f(legacyExtensionTypeOf(x.desc)) {
+	p.x.Range(func(_ pref.FieldNumber, x papi.ExtensionField) bool {
+		if x.Desc != nil {
+			if !f(legacyExtensionTypeOf(x.Desc)) {
 				return false
 			}
 		}
@@ -205,7 +231,7 @@
 	})
 }
 
-func legacyExtensionDescOf(t pref.ExtensionType, parent reflect.Type) *protoV1.ExtensionDesc {
+func legacyExtensionDescOf(t pref.ExtensionType, parent reflect.Type) *papi.ExtensionDesc {
 	if t, ok := t.(*legacyExtensionType); ok {
 		return t.desc
 	}
@@ -235,8 +261,8 @@
 	}
 
 	// Construct and return a v1 ExtensionDesc.
-	return &protoV1.ExtensionDesc{
-		ExtendedType:  reflect.Zero(parent).Interface().(protoV1.Message),
+	return &papi.ExtensionDesc{
+		ExtendedType:  reflect.Zero(parent).Interface().(papi.Message),
 		ExtensionType: reflect.Zero(extType).Interface(),
 		Field:         int32(t.Number()),
 		Name:          string(t.FullName()),
@@ -244,8 +270,10 @@
 	}
 }
 
-func legacyExtensionTypeOf(d *protoV1.ExtensionDesc) pref.ExtensionType {
-	// TODO: Add a field to protoV1.ExtensionDesc to contain a v2 descriptor.
+func legacyExtensionTypeOf(d *papi.ExtensionDesc) pref.ExtensionType {
+	if d.Type != nil {
+		return d.Type
+	}
 
 	// Derive basic field information from the struct tag.
 	t := reflect.TypeOf(d.ExtensionType)
@@ -330,7 +358,7 @@
 
 type legacyExtensionType struct {
 	pref.ExtensionType
-	desc        *protoV1.ExtensionDesc
+	desc        *papi.ExtensionDesc
 	typ         reflect.Type
 	new         func() interface{}
 	valueOf     func(interface{}) pref.Value
diff --git a/internal/impl/legacy_extension_hack.go b/internal/impl/legacy_extension_hack.go
deleted file mode 100644
index 1ee56cc..0000000
--- a/internal/impl/legacy_extension_hack.go
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package impl
-
-import (
-	"reflect"
-	"sync"
-	"unsafe"
-
-	protoV1 "github.com/golang/protobuf/proto"
-	pref "github.com/golang/protobuf/v2/reflect/protoreflect"
-)
-
-// TODO: The logic in the file is a hack and should be in the v1 repository.
-// We need to break the dependency on proto v1 since it is v1 that will
-// eventually need to depend on v2.
-
-// TODO: The v1 API currently exposes no exported functionality for interacting
-// with the extension data structures. We will need to make changes in v1 so
-// that v2 can access these data structures without relying on unsafe.
-
-var (
-	extTypeA = reflect.TypeOf(map[int32]protoV1.Extension(nil))
-	extTypeB = reflect.TypeOf(protoV1.XXX_InternalExtensions{})
-)
-
-type legacyExtensionIface interface {
-	Len() int
-	Has(pref.FieldNumber) bool
-	Get(pref.FieldNumber) legacyExtensionEntry
-	Set(pref.FieldNumber, legacyExtensionEntry)
-	Clear(pref.FieldNumber)
-	Range(f func(pref.FieldNumber, legacyExtensionEntry) bool)
-}
-
-func makeLegacyExtensionMapFunc(t reflect.Type) func(*messageDataType) legacyExtensionIface {
-	fx1, _ := t.FieldByName("XXX_extensions")
-	fx2, _ := t.FieldByName("XXX_InternalExtensions")
-	switch {
-	case fx1.Type == extTypeA:
-		return func(p *messageDataType) legacyExtensionIface {
-			rv := p.p.asType(t).Elem()
-			return (*legacyExtensionMap)(unsafe.Pointer(rv.UnsafeAddr() + fx1.Offset))
-		}
-	case fx2.Type == extTypeB:
-		return func(p *messageDataType) legacyExtensionIface {
-			rv := p.p.asType(t).Elem()
-			return (*legacyExtensionSyncMap)(unsafe.Pointer(rv.UnsafeAddr() + fx2.Offset))
-		}
-	default:
-		return nil
-	}
-}
-
-// TODO: We currently don't do locking with legacyExtensionSyncMap.p.mu.
-// The locking behavior was already obscure "feature" beforehand,
-// and it is not obvious how it translates to the v2 API.
-// The v2 API presents a Range method, which calls a user provided function,
-// which may in turn call other methods on the map. In such a use case,
-// acquiring a lock within each method would result in a reentrant deadlock.
-
-// legacyExtensionSyncMap is identical to protoV1.XXX_InternalExtensions.
-// It implements legacyExtensionIface.
-type legacyExtensionSyncMap struct {
-	p *struct {
-		mu sync.Mutex
-		m  legacyExtensionMap
-	}
-}
-
-func (m legacyExtensionSyncMap) Len() int {
-	if m.p == nil {
-		return 0
-	}
-	return m.p.m.Len()
-}
-func (m legacyExtensionSyncMap) Has(n pref.FieldNumber) bool {
-	return m.p.m.Has(n)
-}
-func (m legacyExtensionSyncMap) Get(n pref.FieldNumber) legacyExtensionEntry {
-	if m.p == nil {
-		return legacyExtensionEntry{}
-	}
-	return m.p.m.Get(n)
-}
-func (m *legacyExtensionSyncMap) Set(n pref.FieldNumber, x legacyExtensionEntry) {
-	if m.p == nil {
-		m.p = new(struct {
-			mu sync.Mutex
-			m  legacyExtensionMap
-		})
-	}
-	m.p.m.Set(n, x)
-}
-func (m legacyExtensionSyncMap) Clear(n pref.FieldNumber) {
-	m.p.m.Clear(n)
-}
-func (m legacyExtensionSyncMap) Range(f func(pref.FieldNumber, legacyExtensionEntry) bool) {
-	if m.p == nil {
-		return
-	}
-	m.p.m.Range(f)
-}
-
-// legacyExtensionMap is identical to map[int32]protoV1.Extension.
-// It implements legacyExtensionIface.
-type legacyExtensionMap map[pref.FieldNumber]legacyExtensionEntry
-
-func (m legacyExtensionMap) Len() int {
-	return len(m)
-}
-func (m legacyExtensionMap) Has(n pref.FieldNumber) bool {
-	_, ok := m[n]
-	return ok
-}
-func (m legacyExtensionMap) Get(n pref.FieldNumber) legacyExtensionEntry {
-	return m[n]
-}
-func (m *legacyExtensionMap) Set(n pref.FieldNumber, x legacyExtensionEntry) {
-	if *m == nil {
-		*m = make(map[pref.FieldNumber]legacyExtensionEntry)
-	}
-	(*m)[n] = x
-}
-func (m *legacyExtensionMap) Clear(n pref.FieldNumber) {
-	delete(*m, n)
-}
-func (m legacyExtensionMap) Range(f func(pref.FieldNumber, legacyExtensionEntry) bool) {
-	for n, x := range m {
-		if !f(n, x) {
-			return
-		}
-	}
-}
-
-// legacyExtensionEntry is identical to protoV1.Extension.
-type legacyExtensionEntry struct {
-	desc *protoV1.ExtensionDesc
-	val  interface{}
-	raw  []byte
-}
diff --git a/internal/impl/legacy_test.go b/internal/impl/legacy_test.go
index cd5f376..f1fe38f 100644
--- a/internal/impl/legacy_test.go
+++ b/internal/impl/legacy_test.go
@@ -10,7 +10,7 @@
 	"reflect"
 	"testing"
 
-	protoV1 "github.com/golang/protobuf/proto"
+	papi "github.com/golang/protobuf/protoapi"
 	pack "github.com/golang/protobuf/v2/internal/encoding/pack"
 	pragma "github.com/golang/protobuf/v2/internal/pragma"
 	scalar "github.com/golang/protobuf/v2/internal/scalar"
@@ -445,14 +445,14 @@
 
 type legacyTestMessage struct {
 	XXX_unrecognized []byte
-	protoV1.XXX_InternalExtensions
+	papi.XXX_InternalExtensions
 }
 
 func (*legacyTestMessage) Reset()         {}
 func (*legacyTestMessage) String() string { return "" }
 func (*legacyTestMessage) ProtoMessage()  {}
-func (*legacyTestMessage) ExtensionRangeArray() []protoV1.ExtensionRange {
-	return []protoV1.ExtensionRange{{Start: 10, End: 20}, {Start: 40, End: 80}, {Start: 10000, End: 20000}}
+func (*legacyTestMessage) ExtensionRangeArray() []papi.ExtensionRange {
+	return []papi.ExtensionRange{{Start: 10, End: 20}, {Start: 40, End: 80}, {Start: 10000, End: 20000}}
 }
 
 func TestLegacyUnknown(t *testing.T) {
@@ -684,7 +684,7 @@
 
 func TestLegactExtensions(t *testing.T) {
 	extensions := []pref.ExtensionType{
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: (*bool)(nil),
 			Field:         10000,
@@ -692,7 +692,7 @@
 			Tag:           "varint,10000,opt,name=optional_bool,json=optionalBool,def=1",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: (*int32)(nil),
 			Field:         10001,
@@ -700,7 +700,7 @@
 			Tag:           "varint,10001,opt,name=optional_int32,json=optionalInt32,def=-12345",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: (*uint32)(nil),
 			Field:         10002,
@@ -708,7 +708,7 @@
 			Tag:           "varint,10002,opt,name=optional_uint32,json=optionalUint32,def=3200",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: (*float32)(nil),
 			Field:         10003,
@@ -716,7 +716,7 @@
 			Tag:           "fixed32,10003,opt,name=optional_float,json=optionalFloat,def=3.14159",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: (*string)(nil),
 			Field:         10004,
@@ -724,7 +724,7 @@
 			Tag:           "bytes,10004,opt,name=optional_string,json=optionalString,def=hello, \"world!\"\n",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: ([]byte)(nil),
 			Field:         10005,
@@ -732,7 +732,7 @@
 			Tag:           "bytes,10005,opt,name=optional_bytes,json=optionalBytes,def=dead\\336\\255\\276\\357beef",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: (*proto2_20180125.Message_ChildEnum)(nil),
 			Field:         10006,
@@ -740,7 +740,7 @@
 			Tag:           "varint,10006,opt,name=optional_enum_v1,json=optionalEnumV1,enum=google.golang.org.proto2_20180125.Message_ChildEnum,def=0",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: (*proto2_20180125.Message_ChildMessage)(nil),
 			Field:         10007,
@@ -748,7 +748,7 @@
 			Tag:           "bytes,10007,opt,name=optional_message_v1,json=optionalMessageV1",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: (*EnumProto2)(nil),
 			Field:         10008,
@@ -756,7 +756,7 @@
 			Tag:           "varint,10008,opt,name=optional_enum_v2,json=optionalEnumV2,enum=EnumProto2,def=57005",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: (*EnumMessages)(nil),
 			Field:         10009,
@@ -764,7 +764,7 @@
 			Tag:           "bytes,10009,opt,name=optional_message_v2,json=optionalMessageV2",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: ([]bool)(nil),
 			Field:         10010,
@@ -772,7 +772,7 @@
 			Tag:           "varint,10010,rep,name=repeated_bool,json=repeatedBool",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: ([]int32)(nil),
 			Field:         10011,
@@ -780,7 +780,7 @@
 			Tag:           "varint,10011,rep,name=repeated_int32,json=repeatedInt32",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: ([]uint32)(nil),
 			Field:         10012,
@@ -788,7 +788,7 @@
 			Tag:           "varint,10012,rep,name=repeated_uint32,json=repeatedUint32",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: ([]float32)(nil),
 			Field:         10013,
@@ -796,7 +796,7 @@
 			Tag:           "fixed32,10013,rep,name=repeated_float,json=repeatedFloat",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: ([]string)(nil),
 			Field:         10014,
@@ -804,7 +804,7 @@
 			Tag:           "bytes,10014,rep,name=repeated_string,json=repeatedString",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: ([][]byte)(nil),
 			Field:         10015,
@@ -812,7 +812,7 @@
 			Tag:           "bytes,10015,rep,name=repeated_bytes,json=repeatedBytes",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: ([]proto2_20180125.Message_ChildEnum)(nil),
 			Field:         10016,
@@ -820,7 +820,7 @@
 			Tag:           "varint,10016,rep,name=repeated_enum_v1,json=repeatedEnumV1,enum=google.golang.org.proto2_20180125.Message_ChildEnum",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: ([]*proto2_20180125.Message_ChildMessage)(nil),
 			Field:         10017,
@@ -828,7 +828,7 @@
 			Tag:           "bytes,10017,rep,name=repeated_message_v1,json=repeatedMessageV1",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: ([]EnumProto2)(nil),
 			Field:         10018,
@@ -836,7 +836,7 @@
 			Tag:           "varint,10018,rep,name=repeated_enum_v2,json=repeatedEnumV2,enum=EnumProto2",
 			Filename:      "fizz/buzz/test.proto",
 		}),
-		legacyExtensionTypeOf(&protoV1.ExtensionDesc{
+		legacyExtensionTypeOf(&papi.ExtensionDesc{
 			ExtendedType:  (*legacyTestMessage)(nil),
 			ExtensionType: ([]*EnumMessages)(nil),
 			Field:         10019,
diff --git a/internal/impl/legacy_unknown.go b/internal/impl/legacy_unknown.go
index e0cb035..0492eca 100644
--- a/internal/impl/legacy_unknown.go
+++ b/internal/impl/legacy_unknown.go
@@ -9,6 +9,7 @@
 	"reflect"
 	"sort"
 
+	papi "github.com/golang/protobuf/protoapi"
 	"github.com/golang/protobuf/v2/internal/encoding/wire"
 	pref "github.com/golang/protobuf/v2/reflect/protoreflect"
 )
@@ -40,14 +41,14 @@
 // and also the extension field map.
 type legacyUnknownBytesAndExtensionMap struct {
 	u pref.UnknownFields
-	x legacyExtensionIface
+	x papi.ExtensionFields
 	r pref.FieldRanges
 }
 
 func (fs *legacyUnknownBytesAndExtensionMap) Len() int {
 	n := fs.u.Len()
-	fs.x.Range(func(_ pref.FieldNumber, x legacyExtensionEntry) bool {
-		if len(x.raw) > 0 {
+	fs.x.Range(func(_ pref.FieldNumber, x papi.ExtensionField) bool {
+		if len(x.Raw) > 0 {
 			n++
 		}
 		return true
@@ -57,7 +58,7 @@
 
 func (fs *legacyUnknownBytesAndExtensionMap) Get(num pref.FieldNumber) (raw pref.RawFields) {
 	if fs.r.Has(num) {
-		return fs.x.Get(num).raw
+		return fs.x.Get(num).Raw
 	}
 	return fs.u.Get(num)
 }
@@ -65,7 +66,7 @@
 func (fs *legacyUnknownBytesAndExtensionMap) Set(num pref.FieldNumber, raw pref.RawFields) {
 	if fs.r.Has(num) {
 		x := fs.x.Get(num)
-		x.raw = raw
+		x.Raw = raw
 		fs.x.Set(num, x)
 		return
 	}
@@ -91,9 +92,9 @@
 		raw pref.RawFields
 	}
 	var xs []entry
-	fs.x.Range(func(n pref.FieldNumber, x legacyExtensionEntry) bool {
-		if len(x.raw) > 0 {
-			xs = append(xs, entry{n, x.raw})
+	fs.x.Range(func(n pref.FieldNumber, x papi.ExtensionField) bool {
+		if len(x.Raw) > 0 {
+			xs = append(xs, entry{n, x.Raw})
 		}
 		return true
 	})
diff --git a/internal/impl/message_test.go b/internal/impl/message_test.go
index 5637b92..6d82456 100644
--- a/internal/impl/message_test.go
+++ b/internal/impl/message_test.go
@@ -765,8 +765,8 @@
 func (m *OneofScalars) ProtoReflect() pref.Message        { return m }
 func (m *OneofScalars) ProtoMutable()                     {}
 
-func (*OneofScalars) XXX_OneofFuncs() (func(protoV1.Message, *protoV1.Buffer) error, func(protoV1.Message, int, int, *protoV1.Buffer) (bool, error), func(protoV1.Message) int, []interface{}) {
-	return nil, nil, nil, []interface{}{
+func (*OneofScalars) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
 		(*OneofScalars_Bool)(nil),
 		(*OneofScalars_Int32)(nil),
 		(*OneofScalars_Int64)(nil),
@@ -985,8 +985,8 @@
 func (m *EnumMessages) ProtoReflect() pref.Message        { return m }
 func (m *EnumMessages) ProtoMutable()                     {}
 
-func (*EnumMessages) XXX_OneofFuncs() (func(protoV1.Message, *protoV1.Buffer) error, func(protoV1.Message, int, int, *protoV1.Buffer) (bool, error), func(protoV1.Message) int, []interface{}) {
-	return nil, nil, nil, []interface{}{
+func (*EnumMessages) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
 		(*EnumMessages_OneofE2)(nil),
 		(*EnumMessages_OneofE3)(nil),
 		(*EnumMessages_OneofM2)(nil),
diff --git a/internal/value/convert.go b/internal/value/convert.go
index e491fd1..6660d44 100644
--- a/internal/value/convert.go
+++ b/internal/value/convert.go
@@ -10,6 +10,7 @@
 	"fmt"
 	"reflect"
 
+	papi "github.com/golang/protobuf/protoapi"
 	pref "github.com/golang/protobuf/v2/reflect/protoreflect"
 )
 
@@ -19,13 +20,6 @@
 	Unwrap() interface{}
 }
 
-// messageV1 is the protoV1.Message interface.
-type messageV1 = interface {
-	Reset()
-	String() string
-	ProtoMessage()
-}
-
 var (
 	boolType    = reflect.TypeOf(bool(false))
 	int32Type   = reflect.TypeOf(int32(0))
@@ -38,7 +32,7 @@
 	bytesType   = reflect.TypeOf([]byte(nil))
 
 	enumIfaceV2    = reflect.TypeOf((*pref.ProtoEnum)(nil)).Elem()
-	messageIfaceV1 = reflect.TypeOf((*messageV1)(nil)).Elem()
+	messageIfaceV1 = reflect.TypeOf((*papi.Message)(nil)).Elem()
 	messageIfaceV2 = reflect.TypeOf((*pref.ProtoMessage)(nil)).Elem()
 
 	byteType = reflect.TypeOf(byte(0))