proto, internal/impl: make IsInitialized more consistent
Make the fast-path and slow-path versions of IsInitialized report
exactly the same errors: An errors.RequiredNotSet containing the
full name of one of the unset required fields.
Bugfix: Fast-path IsInitialized on a nil message reports an error only
when the message directly contains required fields.
Bugfix: Include fast-path IsInitialized in legacy messageIfaceWrapper.
Fixes golang/protobuf#887
Change-Id: Ia5e4b386f8c23f6f855d995f4a098b1338acbae3
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/185397
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/internal/impl/isinit.go b/internal/impl/isinit.go
index 29f9ad8..a533cf4 100644
--- a/internal/impl/isinit.go
+++ b/internal/impl/isinit.go
@@ -7,15 +7,11 @@
import (
"sync"
+ "google.golang.org/protobuf/internal/errors"
"google.golang.org/protobuf/proto"
pref "google.golang.org/protobuf/reflect/protoreflect"
)
-type errRequiredNotSet struct{}
-
-func (errRequiredNotSet) Error() string { return "proto: required field not set" }
-func (errRequiredNotSet) RequiredNotSet() bool { return true }
-
func (mi *MessageInfo) isInitialized(msg proto.Message) error {
return mi.isInitializedPointer(pointerOfIface(msg))
}
@@ -26,7 +22,12 @@
return nil
}
if p.IsNil() {
- return errRequiredNotSet{}
+ for _, f := range mi.orderedCoderFields {
+ if f.isRequired {
+ return errors.RequiredNotSet(string(mi.PBType.Fields().ByNumber(f.num).FullName()))
+ }
+ }
+ return nil
}
if mi.extensionOffset.IsValid() {
e := p.Apply(mi.extensionOffset).Extensions()
@@ -41,7 +42,7 @@
fptr := p.Apply(f.offset)
if f.isPointer && fptr.Elem().IsNil() {
if f.isRequired {
- return errRequiredNotSet{}
+ return errors.RequiredNotSet(string(mi.PBType.Fields().ByNumber(f.num).FullName()))
}
continue
}