internal/impl: support aberrant enums and messages

Aberrant messages are hand-crafted messages that happen to work because
they use the same struct tags that generated code emits.
This happens to work in v1, but is unspecified behavior and entirely outside
the compatibility promise.

Support for this was added early on in the history of the v2 implementation,
but entirely untested. It was removed in CL/182360 to reduce the
technical debt of the legacy implementation. Unfortunately, sufficient number
of targets do rely on this aberrant support, so it is being added back.

The logic being added is essentially the same thing as the previous logic,
but ported to use internal/filedesc instead of the now deleted
internal/prototype package.

Change-Id: Ib5cab3e90480825b9615db358044ce05a14b05bd
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/184517
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/filedesc/desc.go b/internal/filedesc/desc.go
index 3e939e6..84c90fa 100644
--- a/internal/filedesc/desc.go
+++ b/internal/filedesc/desc.go
@@ -528,6 +528,9 @@
 func (dv *defaultValue) get(fd pref.FieldDescriptor) pref.Value {
 	// Return the zero value as the default if unpopulated.
 	if !dv.has {
+		if fd.Cardinality() == pref.Repeated {
+			return pref.Value{}
+		}
 		switch fd.Kind() {
 		case pref.BoolKind:
 			return pref.ValueOf(false)
diff --git a/internal/filedesc/desc_test.go b/internal/filedesc/desc_test.go
index b6e0f7d..5bea386 100644
--- a/internal/filedesc/desc_test.go
+++ b/internal/filedesc/desc_test.go
@@ -347,7 +347,7 @@
 						"IsPacked":    true,
 						"IsList":      true,
 						"IsMap":       false,
-						"Default":     int32(0),
+						"Default":     nil,
 					},
 					"ByNumber:6": M{
 						"Cardinality":     pref.Required,
diff --git a/internal/filedesc/placeholder.go b/internal/filedesc/placeholder.go
index be95831..eaf04ee 100644
--- a/internal/filedesc/placeholder.go
+++ b/internal/filedesc/placeholder.go
@@ -64,6 +64,21 @@
 func (e PlaceholderEnum) ProtoType(pref.EnumDescriptor)       { return }
 func (e PlaceholderEnum) ProtoInternal(pragma.DoNotImplement) { return }
 
+// PlaceholderEnumValue is a placeholder, representing only the full name.
+type PlaceholderEnumValue pref.FullName
+
+func (e PlaceholderEnumValue) ParentFile() pref.FileDescriptor     { return nil }
+func (e PlaceholderEnumValue) Parent() pref.Descriptor             { return nil }
+func (e PlaceholderEnumValue) Index() int                          { return 0 }
+func (e PlaceholderEnumValue) Syntax() pref.Syntax                 { return 0 }
+func (e PlaceholderEnumValue) Name() pref.Name                     { return pref.FullName(e).Name() }
+func (e PlaceholderEnumValue) FullName() pref.FullName             { return pref.FullName(e) }
+func (e PlaceholderEnumValue) IsPlaceholder() bool                 { return true }
+func (e PlaceholderEnumValue) Options() pref.ProtoMessage          { return descopts.EnumValue }
+func (e PlaceholderEnumValue) Number() pref.EnumNumber             { return 0 }
+func (e PlaceholderEnumValue) ProtoType(pref.EnumValueDescriptor)  { return }
+func (e PlaceholderEnumValue) ProtoInternal(pragma.DoNotImplement) { return }
+
 // PlaceholderMessage is a placeholder, representing only the full name.
 type PlaceholderMessage pref.FullName