all: use v2 Message interface for weak fields

Cleanup the generated logic by having the implementation be backed
by protoimpl rather that directly generated.

Weak fields are a deprecated feature of protobufs and
have entirely be superceded by extensions.
Unfortunately, there are still some usages of it.

Change-Id: Ie1a4b7da253e2ccf5e56627775d9b2fb4090d59a
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/229717
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/impl/weak.go b/internal/impl/weak.go
index 575c988..009cbef 100644
--- a/internal/impl/weak.go
+++ b/internal/impl/weak.go
@@ -5,9 +5,10 @@
 package impl
 
 import (
-	"reflect"
+	"fmt"
 
 	pref "google.golang.org/protobuf/reflect/protoreflect"
+	"google.golang.org/protobuf/reflect/protoregistry"
 )
 
 // weakFields adds methods to the exported WeakFields type for internal use.
@@ -16,31 +17,58 @@
 // defined directly on it.
 type weakFields WeakFields
 
-func (w *weakFields) get(num pref.FieldNumber) (_ pref.ProtoMessage, ok bool) {
-	if *w == nil {
-		return nil, false
-	}
-	m, ok := (*w)[int32(num)]
-	if !ok {
-		return nil, false
-	}
-	// As a legacy quirk, consider a typed nil to be unset.
-	//
-	// TODO: Consider fixing the generated set methods to clear the field
-	// when provided with a typed nil.
-	if v := reflect.ValueOf(m); v.Kind() == reflect.Ptr && v.IsNil() {
-		return nil, false
-	}
-	return Export{}.ProtoMessageV2Of(m), true
+func (w weakFields) get(num pref.FieldNumber) (pref.ProtoMessage, bool) {
+	m, ok := w[int32(num)]
+	return m, ok
 }
 
 func (w *weakFields) set(num pref.FieldNumber, m pref.ProtoMessage) {
 	if *w == nil {
 		*w = make(weakFields)
 	}
-	(*w)[int32(num)] = Export{}.ProtoMessageV1Of(m)
+	(*w)[int32(num)] = m
 }
 
 func (w *weakFields) clear(num pref.FieldNumber) {
 	delete(*w, int32(num))
 }
+
+func (Export) HasWeak(w WeakFields, num pref.FieldNumber) bool {
+	_, ok := w[int32(num)]
+	return ok
+}
+
+func (Export) ClearWeak(w *WeakFields, num pref.FieldNumber) {
+	delete(*w, int32(num))
+}
+
+func (Export) GetWeak(w WeakFields, num pref.FieldNumber, name pref.FullName) pref.ProtoMessage {
+	if m, ok := w[int32(num)]; ok {
+		return m
+	}
+	mt, _ := protoregistry.GlobalTypes.FindMessageByName(name)
+	if mt == nil {
+		panic(fmt.Sprintf("message %v for weak field is not linked in", name))
+	}
+	return mt.Zero().Interface()
+}
+
+func (Export) SetWeak(w *WeakFields, num pref.FieldNumber, name pref.FullName, m pref.ProtoMessage) {
+	if m != nil {
+		mt, _ := protoregistry.GlobalTypes.FindMessageByName(name)
+		if mt == nil {
+			panic(fmt.Sprintf("message %v for weak field is not linked in", name))
+		}
+		if mt != m.ProtoReflect().Type() {
+			panic(fmt.Sprintf("invalid message type for weak field: got %T, want %T", m, mt.Zero().Interface()))
+		}
+	}
+	if m == nil || !m.ProtoReflect().IsValid() {
+		delete(*w, int32(num))
+		return
+	}
+	if *w == nil {
+		*w = make(weakFields)
+	}
+	(*w)[int32(num)] = m
+}