proto: add Equal

Add support for basic equality comparison of messages.

Messages are equal if they have the same type and marshal to the
same bytes with deterministic serialization, with some exceptions:

 - Messages with different registered extensions are unequal.
 - NaN is not equal to itself.

Unlike the v1 Equal, a nil message is equal to an empty message of
the same type.

Change-Id: Ibabdadd8c767b801051b8241aeae1ba077e58121
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/174277
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/internal/testprotos/test/test.pb.go b/internal/testprotos/test/test.pb.go
index 263dd3a..454e974 100644
--- a/internal/testprotos/test/test.pb.go
+++ b/internal/testprotos/test/test.pb.go
@@ -2019,6 +2019,126 @@
 	},
 	{
 		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*int32)(nil),
+		Field:         81,
+		Name:          "goproto.proto.test.default_int32_extension",
+		Tag:           "varint,81,opt,name=default_int32_extension,def=81",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*int64)(nil),
+		Field:         82,
+		Name:          "goproto.proto.test.default_int64_extension",
+		Tag:           "varint,82,opt,name=default_int64_extension,def=82",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*uint32)(nil),
+		Field:         83,
+		Name:          "goproto.proto.test.default_uint32_extension",
+		Tag:           "varint,83,opt,name=default_uint32_extension,def=83",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*uint64)(nil),
+		Field:         84,
+		Name:          "goproto.proto.test.default_uint64_extension",
+		Tag:           "varint,84,opt,name=default_uint64_extension,def=84",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*int32)(nil),
+		Field:         85,
+		Name:          "goproto.proto.test.default_sint32_extension",
+		Tag:           "zigzag32,85,opt,name=default_sint32_extension,def=-85",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*int64)(nil),
+		Field:         86,
+		Name:          "goproto.proto.test.default_sint64_extension",
+		Tag:           "zigzag64,86,opt,name=default_sint64_extension,def=86",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*uint32)(nil),
+		Field:         87,
+		Name:          "goproto.proto.test.default_fixed32_extension",
+		Tag:           "fixed32,87,opt,name=default_fixed32_extension,def=87",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*uint64)(nil),
+		Field:         88,
+		Name:          "goproto.proto.test.default_fixed64_extension",
+		Tag:           "fixed64,88,opt,name=default_fixed64_extension,def=88",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*int32)(nil),
+		Field:         89,
+		Name:          "goproto.proto.test.default_sfixed32_extension",
+		Tag:           "fixed32,89,opt,name=default_sfixed32_extension,def=89",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*int64)(nil),
+		Field:         80,
+		Name:          "goproto.proto.test.default_sfixed64_extension",
+		Tag:           "fixed64,80,opt,name=default_sfixed64_extension,def=-90",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*float32)(nil),
+		Field:         91,
+		Name:          "goproto.proto.test.default_float_extension",
+		Tag:           "fixed32,91,opt,name=default_float_extension,def=91.5",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*float64)(nil),
+		Field:         92,
+		Name:          "goproto.proto.test.default_double_extension",
+		Tag:           "fixed64,92,opt,name=default_double_extension,def=92000",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*bool)(nil),
+		Field:         93,
+		Name:          "goproto.proto.test.default_bool_extension",
+		Tag:           "varint,93,opt,name=default_bool_extension,def=1",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: (*string)(nil),
+		Field:         94,
+		Name:          "goproto.proto.test.default_string_extension",
+		Tag:           "bytes,94,opt,name=default_string_extension,def=hello",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
+		ExtensionType: ([]byte)(nil),
+		Field:         95,
+		Name:          "goproto.proto.test.default_bytes_extension",
+		Tag:           "bytes,95,opt,name=default_bytes_extension,def=world",
+		Filename:      "test/test.proto",
+	},
+	{
+		ExtendedType:  (*TestAllExtensions)(nil),
 		ExtensionType: (*string)(nil),
 		Field:         1003,
 		Name:          "goproto.proto.test.TestNestedExtension.nested_string_extension",
@@ -2151,14 +2271,59 @@
 	// extend goproto.proto.test.TestAllExtensions { repeated goproto.proto.test.TestAllTypes.NestedEnum repeated_nested_enum_extension = 51; }
 	E_RepeatedNestedEnumExtension = &file_test_test_proto_extDescs[35]
 
+	// extend goproto.proto.test.TestAllExtensions { optional int32 default_int32_extension = 81; }
+	E_DefaultInt32Extension = &file_test_test_proto_extDescs[36]
+
+	// extend goproto.proto.test.TestAllExtensions { optional int64 default_int64_extension = 82; }
+	E_DefaultInt64Extension = &file_test_test_proto_extDescs[37]
+
+	// extend goproto.proto.test.TestAllExtensions { optional uint32 default_uint32_extension = 83; }
+	E_DefaultUint32Extension = &file_test_test_proto_extDescs[38]
+
+	// extend goproto.proto.test.TestAllExtensions { optional uint64 default_uint64_extension = 84; }
+	E_DefaultUint64Extension = &file_test_test_proto_extDescs[39]
+
+	// extend goproto.proto.test.TestAllExtensions { optional sint32 default_sint32_extension = 85; }
+	E_DefaultSint32Extension = &file_test_test_proto_extDescs[40]
+
+	// extend goproto.proto.test.TestAllExtensions { optional sint64 default_sint64_extension = 86; }
+	E_DefaultSint64Extension = &file_test_test_proto_extDescs[41]
+
+	// extend goproto.proto.test.TestAllExtensions { optional fixed32 default_fixed32_extension = 87; }
+	E_DefaultFixed32Extension = &file_test_test_proto_extDescs[42]
+
+	// extend goproto.proto.test.TestAllExtensions { optional fixed64 default_fixed64_extension = 88; }
+	E_DefaultFixed64Extension = &file_test_test_proto_extDescs[43]
+
+	// extend goproto.proto.test.TestAllExtensions { optional sfixed32 default_sfixed32_extension = 89; }
+	E_DefaultSfixed32Extension = &file_test_test_proto_extDescs[44]
+
+	// extend goproto.proto.test.TestAllExtensions { optional sfixed64 default_sfixed64_extension = 80; }
+	E_DefaultSfixed64Extension = &file_test_test_proto_extDescs[45]
+
+	// extend goproto.proto.test.TestAllExtensions { optional float default_float_extension = 91; }
+	E_DefaultFloatExtension = &file_test_test_proto_extDescs[46]
+
+	// extend goproto.proto.test.TestAllExtensions { optional double default_double_extension = 92; }
+	E_DefaultDoubleExtension = &file_test_test_proto_extDescs[47]
+
+	// extend goproto.proto.test.TestAllExtensions { optional bool default_bool_extension = 93; }
+	E_DefaultBoolExtension = &file_test_test_proto_extDescs[48]
+
+	// extend goproto.proto.test.TestAllExtensions { optional string default_string_extension = 94; }
+	E_DefaultStringExtension = &file_test_test_proto_extDescs[49]
+
+	// extend goproto.proto.test.TestAllExtensions { optional bytes default_bytes_extension = 95; }
+	E_DefaultBytesExtension = &file_test_test_proto_extDescs[50]
+
 	// extend goproto.proto.test.TestAllExtensions { optional string nested_string_extension = 1003; }
-	E_TestNestedExtension_NestedStringExtension = &file_test_test_proto_extDescs[36]
+	E_TestNestedExtension_NestedStringExtension = &file_test_test_proto_extDescs[51]
 
 	// extend goproto.proto.test.TestAllExtensions { optional goproto.proto.test.TestRequired single = 1000; }
-	E_TestRequired_Single = &file_test_test_proto_extDescs[37]
+	E_TestRequired_Single = &file_test_test_proto_extDescs[52]
 
 	// extend goproto.proto.test.TestAllExtensions { repeated goproto.proto.test.TestRequired multi = 1001; }
-	E_TestRequired_Multi = &file_test_test_proto_extDescs[38]
+	E_TestRequired_Multi = &file_test_test_proto_extDescs[53]
 )
 var File_test_test_proto protoreflect.FileDescriptor
 
@@ -2969,11 +3134,107 @@
 	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x41,
 	0x6c, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x45, 0x6e,
 	0x75, 0x6d, 0x52, 0x1b, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x65, 0x73, 0x74,
-	0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x42,
-	0x38, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f,
-	0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x76, 0x32,
-	0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x50, 0x01, 0x58, 0x02,
+	0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3a,
+	0x61, 0x0a, 0x17, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32,
+	0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x67, 0x6f, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e,
+	0x54, 0x65, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
+	0x73, 0x18, 0x51, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x02, 0x38, 0x31, 0x52, 0x15, 0x64, 0x65, 0x66,
+	0x61, 0x75, 0x6c, 0x74, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
+	0x6f, 0x6e, 0x3a, 0x61, 0x0a, 0x17, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x69, 0x6e,
+	0x74, 0x36, 0x34, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e,
+	0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x65,
+	0x73, 0x74, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73,
+	0x69, 0x6f, 0x6e, 0x73, 0x18, 0x52, 0x20, 0x01, 0x28, 0x03, 0x3a, 0x02, 0x38, 0x32, 0x52, 0x15,
+	0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x45, 0x78, 0x74, 0x65,
+	0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x63, 0x0a, 0x18, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
+	0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+	0x6e, 0x12, 0x25, 0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x78,
+	0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x53, 0x20, 0x01, 0x28, 0x0d, 0x3a, 0x02,
+	0x38, 0x33, 0x52, 0x16, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x55, 0x69, 0x6e, 0x74, 0x33,
+	0x32, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x63, 0x0a, 0x18, 0x64, 0x65,
+	0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x65, 0x78, 0x74,
+	0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x65, 0x73, 0x74,
+	0x41, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x54, 0x20,
+	0x01, 0x28, 0x04, 0x3a, 0x02, 0x38, 0x34, 0x52, 0x16, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
+	0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3a,
+	0x64, 0x0a, 0x18, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x73, 0x69, 0x6e, 0x74, 0x33,
+	0x32, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x67, 0x6f,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74,
+	0x2e, 0x54, 0x65, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+	0x6e, 0x73, 0x18, 0x55, 0x20, 0x01, 0x28, 0x11, 0x3a, 0x03, 0x2d, 0x38, 0x35, 0x52, 0x16, 0x64,
+	0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x45, 0x78, 0x74, 0x65,
+	0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x63, 0x0a, 0x18, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
+	0x5f, 0x73, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+	0x6e, 0x12, 0x25, 0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x78,
+	0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x56, 0x20, 0x01, 0x28, 0x12, 0x3a, 0x02,
+	0x38, 0x36, 0x52, 0x16, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x69, 0x6e, 0x74, 0x36,
+	0x34, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x65, 0x0a, 0x19, 0x64, 0x65,
+	0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x5f, 0x65, 0x78,
+	0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x65, 0x73,
+	0x74, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x57,
+	0x20, 0x01, 0x28, 0x07, 0x3a, 0x02, 0x38, 0x37, 0x52, 0x17, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c,
+	0x74, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+	0x6e, 0x3a, 0x65, 0x0a, 0x19, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x66, 0x69, 0x78,
+	0x65, 0x64, 0x36, 0x34, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25,
+	0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74,
+	0x65, 0x73, 0x74, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e,
+	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x58, 0x20, 0x01, 0x28, 0x06, 0x3a, 0x02, 0x38, 0x38, 0x52,
+	0x17, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x45,
+	0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x67, 0x0a, 0x1a, 0x64, 0x65, 0x66, 0x61,
+	0x75, 0x6c, 0x74, 0x5f, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x5f, 0x65, 0x78, 0x74,
+	0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x65, 0x73, 0x74,
+	0x41, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x59, 0x20,
+	0x01, 0x28, 0x0f, 0x3a, 0x02, 0x38, 0x39, 0x52, 0x18, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
+	0x53, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+	0x6e, 0x3a, 0x68, 0x0a, 0x1a, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x73, 0x66, 0x69,
+	0x78, 0x65, 0x64, 0x36, 0x34, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12,
+	0x25, 0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+	0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65,
+	0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x50, 0x20, 0x01, 0x28, 0x10, 0x3a, 0x03, 0x2d, 0x39,
+	0x30, 0x52, 0x18, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x66, 0x69, 0x78, 0x65, 0x64,
+	0x36, 0x34, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x63, 0x0a, 0x17, 0x64,
+	0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x5f, 0x65, 0x78, 0x74,
+	0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x65, 0x73, 0x74,
+	0x41, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x5b, 0x20,
+	0x01, 0x28, 0x02, 0x3a, 0x04, 0x39, 0x31, 0x2e, 0x35, 0x52, 0x15, 0x64, 0x65, 0x66, 0x61, 0x75,
+	0x6c, 0x74, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
+	0x3a, 0x66, 0x0a, 0x18, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x64, 0x6f, 0x75, 0x62,
+	0x6c, 0x65, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x67,
+	0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x65, 0x73,
+	0x74, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
+	0x6f, 0x6e, 0x73, 0x18, 0x5c, 0x20, 0x01, 0x28, 0x01, 0x3a, 0x05, 0x39, 0x32, 0x30, 0x30, 0x30,
+	0x52, 0x16, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x45,
+	0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x61, 0x0a, 0x16, 0x64, 0x65, 0x66, 0x61,
+	0x75, 0x6c, 0x74, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
+	0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x45,
+	0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x5d, 0x20, 0x01, 0x28, 0x08, 0x3a,
+	0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x14, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x42, 0x6f,
+	0x6f, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x66, 0x0a, 0x18, 0x64,
+	0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x78,
+	0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x65, 0x73,
+	0x74, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x5e,
+	0x20, 0x01, 0x28, 0x09, 0x3a, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x16, 0x64, 0x65, 0x66,
+	0x61, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73,
+	0x69, 0x6f, 0x6e, 0x3a, 0x64, 0x0a, 0x17, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x62,
+	0x79, 0x74, 0x65, 0x73, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25,
+	0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74,
+	0x65, 0x73, 0x74, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e,
+	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x5f, 0x20, 0x01, 0x28, 0x0c, 0x3a, 0x05, 0x77, 0x6f, 0x72,
+	0x6c, 0x64, 0x52, 0x15, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73,
+	0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, 0x74,
+	0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x76, 0x32, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
+	0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x74,
+	0x65, 0x73, 0x74, 0x50, 0x01, 0x58, 0x02,
 }
 
 var (
@@ -3071,6 +3332,21 @@
 	8,  // goproto.proto.test.repeatedgroup_extension:extendee -> goproto.proto.test.TestAllExtensions
 	8,  // goproto.proto.test.repeated_nested_message_extension:extendee -> goproto.proto.test.TestAllExtensions
 	8,  // goproto.proto.test.repeated_nested_enum_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_int32_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_int64_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_uint32_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_uint64_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_sint32_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_sint64_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_fixed32_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_fixed64_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_sfixed32_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_sfixed64_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_float_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_double_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_bool_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_string_extension:extendee -> goproto.proto.test.TestAllExtensions
+	8,  // goproto.proto.test.default_bytes_extension:extendee -> goproto.proto.test.TestAllExtensions
 	8,  // goproto.proto.test.TestNestedExtension.nested_string_extension:extendee -> goproto.proto.test.TestAllExtensions
 	8,  // goproto.proto.test.TestRequired.single:extendee -> goproto.proto.test.TestAllExtensions
 	8,  // goproto.proto.test.TestRequired.multi:extendee -> goproto.proto.test.TestAllExtensions
@@ -3142,7 +3418,7 @@
 	file_test_test_import_proto_init()
 	file_test_test_public_proto_init()
 	file_test_test_weak_proto_init()
-	extensionTypes := make([]protoreflect.ExtensionType, 39)
+	extensionTypes := make([]protoreflect.ExtensionType, 54)
 	File_test_test_proto = protoimpl.FileBuilder{
 		RawDescriptor:        file_test_test_proto_rawDesc,
 		GoTypes:              file_test_test_proto_goTypes,
diff --git a/internal/testprotos/test/test.proto b/internal/testprotos/test/test.proto
index c6b2d6a..de32b96 100644
--- a/internal/testprotos/test/test.proto
+++ b/internal/testprotos/test/test.proto
@@ -210,6 +210,22 @@
 
   repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48;
   repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51;
+
+  optional int32    default_int32_extension    = 81 [default =  81    ];
+  optional int64    default_int64_extension    = 82 [default =  82    ];
+  optional uint32   default_uint32_extension   = 83 [default =  83    ];
+  optional uint64   default_uint64_extension   = 84 [default =  84    ];
+  optional sint32   default_sint32_extension   = 85 [default = -85    ];
+  optional sint64   default_sint64_extension   = 86 [default =  86    ];
+  optional fixed32  default_fixed32_extension  = 87 [default =  87    ];
+  optional fixed64  default_fixed64_extension  = 88 [default =  88    ];
+  optional sfixed32 default_sfixed32_extension = 89 [default =  89    ];
+  optional sfixed64 default_sfixed64_extension = 80 [default = -90    ];
+  optional float    default_float_extension    = 91 [default =  91.5  ];
+  optional double   default_double_extension   = 92 [default =  92e3  ];
+  optional bool     default_bool_extension     = 93 [default = true   ];
+  optional string   default_string_extension   = 94 [default = "hello"];
+  optional bytes    default_bytes_extension    = 95 [default = "world"];
 }
 
 message TestNestedExtension {
diff --git a/proto/decode_test.go b/proto/decode_test.go
index 2c95f6b..084014f 100644
--- a/proto/decode_test.go
+++ b/proto/decode_test.go
@@ -16,6 +16,7 @@
 	"github.com/golang/protobuf/v2/internal/scalar"
 	"github.com/golang/protobuf/v2/proto"
 	pref "github.com/golang/protobuf/v2/reflect/protoreflect"
+	"github.com/golang/protobuf/v2/runtime/protolegacy"
 
 	testpb "github.com/golang/protobuf/v2/internal/testprotos/test"
 	test3pb "github.com/golang/protobuf/v2/internal/testprotos/test3"
@@ -1254,6 +1255,13 @@
 	}
 }
 
+func registerExtension(desc *protoV1.ExtensionDesc) buildOpt {
+	return func(m proto.Message) {
+		et := protolegacy.X.ExtensionTypeFromDesc(desc)
+		m.ProtoReflect().KnownFields().ExtensionTypes().Register(et)
+	}
+}
+
 func extend(desc *protoV1.ExtensionDesc, value interface{}) buildOpt {
 	return func(m proto.Message) {
 		if err := protoV1.SetExtension(m.(protoV1.Message), desc, value); err != nil {
diff --git a/proto/encode_test.go b/proto/encode_test.go
index d670edf..6ed5250 100644
--- a/proto/encode_test.go
+++ b/proto/encode_test.go
@@ -8,6 +8,7 @@
 
 	protoV1 "github.com/golang/protobuf/proto"
 	"github.com/golang/protobuf/v2/proto"
+	pref "github.com/golang/protobuf/v2/reflect/protoreflect"
 	"github.com/google/go-cmp/cmp"
 
 	test3pb "github.com/golang/protobuf/v2/internal/testprotos/test3"
@@ -30,7 +31,7 @@
 					t.Errorf("Size and marshal disagree: Size(m)=%v; len(Marshal(m))=%v\nMessage:\n%v", size, len(wire), marshalText(want))
 				}
 
-				got := reflect.New(reflect.TypeOf(want).Elem()).Interface().(proto.Message)
+				got := newMessage(want)
 				uopts := proto.UnmarshalOptions{
 					AllowPartial: test.partial,
 				}
@@ -43,7 +44,7 @@
 					// Equal doesn't work on messages containing invalid extension data.
 					return
 				}
-				if !protoV1.Equal(got.(protoV1.Message), want.(protoV1.Message)) {
+				if !proto.Equal(got, want) {
 					t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", protoV1.MarshalTextString(got.(protoV1.Message)), protoV1.MarshalTextString(want.(protoV1.Message)))
 				}
 			})
@@ -71,7 +72,7 @@
 					t.Fatalf("deterministic marshal returned varying results:\n%v", cmp.Diff(wire, wire2))
 				}
 
-				got := reflect.New(reflect.TypeOf(want).Elem()).Interface().(proto.Message)
+				got := newMessage(want)
 				uopts := proto.UnmarshalOptions{
 					AllowPartial: test.partial,
 				}
@@ -84,7 +85,7 @@
 					// Equal doesn't work on messages containing invalid extension data.
 					return
 				}
-				if !protoV1.Equal(got.(protoV1.Message), want.(protoV1.Message)) {
+				if !proto.Equal(got, want) {
 					t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", marshalText(got), marshalText(want))
 				}
 			})
@@ -100,12 +101,12 @@
 				if !isErrInvalidUTF8(err) {
 					t.Errorf("Marshal did not return expected error for invalid UTF8: %v\nMessage:\n%v", err, marshalText(want))
 				}
-				got := reflect.New(reflect.TypeOf(want).Elem()).Interface().(proto.Message)
+				got := newMessage(want)
 				if err := proto.Unmarshal(wire, got); !isErrInvalidUTF8(err) {
 					t.Errorf("Unmarshal error: %v\nMessage:\n%v", err, marshalText(want))
 					return
 				}
-				if !protoV1.Equal(got.(protoV1.Message), want.(protoV1.Message)) {
+				if !proto.Equal(got, want) {
 					t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", marshalText(got), marshalText(want))
 				}
 			})
@@ -142,3 +143,13 @@
 		t.Fatalf("MarshalAppend modified prefix: got %v, want prefix %v", got, want)
 	}
 }
+
+// newMessage returns a new message with the same type and extension fields as m.
+func newMessage(m proto.Message) proto.Message {
+	n := reflect.New(reflect.TypeOf(m).Elem()).Interface().(proto.Message)
+	m.ProtoReflect().KnownFields().ExtensionTypes().Range(func(xt pref.ExtensionType) bool {
+		n.ProtoReflect().KnownFields().ExtensionTypes().Register(xt)
+		return true
+	})
+	return n
+}
diff --git a/proto/equal.go b/proto/equal.go
new file mode 100644
index 0000000..cd31056
--- /dev/null
+++ b/proto/equal.go
@@ -0,0 +1,153 @@
+// Copyright 2019 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 proto
+
+import (
+	"bytes"
+
+	pref "github.com/golang/protobuf/v2/reflect/protoreflect"
+)
+
+// Equal returns true of two messages are equal.
+//
+// Two messages are equal if they have identical types and registered extension fields,
+// marshal to the same bytes under deterministic serialization,
+// and contain no floating point NaNs.
+func Equal(a, b Message) bool {
+	return equalMessage(a.ProtoReflect(), b.ProtoReflect())
+}
+
+// equalMessage compares two messages.
+func equalMessage(a, b pref.Message) bool {
+	mda, mdb := a.Type(), b.Type()
+	if mda != mdb && mda.FullName() != mdb.FullName() {
+		return false
+	}
+
+	// TODO: The v1 says that a nil message is not equal to an empty one.
+	// Decide what to do about this when v1 wraps v2.
+
+	knowna, knownb := a.KnownFields(), b.KnownFields()
+
+	fields := mda.Fields()
+	for i, flen := 0, fields.Len(); i < flen; i++ {
+		fd := fields.Get(i)
+		num := fd.Number()
+		hasa, hasb := knowna.Has(num), knownb.Has(num)
+		if !hasa && !hasb {
+			continue
+		}
+		if hasa != hasb || !equalFields(fd, knowna.Get(num), knownb.Get(num)) {
+			return false
+		}
+	}
+	equal := true
+
+	unknowna, unknownb := a.UnknownFields(), b.UnknownFields()
+	ulen := unknowna.Len()
+	if ulen != unknownb.Len() {
+		return false
+	}
+	unknowna.Range(func(num pref.FieldNumber, ra pref.RawFields) bool {
+		rb := unknownb.Get(num)
+		if !bytes.Equal([]byte(ra), []byte(rb)) {
+			equal = false
+			return false
+		}
+		return true
+	})
+	if !equal {
+		return false
+	}
+
+	// If the set of extension types is not identical for both messages, we report
+	// a inequality.
+	//
+	// This requirement is stringent. Registering an extension type for a message
+	// without setting a value for the extension will cause that message to compare
+	// as inequal to the same message without the registration.
+	//
+	// TODO: Revisit this behavior after eager decoding of extensions is implemented.
+	xtypesa, xtypesb := knowna.ExtensionTypes(), knownb.ExtensionTypes()
+	if la, lb := xtypesa.Len(), xtypesb.Len(); la != lb {
+		return false
+	} else if la == 0 {
+		return true
+	}
+	xtypesa.Range(func(xt pref.ExtensionType) bool {
+		num := xt.Number()
+		if xtypesb.ByNumber(num) != xt {
+			equal = false
+			return false
+		}
+		hasa, hasb := knowna.Has(num), knownb.Has(num)
+		if !hasa && !hasb {
+			return true
+		}
+		if hasa != hasb || !equalFields(xt, knowna.Get(num), knownb.Get(num)) {
+			equal = false
+			return false
+		}
+		return true
+	})
+	return equal
+}
+
+// equalFields compares two fields.
+func equalFields(fd pref.FieldDescriptor, a, b pref.Value) bool {
+	switch {
+	case fd.IsMap():
+		return equalMap(fd, a.Map(), b.Map())
+	case fd.Cardinality() == pref.Repeated:
+		return equalList(fd, a.List(), b.List())
+	default:
+		return equalValue(fd, a, b)
+	}
+}
+
+// equalMap compares a map field.
+func equalMap(fd pref.FieldDescriptor, a, b pref.Map) bool {
+	fdv := fd.Message().Fields().ByNumber(2)
+	alen := a.Len()
+	if alen != b.Len() {
+		return false
+	}
+	equal := true
+	a.Range(func(k pref.MapKey, va pref.Value) bool {
+		vb := b.Get(k)
+		if !vb.IsValid() || !equalValue(fdv, va, vb) {
+			equal = false
+			return false
+		}
+		return true
+	})
+	return equal
+}
+
+// equalList compares a non-map repeated field.
+func equalList(fd pref.FieldDescriptor, a, b pref.List) bool {
+	alen := a.Len()
+	if alen != b.Len() {
+		return false
+	}
+	for i := 0; i < alen; i++ {
+		if !equalValue(fd, a.Get(i), b.Get(i)) {
+			return false
+		}
+	}
+	return true
+}
+
+// equalValue compares the scalar value type of a field.
+func equalValue(fd pref.FieldDescriptor, a, b pref.Value) bool {
+	switch {
+	case fd.Message() != nil:
+		return equalMessage(a.Message(), b.Message())
+	case fd.Kind() == pref.BytesKind:
+		return bytes.Equal(a.Bytes(), b.Bytes())
+	default:
+		return a.Interface() == b.Interface()
+	}
+}
diff --git a/proto/equal_test.go b/proto/equal_test.go
new file mode 100644
index 0000000..1c3915c
--- /dev/null
+++ b/proto/equal_test.go
@@ -0,0 +1,516 @@
+// Copyright 2019 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 proto_test
+
+import (
+	"testing"
+
+	"github.com/golang/protobuf/v2/internal/encoding/pack"
+	"github.com/golang/protobuf/v2/internal/scalar"
+	testpb "github.com/golang/protobuf/v2/internal/testprotos/test"
+	test3pb "github.com/golang/protobuf/v2/internal/testprotos/test3"
+	"github.com/golang/protobuf/v2/proto"
+)
+
+func TestEqual(t *testing.T) {
+	for _, test := range inequalities {
+		if !proto.Equal(test.a, test.a) {
+			t.Errorf("Equal(a, a) = false, want true\na = %T %v", test.a, marshalText(test.a))
+		}
+		if proto.Equal(test.a, test.b) {
+			t.Errorf("Equal(a, b) = true, want false\na = %T %v\nb = %T %v", test.a, marshalText(test.a), test.b, marshalText(test.b))
+		}
+	}
+}
+
+var inequalities = []struct{ a, b proto.Message }{
+	// Scalar values.
+	{
+		&testpb.TestAllTypes{OptionalInt32: scalar.Int32(1)},
+		&testpb.TestAllTypes{OptionalInt32: scalar.Int32(2)},
+	},
+	{
+		&testpb.TestAllTypes{OptionalInt64: scalar.Int64(1)},
+		&testpb.TestAllTypes{OptionalInt64: scalar.Int64(2)},
+	},
+	{
+		&testpb.TestAllTypes{OptionalUint32: scalar.Uint32(1)},
+		&testpb.TestAllTypes{OptionalUint32: scalar.Uint32(2)},
+	},
+	{
+		&testpb.TestAllTypes{OptionalUint64: scalar.Uint64(1)},
+		&testpb.TestAllTypes{OptionalUint64: scalar.Uint64(2)},
+	},
+	{
+		&testpb.TestAllTypes{OptionalSint32: scalar.Int32(1)},
+		&testpb.TestAllTypes{OptionalSint32: scalar.Int32(2)},
+	},
+	{
+		&testpb.TestAllTypes{OptionalSint64: scalar.Int64(1)},
+		&testpb.TestAllTypes{OptionalSint64: scalar.Int64(2)},
+	},
+	{
+		&testpb.TestAllTypes{OptionalFixed32: scalar.Uint32(1)},
+		&testpb.TestAllTypes{OptionalFixed32: scalar.Uint32(2)},
+	},
+	{
+		&testpb.TestAllTypes{OptionalFixed64: scalar.Uint64(1)},
+		&testpb.TestAllTypes{OptionalFixed64: scalar.Uint64(2)},
+	},
+	{
+		&testpb.TestAllTypes{OptionalSfixed32: scalar.Int32(1)},
+		&testpb.TestAllTypes{OptionalSfixed32: scalar.Int32(2)},
+	},
+	{
+		&testpb.TestAllTypes{OptionalSfixed64: scalar.Int64(1)},
+		&testpb.TestAllTypes{OptionalSfixed64: scalar.Int64(2)},
+	},
+	{
+		&testpb.TestAllTypes{OptionalFloat: scalar.Float32(1)},
+		&testpb.TestAllTypes{OptionalFloat: scalar.Float32(2)},
+	},
+	{
+		&testpb.TestAllTypes{OptionalDouble: scalar.Float64(1)},
+		&testpb.TestAllTypes{OptionalDouble: scalar.Float64(2)},
+	},
+	{
+		&testpb.TestAllTypes{OptionalBool: scalar.Bool(true)},
+		&testpb.TestAllTypes{OptionalBool: scalar.Bool(false)},
+	},
+	{
+		&testpb.TestAllTypes{OptionalString: scalar.String("a")},
+		&testpb.TestAllTypes{OptionalString: scalar.String("b")},
+	},
+	{
+		&testpb.TestAllTypes{OptionalBytes: []byte("a")},
+		&testpb.TestAllTypes{OptionalBytes: []byte("b")},
+	},
+	{
+		&testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
+		&testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()},
+	},
+	// Proto2 presence.
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalInt32: scalar.Int32(0)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalInt64: scalar.Int64(0)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalUint32: scalar.Uint32(0)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalUint64: scalar.Uint64(0)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalSint32: scalar.Int32(0)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalSint64: scalar.Int64(0)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalFixed32: scalar.Uint32(0)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalFixed64: scalar.Uint64(0)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalSfixed32: scalar.Int32(0)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalSfixed64: scalar.Int64(0)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalFloat: scalar.Float32(0)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalDouble: scalar.Float64(0)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalBool: scalar.Bool(false)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalString: scalar.String("")},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalBytes: []byte{}},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
+	},
+	// Groups.
+	{
+		&testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{
+			A: scalar.Int32(1),
+		}},
+		&testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{
+			A: scalar.Int32(2),
+		}},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{}},
+	},
+	// Messages.
+	{
+		&testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
+			A: scalar.Int32(1),
+		}},
+		&testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
+			A: scalar.Int32(2),
+		}},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{}},
+	},
+	{
+		&test3pb.TestAllTypes{},
+		&test3pb.TestAllTypes{OptionalNestedMessage: &test3pb.TestAllTypes_NestedMessage{}},
+	},
+	// Lists.
+	{
+		&testpb.TestAllTypes{RepeatedInt32: []int32{1}},
+		&testpb.TestAllTypes{RepeatedInt32: []int32{1, 2}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedInt32: []int32{1, 2}},
+		&testpb.TestAllTypes{RepeatedInt32: []int32{1, 3}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedInt64: []int64{1, 2}},
+		&testpb.TestAllTypes{RepeatedInt64: []int64{1, 3}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedUint32: []uint32{1, 2}},
+		&testpb.TestAllTypes{RepeatedUint32: []uint32{1, 3}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedUint64: []uint64{1, 2}},
+		&testpb.TestAllTypes{RepeatedUint64: []uint64{1, 3}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedSint32: []int32{1, 2}},
+		&testpb.TestAllTypes{RepeatedSint32: []int32{1, 3}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedSint64: []int64{1, 2}},
+		&testpb.TestAllTypes{RepeatedSint64: []int64{1, 3}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedFixed32: []uint32{1, 2}},
+		&testpb.TestAllTypes{RepeatedFixed32: []uint32{1, 3}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedFixed64: []uint64{1, 2}},
+		&testpb.TestAllTypes{RepeatedFixed64: []uint64{1, 3}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedSfixed32: []int32{1, 2}},
+		&testpb.TestAllTypes{RepeatedSfixed32: []int32{1, 3}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedSfixed64: []int64{1, 2}},
+		&testpb.TestAllTypes{RepeatedSfixed64: []int64{1, 3}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedFloat: []float32{1, 2}},
+		&testpb.TestAllTypes{RepeatedFloat: []float32{1, 3}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedDouble: []float64{1, 2}},
+		&testpb.TestAllTypes{RepeatedDouble: []float64{1, 3}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedBool: []bool{true, false}},
+		&testpb.TestAllTypes{RepeatedBool: []bool{true, true}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedString: []string{"a", "b"}},
+		&testpb.TestAllTypes{RepeatedString: []string{"a", "c"}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedBytes: [][]byte{[]byte("a"), []byte("b")}},
+		&testpb.TestAllTypes{RepeatedBytes: [][]byte{[]byte("a"), []byte("c")}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}},
+		&testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}},
+	},
+	{
+		&testpb.TestAllTypes{Repeatedgroup: []*testpb.TestAllTypes_RepeatedGroup{
+			{A: scalar.Int32(1)},
+			{A: scalar.Int32(2)},
+		}},
+		&testpb.TestAllTypes{Repeatedgroup: []*testpb.TestAllTypes_RepeatedGroup{
+			{A: scalar.Int32(1)},
+			{A: scalar.Int32(3)},
+		}},
+	},
+	{
+		&testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{
+			{A: scalar.Int32(1)},
+			{A: scalar.Int32(2)},
+		}},
+		&testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{
+			{A: scalar.Int32(1)},
+			{A: scalar.Int32(3)},
+		}},
+	},
+	// Maps: various configurations.
+	{
+		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
+		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{3: 4}},
+	},
+	{
+		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
+		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
+	},
+	{
+		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
+		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
+	},
+	// Maps: various types.
+	{
+		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
+		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 5}},
+	},
+	{
+		&testpb.TestAllTypes{MapInt64Int64: map[int64]int64{1: 2, 3: 4}},
+		&testpb.TestAllTypes{MapInt64Int64: map[int64]int64{1: 2, 3: 5}},
+	},
+	{
+		&testpb.TestAllTypes{MapUint32Uint32: map[uint32]uint32{1: 2, 3: 4}},
+		&testpb.TestAllTypes{MapUint32Uint32: map[uint32]uint32{1: 2, 3: 5}},
+	},
+	{
+		&testpb.TestAllTypes{MapUint64Uint64: map[uint64]uint64{1: 2, 3: 4}},
+		&testpb.TestAllTypes{MapUint64Uint64: map[uint64]uint64{1: 2, 3: 5}},
+	},
+	{
+		&testpb.TestAllTypes{MapSint32Sint32: map[int32]int32{1: 2, 3: 4}},
+		&testpb.TestAllTypes{MapSint32Sint32: map[int32]int32{1: 2, 3: 5}},
+	},
+	{
+		&testpb.TestAllTypes{MapSint64Sint64: map[int64]int64{1: 2, 3: 4}},
+		&testpb.TestAllTypes{MapSint64Sint64: map[int64]int64{1: 2, 3: 5}},
+	},
+	{
+		&testpb.TestAllTypes{MapFixed32Fixed32: map[uint32]uint32{1: 2, 3: 4}},
+		&testpb.TestAllTypes{MapFixed32Fixed32: map[uint32]uint32{1: 2, 3: 5}},
+	},
+	{
+		&testpb.TestAllTypes{MapFixed64Fixed64: map[uint64]uint64{1: 2, 3: 4}},
+		&testpb.TestAllTypes{MapFixed64Fixed64: map[uint64]uint64{1: 2, 3: 5}},
+	},
+	{
+		&testpb.TestAllTypes{MapSfixed32Sfixed32: map[int32]int32{1: 2, 3: 4}},
+		&testpb.TestAllTypes{MapSfixed32Sfixed32: map[int32]int32{1: 2, 3: 5}},
+	},
+	{
+		&testpb.TestAllTypes{MapSfixed64Sfixed64: map[int64]int64{1: 2, 3: 4}},
+		&testpb.TestAllTypes{MapSfixed64Sfixed64: map[int64]int64{1: 2, 3: 5}},
+	},
+	{
+		&testpb.TestAllTypes{MapInt32Float: map[int32]float32{1: 2, 3: 4}},
+		&testpb.TestAllTypes{MapInt32Float: map[int32]float32{1: 2, 3: 5}},
+	},
+	{
+		&testpb.TestAllTypes{MapInt32Double: map[int32]float64{1: 2, 3: 4}},
+		&testpb.TestAllTypes{MapInt32Double: map[int32]float64{1: 2, 3: 5}},
+	},
+	{
+		&testpb.TestAllTypes{MapBoolBool: map[bool]bool{true: false, false: true}},
+		&testpb.TestAllTypes{MapBoolBool: map[bool]bool{true: false, false: false}},
+	},
+	{
+		&testpb.TestAllTypes{MapStringString: map[string]string{"a": "b", "c": "d"}},
+		&testpb.TestAllTypes{MapStringString: map[string]string{"a": "b", "c": "e"}},
+	},
+	{
+		&testpb.TestAllTypes{MapStringBytes: map[string][]byte{"a": []byte("b"), "c": []byte("d")}},
+		&testpb.TestAllTypes{MapStringBytes: map[string][]byte{"a": []byte("b"), "c": []byte("e")}},
+	},
+	{
+		&testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{
+			"a": {A: scalar.Int32(1)},
+			"b": {A: scalar.Int32(2)},
+		}},
+		&testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{
+			"a": {A: scalar.Int32(1)},
+			"b": {A: scalar.Int32(3)},
+		}},
+	},
+	{
+		&testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{
+			"a": testpb.TestAllTypes_FOO,
+			"b": testpb.TestAllTypes_BAR,
+		}},
+		&testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{
+			"a": testpb.TestAllTypes_FOO,
+			"b": testpb.TestAllTypes_BAZ,
+		}},
+	},
+	// Unknown fields.
+	{
+		build(&testpb.TestAllTypes{}, unknown(100000, pack.Message{
+			pack.Tag{100000, pack.VarintType}, pack.Varint(1),
+		}.Marshal())),
+		build(&testpb.TestAllTypes{}, unknown(100000, pack.Message{
+			pack.Tag{100000, pack.VarintType}, pack.Varint(2),
+		}.Marshal())),
+	},
+	{
+		build(&testpb.TestAllTypes{}, unknown(100000, pack.Message{
+			pack.Tag{100000, pack.VarintType}, pack.Varint(1),
+		}.Marshal())),
+		&testpb.TestAllTypes{},
+	},
+	{
+		&testpb.TestAllTypes{},
+		build(&testpb.TestAllTypes{}, unknown(100000, pack.Message{
+			pack.Tag{100000, pack.VarintType}, pack.Varint(1),
+		}.Marshal())),
+	},
+	// Extensions.
+	{
+		build(&testpb.TestAllExtensions{},
+			extend(testpb.E_OptionalInt32Extension, scalar.Int32(1)),
+		),
+		build(&testpb.TestAllExtensions{},
+			extend(testpb.E_OptionalInt32Extension, scalar.Int32(2)),
+		),
+	},
+	{
+		build(&testpb.TestAllExtensions{},
+			registerExtension(testpb.E_OptionalInt32Extension),
+		),
+		build(&testpb.TestAllExtensions{},
+			extend(testpb.E_OptionalInt32Extension, scalar.Int32(2)),
+		),
+	},
+	{
+		build(&testpb.TestAllExtensions{},
+			extend(testpb.E_OptionalInt32Extension, scalar.Int32(1)),
+		),
+		build(&testpb.TestAllExtensions{},
+			registerExtension(testpb.E_OptionalInt32Extension),
+		),
+	},
+	{
+		&testpb.TestAllExtensions{},
+		build(&testpb.TestAllExtensions{},
+			extend(testpb.E_OptionalInt32Extension, scalar.Int32(2)),
+		),
+	},
+	{
+		&testpb.TestAllExtensions{},
+		build(&testpb.TestAllExtensions{},
+			registerExtension(testpb.E_OptionalInt32Extension),
+		),
+	},
+	// Proto2 default values are not considered by Equal, so the following are still unequal.
+	{
+		&testpb.TestAllTypes{DefaultInt32: scalar.Int32(81)},
+		&testpb.TestAllTypes{},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultInt32: scalar.Int32(81)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultInt64: scalar.Int64(82)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultUint32: scalar.Uint32(83)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultUint64: scalar.Uint64(84)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultSint32: scalar.Int32(-85)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultSint64: scalar.Int64(86)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultFixed32: scalar.Uint32(87)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultFixed64: scalar.Uint64(88)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultSfixed32: scalar.Int32(89)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultSfixed64: scalar.Int64(-90)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultFloat: scalar.Float32(91.5)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultDouble: scalar.Float64(92e3)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultBool: scalar.Bool(true)},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultString: scalar.String("hello")},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultBytes: []byte("world")},
+	},
+	{
+		&testpb.TestAllTypes{},
+		&testpb.TestAllTypes{DefaultNestedEnum: testpb.TestAllTypes_BAR.Enum()},
+	},
+	// Extension ddefault values are not considered by Equal, so the following are still unequal.
+	{
+		build(&testpb.TestAllExtensions{},
+			registerExtension(testpb.E_DefaultInt32Extension),
+		),
+		build(&testpb.TestAllExtensions{},
+			extend(testpb.E_DefaultInt32Extension, scalar.Int32(81)),
+		),
+	},
+	{
+		build(&testpb.TestAllExtensions{},
+			extend(testpb.E_DefaultInt32Extension, scalar.Int32(81)),
+		),
+		build(&testpb.TestAllExtensions{},
+			registerExtension(testpb.E_DefaultInt32Extension),
+		),
+	},
+}