proto: Add CloneOf[M Message](m M) M

This allows writing:
  `copy := proto.CloneOf(orig)`
instead of the previous:
  `copy := proto.Clone(orig).(*pb.MyMessage)`

Fixes golang/protobuf#1594

Change-Id: I7b8b712b6e59607ccc339720ee3c146e8a7ea28b
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/653536
Reviewed-by: Cassondra Foesch <cfoesch@gmail.com>
Reviewed-by: Michael Stapelberg <stapelberg@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/proto/merge.go b/proto/merge.go
index 3c6fe57..ef55b97 100644
--- a/proto/merge.go
+++ b/proto/merge.go
@@ -59,6 +59,12 @@
 	return dst.Interface()
 }
 
+// CloneOf returns a deep copy of m. If the top-level message is invalid,
+// it returns an invalid message as well.
+func CloneOf[M Message](m M) M {
+	return Clone(m).(M)
+}
+
 // mergeOptions provides a namespace for merge functions, and can be
 // exported in the future if we add user-visible merge options.
 type mergeOptions struct{}
diff --git a/proto/merge_test.go b/proto/merge_test.go
index 05978cb..2cdc1b7 100644
--- a/proto/merge_test.go
+++ b/proto/merge_test.go
@@ -853,6 +853,16 @@
 	}
 }
 
+func TestCloneOf(t *testing.T) {
+	want := &testpb.TestAllTypes{
+		OptionalInt32: proto.Int32(1),
+	}
+	got := proto.CloneOf(want)
+	if !proto.Equal(got, want) {
+		t.Errorf("Clone(src) != src:\n got %v\nwant %v", got, want)
+	}
+}
+
 // mutateValue changes a Value, returning a new value.
 //
 // For scalar values, it returns a value different from the input.