internal/impl: add fast-path for IsInitialized

This currently returns uninformative errors from the fast path and then
consults the slow, reflection-based path only when an error is detected.
Perhaps it's worth going through the effort of producing better errors
directly on the fast path.

Change-Id: I68536e9438010dbd97dbaff4f47b78430221d94b
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171462
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/proto/isinit.go b/proto/isinit.go
index c535cf7..1bb29bd 100644
--- a/proto/isinit.go
+++ b/proto/isinit.go
@@ -15,12 +15,13 @@
 // IsInitialized returns an error if any required fields in m are not set.
 func IsInitialized(m Message) error {
 	if methods := protoMethods(m); methods != nil && methods.IsInitialized != nil {
-		// TODO: Do we need a way to disable the fast path here?
+		if err := methods.IsInitialized(m); err == nil {
+			return nil
+		}
+		// Fall through to the slow path, since the fast-path
+		// implementation doesn't produce nice errors.
 		//
-		// TODO: Should detailed information about missing
-		// fields always be provided by the slow-but-informative
-		// reflective implementation?
-		return methods.IsInitialized(m)
+		// TODO: Consider producing better errors from the fast path.
 	}
 	return isInitialized(m.ProtoReflect(), nil)
 }