Просмотр исходного кода

all: remove non-fatal UTF-8 validation errors (and non-fatal in general)

Immediately abort (un)marshal operations when encountering invalid UTF-8
data in proto3 strings. No other proto implementation supports non-UTF-8
data in proto3 strings (and many reject it in proto2 strings as well).
Producing invalid output is an interoperability threat (other
implementations won't be able to read it).

The case where existing string data is found to contain non-UTF8 data is
better handled by changing the field to the `bytes` type, which (aside
from UTF-8 validation) is wire-compatible with `string`.

Remove the errors.NonFatal type, since there are no remaining cases
where it is needed. "Non-fatal" errors which produce results and a
non-nil error are problematic because they compose poorly; the better
approach is to take an option like AllowPartial indicating which
conditions to check for.

Change-Id: I9d189ec6ffda7b5d96d094aa1b290af2e3f23736
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/183098
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
Damien Neil 6 лет назад
Родитель
Сommit
8c86fc5e7d

+ 36 - 48
encoding/protojson/decode.go

@@ -62,8 +62,7 @@ func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
 	}
 	o.decoder = json.NewDecoder(b)
 
-	var nerr errors.NonFatal
-	if err := o.unmarshalMessage(m.ProtoReflect(), false); !nerr.Merge(err) {
+	if err := o.unmarshalMessage(m.ProtoReflect(), false); err != nil {
 		return err
 	}
 
@@ -76,10 +75,10 @@ func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
 		return unexpectedJSONError{val}
 	}
 
-	if !o.AllowPartial {
-		nerr.Merge(proto.IsInitialized(m))
+	if o.AllowPartial {
+		return nil
 	}
-	return nerr.E
+	return proto.IsInitialized(m)
 }
 
 // unexpectedJSONError is an error that contains the unexpected json.Value. This
@@ -116,30 +115,27 @@ func newError(f string, x ...interface{}) error {
 
 // unmarshalMessage unmarshals a message into the given protoreflect.Message.
 func (o UnmarshalOptions) unmarshalMessage(m pref.Message, skipTypeURL bool) error {
-	var nerr errors.NonFatal
-
 	if isCustomType(m.Descriptor().FullName()) {
 		return o.unmarshalCustomType(m)
 	}
 
 	jval, err := o.decoder.Read()
-	if !nerr.Merge(err) {
+	if err != nil {
 		return err
 	}
 	if jval.Type() != json.StartObject {
 		return unexpectedJSONError{jval}
 	}
 
-	if err := o.unmarshalFields(m, skipTypeURL); !nerr.Merge(err) {
+	if err := o.unmarshalFields(m, skipTypeURL); err != nil {
 		return err
 	}
 
-	return nerr.E
+	return nil
 }
 
 // unmarshalFields unmarshals the fields into the given protoreflect.Message.
 func (o UnmarshalOptions) unmarshalFields(m pref.Message, skipTypeURL bool) error {
-	var nerr errors.NonFatal
 	var seenNums set.Ints
 	var seenOneofs set.Ints
 
@@ -150,7 +146,7 @@ Loop:
 	for {
 		// Read field name.
 		jval, err := o.decoder.Read()
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 		switch jval.Type() {
@@ -163,7 +159,7 @@ Loop:
 		}
 
 		name, err := jval.Name()
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 		// Unmarshaling a non-custom embedded message in Any will contain the
@@ -195,7 +191,7 @@ Loop:
 		if fd == nil {
 			// Field is unknown.
 			if o.DiscardUnknown {
-				if err := skipJSONValue(o.decoder); !nerr.Merge(err) {
+				if err := skipJSONValue(o.decoder); err != nil {
 					return err
 				}
 				continue
@@ -220,12 +216,12 @@ Loop:
 		switch {
 		case fd.IsList():
 			list := m.Mutable(fd).List()
-			if err := o.unmarshalList(list, fd); !nerr.Merge(err) {
+			if err := o.unmarshalList(list, fd); err != nil {
 				return errors.New("%v|%q: %v", fd.FullName(), name, err)
 			}
 		case fd.IsMap():
 			mmap := m.Mutable(fd).Map()
-			if err := o.unmarshalMap(mmap, fd); !nerr.Merge(err) {
+			if err := o.unmarshalMap(mmap, fd); err != nil {
 				return errors.New("%v|%q: %v", fd.FullName(), name, err)
 			}
 		default:
@@ -239,13 +235,13 @@ Loop:
 			}
 
 			// Required or optional fields.
-			if err := o.unmarshalSingular(m, fd); !nerr.Merge(err) {
+			if err := o.unmarshalSingular(m, fd); err != nil {
 				return errors.New("%v|%q: %v", fd.FullName(), name, err)
 			}
 		}
 	}
 
-	return nerr.E
+	return nil
 }
 
 // findExtension returns protoreflect.ExtensionType from the resolver if found.
@@ -287,12 +283,11 @@ func (o UnmarshalOptions) unmarshalSingular(m pref.Message, fd pref.FieldDescrip
 		val, err = o.unmarshalScalar(fd)
 	}
 
-	var nerr errors.NonFatal
-	if !nerr.Merge(err) {
+	if err != nil {
 		return err
 	}
 	m.Set(fd, val)
-	return nerr.E
+	return nil
 }
 
 // unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
@@ -301,9 +296,8 @@ func (o UnmarshalOptions) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value,
 	const b32 int = 32
 	const b64 int = 64
 
-	var nerr errors.NonFatal
 	jval, err := o.decoder.Read()
-	if !nerr.Merge(err) {
+	if err != nil {
 		return pref.Value{}, err
 	}
 
@@ -332,10 +326,10 @@ func (o UnmarshalOptions) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value,
 
 	case pref.StringKind:
 		pval, err := unmarshalString(jval)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return pval, err
 		}
-		return pval, nerr.E
+		return pval, nil
 
 	case pref.BytesKind:
 		return unmarshalBytes(jval)
@@ -367,9 +361,8 @@ func unmarshalInt(jval json.Value, bitSize int) (pref.Value, error) {
 			return pref.Value{}, errors.New("invalid number %v", jval.Raw())
 		}
 		dec := json.NewDecoder([]byte(s))
-		var nerr errors.NonFatal
 		jval, err := dec.Read()
-		if !nerr.Merge(err) {
+		if err != nil {
 			return pref.Value{}, err
 		}
 		return getInt(jval, bitSize)
@@ -400,9 +393,8 @@ func unmarshalUint(jval json.Value, bitSize int) (pref.Value, error) {
 			return pref.Value{}, errors.New("invalid number %v", jval.Raw())
 		}
 		dec := json.NewDecoder([]byte(s))
-		var nerr errors.NonFatal
 		jval, err := dec.Read()
-		if !nerr.Merge(err) {
+		if err != nil {
 			return pref.Value{}, err
 		}
 		return getUint(jval, bitSize)
@@ -450,9 +442,8 @@ func unmarshalFloat(jval json.Value, bitSize int) (pref.Value, error) {
 			return pref.Value{}, errors.New("invalid number %v", jval.Raw())
 		}
 		dec := json.NewDecoder([]byte(s))
-		var nerr errors.NonFatal
 		jval, err := dec.Read()
-		if !nerr.Merge(err) {
+		if err != nil {
 			return pref.Value{}, err
 		}
 		return getFloat(jval, bitSize)
@@ -526,9 +517,8 @@ func unmarshalEnum(jval json.Value, fd pref.FieldDescriptor) (pref.Value, error)
 }
 
 func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor) error {
-	var nerr errors.NonFatal
 	jval, err := o.decoder.Read()
-	if !nerr.Merge(err) {
+	if err != nil {
 		return err
 	}
 	if jval.Type() != json.StartArray {
@@ -540,11 +530,11 @@ func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor)
 		for {
 			m := list.NewMessage()
 			err := o.unmarshalMessage(m, false)
-			if !nerr.Merge(err) {
+			if err != nil {
 				if e, ok := err.(unexpectedJSONError); ok {
 					if e.value.Type() == json.EndArray {
 						// Done with list.
-						return nerr.E
+						return nil
 					}
 				}
 				return err
@@ -554,11 +544,11 @@ func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor)
 	default:
 		for {
 			val, err := o.unmarshalScalar(fd)
-			if !nerr.Merge(err) {
+			if err != nil {
 				if e, ok := err.(unexpectedJSONError); ok {
 					if e.value.Type() == json.EndArray {
 						// Done with list.
-						return nerr.E
+						return nil
 					}
 				}
 				return err
@@ -566,13 +556,12 @@ func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor)
 			list.Append(val)
 		}
 	}
-	return nerr.E
+	return nil
 }
 
 func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
-	var nerr errors.NonFatal
 	jval, err := o.decoder.Read()
-	if !nerr.Merge(err) {
+	if err != nil {
 		return err
 	}
 	if jval.Type() != json.StartObject {
@@ -586,12 +575,11 @@ func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) e
 	switch fd.MapValue().Kind() {
 	case pref.MessageKind, pref.GroupKind:
 		unmarshalMapValue = func() (pref.Value, error) {
-			var nerr errors.NonFatal
 			m := mmap.NewMessage()
-			if err := o.unmarshalMessage(m, false); !nerr.Merge(err) {
+			if err := o.unmarshalMessage(m, false); err != nil {
 				return pref.Value{}, err
 			}
-			return pref.ValueOf(m), nerr.E
+			return pref.ValueOf(m), nil
 		}
 	default:
 		unmarshalMapValue = func() (pref.Value, error) {
@@ -603,7 +591,7 @@ Loop:
 	for {
 		// Read field name.
 		jval, err := o.decoder.Read()
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 		switch jval.Type() {
@@ -616,13 +604,13 @@ Loop:
 		}
 
 		name, err := jval.Name()
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 
 		// Unmarshal field name.
 		pkey, err := unmarshalMapKey(name, fd.MapKey())
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 
@@ -633,14 +621,14 @@ Loop:
 
 		// Read and unmarshal field value.
 		pval, err := unmarshalMapValue()
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 
 		mmap.Set(pkey, pval)
 	}
 
-	return nerr.E
+	return nil
 }
 
 // unmarshalMapKey converts given string into a protoreflect.MapKey. A map key type is any

+ 6 - 118
encoding/protojson/decode_test.go

@@ -5,7 +5,6 @@
 package protojson_test
 
 import (
-	"bytes"
 	"math"
 	"testing"
 
@@ -391,10 +390,7 @@ func TestUnmarshal(t *testing.T) {
 		desc:         "string with invalid UTF-8",
 		inputMessage: &pb3.Scalars{},
 		inputText:    "{\"sString\": \"\xff\"}",
-		wantMessage: &pb3.Scalars{
-			SString: "\xff",
-		},
-		wantErr: true,
+		wantErr:      true,
 	}, {
 		desc:         "not string",
 		inputMessage: &pb2.Scalars{},
@@ -814,18 +810,12 @@ func TestUnmarshal(t *testing.T) {
 		desc:         "repeated string contains invalid UTF8",
 		inputMessage: &pb2.Repeats{},
 		inputText:    `{"rptString": ["` + "abc\xff" + `"]}`,
-		wantMessage: &pb2.Repeats{
-			RptString: []string{"abc\xff"},
-		},
-		wantErr: true,
+		wantErr:      true,
 	}, {
 		desc:         "repeated messages contain invalid UTF8",
 		inputMessage: &pb2.Nests{},
 		inputText:    `{"rptNested": [{"optString": "` + "abc\xff" + `"}]}`,
-		wantMessage: &pb2.Nests{
-			RptNested: []*pb2.Nested{{OptString: scalar.String("abc\xff")}},
-		},
-		wantErr: true,
+		wantErr:      true,
 	}, {
 		desc:         "repeated scalars contain invalid type",
 		inputMessage: &pb2.Repeats{},
@@ -1020,11 +1010,6 @@ func TestUnmarshal(t *testing.T) {
 	}
   }
 }`,
-		wantMessage: &pb3.Maps{
-			StrToNested: map[string]*pb3.Nested{
-				"hello": {SString: "abc\xff"},
-			},
-		},
 		wantErr: true,
 	}, {
 		desc:         "map key contains invalid UTF8",
@@ -1034,11 +1019,6 @@ func TestUnmarshal(t *testing.T) {
     "` + "abc\xff" + `": {}
   }
 }`,
-		wantMessage: &pb3.Maps{
-			StrToNested: map[string]*pb3.Nested{
-				"abc\xff": {},
-			},
-		},
 		wantErr: true,
 	}, {
 		desc:         "required fields not set",
@@ -1509,16 +1489,12 @@ func TestUnmarshal(t *testing.T) {
 		desc:         "StringValue with invalid UTF8 error",
 		inputMessage: &wrapperspb.StringValue{},
 		inputText:    "\"abc\xff\"",
-		wantMessage:  &wrapperspb.StringValue{Value: "abc\xff"},
 		wantErr:      true,
 	}, {
 		desc:         "StringValue field with invalid UTF8 error",
 		inputMessage: &pb2.KnownTypes{},
 		inputText:    "{\n  \"optString\": \"abc\xff\"\n}",
-		wantMessage: &pb2.KnownTypes{
-			OptString: &wrapperspb.StringValue{Value: "abc\xff"},
-		},
-		wantErr: true,
+		wantErr:      true,
 	}, {
 		desc:         "NullValue field with JSON null",
 		inputMessage: &pb2.KnownTypes{},
@@ -1589,7 +1565,6 @@ func TestUnmarshal(t *testing.T) {
 		desc:         "Value string with invalid UTF8",
 		inputMessage: &structpb.Value{},
 		inputText:    "\"\xff\"",
-		wantMessage:  &structpb.Value{Kind: &structpb.Value_StringValue{"\xff"}},
 		wantErr:      true,
 	}, {
 		desc:         "Value field string",
@@ -1606,9 +1581,6 @@ func TestUnmarshal(t *testing.T) {
 		inputText: `{
   "optValue": "` + "\xff" + `"
 }`,
-		wantMessage: &pb2.KnownTypes{
-			OptValue: &structpb.Value{Kind: &structpb.Value_StringValue{"\xff"}},
-		},
 		wantErr: true,
 	}, {
 		desc:         "Value empty struct",
@@ -1660,16 +1632,7 @@ func TestUnmarshal(t *testing.T) {
 		desc:         "Value struct with invalid UTF8 string",
 		inputMessage: &structpb.Value{},
 		inputText:    "{\"string\": \"abc\xff\"}",
-		wantMessage: &structpb.Value{
-			Kind: &structpb.Value_StructValue{
-				&structpb.Struct{
-					Fields: map[string]*structpb.Value{
-						"string": {Kind: &structpb.Value_StringValue{"abc\xff"}},
-					},
-				},
-			},
-		},
-		wantErr: true,
+		wantErr:      true,
 	}, {
 		desc:         "Value field struct",
 		inputMessage: &pb2.KnownTypes{},
@@ -1743,33 +1706,13 @@ func TestUnmarshal(t *testing.T) {
 		desc:         "Value list with invalid UTF8 string",
 		inputMessage: &structpb.Value{},
 		inputText:    "[\"abc\xff\"]",
-		wantMessage: &structpb.Value{
-			Kind: &structpb.Value_ListValue{
-				&structpb.ListValue{
-					Values: []*structpb.Value{
-						{Kind: &structpb.Value_StringValue{"abc\xff"}},
-					},
-				},
-			},
-		},
-		wantErr: true,
+		wantErr:      true,
 	}, {
 		desc:         "Value field list with invalid UTF8 string",
 		inputMessage: &pb2.KnownTypes{},
 		inputText: `{
   "optValue": [ "` + "abc\xff" + `"]
 }`,
-		wantMessage: &pb2.KnownTypes{
-			OptValue: &structpb.Value{
-				Kind: &structpb.Value_ListValue{
-					&structpb.ListValue{
-						Values: []*structpb.Value{
-							{Kind: &structpb.Value_StringValue{"abc\xff"}},
-						},
-					},
-				},
-			},
-		},
 		wantErr: true,
 	}, {
 		desc:         "Duration empty string",
@@ -2073,19 +2016,6 @@ func TestUnmarshal(t *testing.T) {
   "optString": "` + "abc\xff" + `",
   "@type": "foo/pb2.Nested"
 }`,
-		wantMessage: func() proto.Message {
-			m := &pb2.Nested{
-				OptString: scalar.String("abc\xff"),
-			}
-			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
-			if err != nil {
-				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
-			}
-			return &anypb.Any{
-				TypeUrl: "foo/pb2.Nested",
-				Value:   b,
-			}
-		}(),
 		wantErr: true,
 	}, {
 		desc: "Any with BoolValue",
@@ -2141,17 +2071,6 @@ func TestUnmarshal(t *testing.T) {
   "@type": "google.protobuf.StringValue",
   "value": "` + "abc\xff" + `"
 }`,
-		wantMessage: func() proto.Message {
-			m := &wrapperspb.StringValue{Value: "abcd"}
-			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
-			if err != nil {
-				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
-			}
-			return &anypb.Any{
-				TypeUrl: "google.protobuf.StringValue",
-				Value:   bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
-			}
-		}(),
 		wantErr: true,
 	}, {
 		desc: "Any with Int64Value",
@@ -2227,17 +2146,6 @@ func TestUnmarshal(t *testing.T) {
   "@type": "google.protobuf.Value",
   "value": "` + "abc\xff" + `"
 }`,
-		wantMessage: func() proto.Message {
-			m := &structpb.Value{Kind: &structpb.Value_StringValue{"abcd"}}
-			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
-			if err != nil {
-				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
-			}
-			return &anypb.Any{
-				TypeUrl: "google.protobuf.Value",
-				Value:   bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
-			}
-		}(),
 		wantErr: true,
 	}, {
 		desc: "Any with Value of NullValue",
@@ -2380,26 +2288,6 @@ func TestUnmarshal(t *testing.T) {
 	"value": "` + "abc\xff" + `"
   }
 }`,
-		wantMessage: func() proto.Message {
-			m1 := &wrapperspb.StringValue{Value: "abcd"}
-			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
-			if err != nil {
-				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
-			}
-			m2 := &anypb.Any{
-				TypeUrl: "google.protobuf.StringValue",
-				Value:   b,
-			}
-			m3 := &pb2.KnownTypes{OptAny: m2}
-			b, err = proto.MarshalOptions{Deterministic: true}.Marshal(m3)
-			if err != nil {
-				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
-			}
-			return &anypb.Any{
-				TypeUrl: "pb2.KnownTypes",
-				Value:   bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
-			}
-		}(),
 		wantErr: true,
 	}, {
 		desc: "well known types as field values",

+ 23 - 33
encoding/protojson/encode.go

@@ -10,7 +10,6 @@ import (
 	"sort"
 
 	"google.golang.org/protobuf/internal/encoding/json"
-	"google.golang.org/protobuf/internal/errors"
 	"google.golang.org/protobuf/internal/pragma"
 	"google.golang.org/protobuf/proto"
 	pref "google.golang.org/protobuf/reflect/protoreflect"
@@ -58,38 +57,33 @@ func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
 		o.Resolver = protoregistry.GlobalTypes
 	}
 
-	var nerr errors.NonFatal
 	err = o.marshalMessage(m.ProtoReflect())
-	if !nerr.Merge(err) {
+	if err != nil {
 		return nil, err
 	}
-	if !o.AllowPartial {
-		nerr.Merge(proto.IsInitialized(m))
+	if o.AllowPartial {
+		return o.encoder.Bytes(), nil
 	}
-	return o.encoder.Bytes(), nerr.E
+	return o.encoder.Bytes(), proto.IsInitialized(m)
 }
 
 // marshalMessage marshals the given protoreflect.Message.
 func (o MarshalOptions) marshalMessage(m pref.Message) error {
-	var nerr errors.NonFatal
-
 	if isCustomType(m.Descriptor().FullName()) {
 		return o.marshalCustomType(m)
 	}
 
 	o.encoder.StartObject()
 	defer o.encoder.EndObject()
-	if err := o.marshalFields(m); !nerr.Merge(err) {
+	if err := o.marshalFields(m); err != nil {
 		return err
 	}
 
-	return nerr.E
+	return nil
 }
 
 // marshalFields marshals the fields in the given protoreflect.Message.
 func (o MarshalOptions) marshalFields(m pref.Message) error {
-	var nerr errors.NonFatal
-
 	// Marshal out known fields.
 	fieldDescs := m.Descriptor().Fields()
 	for i := 0; i < fieldDescs.Len(); i++ {
@@ -100,19 +94,19 @@ func (o MarshalOptions) marshalFields(m pref.Message) error {
 
 		name := fd.JSONName()
 		val := m.Get(fd)
-		if err := o.encoder.WriteName(name); !nerr.Merge(err) {
+		if err := o.encoder.WriteName(name); err != nil {
 			return err
 		}
-		if err := o.marshalValue(val, fd); !nerr.Merge(err) {
+		if err := o.marshalValue(val, fd); err != nil {
 			return err
 		}
 	}
 
 	// Marshal out extensions.
-	if err := o.marshalExtensions(m); !nerr.Merge(err) {
+	if err := o.marshalExtensions(m); err != nil {
 		return err
 	}
-	return nerr.E
+	return nil
 }
 
 // marshalValue marshals the given protoreflect.Value.
@@ -130,13 +124,12 @@ func (o MarshalOptions) marshalValue(val pref.Value, fd pref.FieldDescriptor) er
 // marshalSingular marshals the given non-repeated field value. This includes
 // all scalar types, enums, messages, and groups.
 func (o MarshalOptions) marshalSingular(val pref.Value, fd pref.FieldDescriptor) error {
-	var nerr errors.NonFatal
 	switch kind := fd.Kind(); kind {
 	case pref.BoolKind:
 		o.encoder.WriteBool(val.Bool())
 
 	case pref.StringKind:
-		if err := o.encoder.WriteString(val.String()); !nerr.Merge(err) {
+		if err := o.encoder.WriteString(val.String()); err != nil {
 			return err
 		}
 
@@ -161,7 +154,7 @@ func (o MarshalOptions) marshalSingular(val pref.Value, fd pref.FieldDescriptor)
 
 	case pref.BytesKind:
 		err := o.encoder.WriteString(base64.StdEncoding.EncodeToString(val.Bytes()))
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 
@@ -170,7 +163,7 @@ func (o MarshalOptions) marshalSingular(val pref.Value, fd pref.FieldDescriptor)
 			o.encoder.WriteNull()
 		} else if desc := fd.Enum().Values().ByNumber(val.Enum()); desc != nil {
 			err := o.encoder.WriteString(string(desc.Name()))
-			if !nerr.Merge(err) {
+			if err != nil {
 				return err
 			}
 		} else {
@@ -179,14 +172,14 @@ func (o MarshalOptions) marshalSingular(val pref.Value, fd pref.FieldDescriptor)
 		}
 
 	case pref.MessageKind, pref.GroupKind:
-		if err := o.marshalMessage(val.Message()); !nerr.Merge(err) {
+		if err := o.marshalMessage(val.Message()); err != nil {
 			return err
 		}
 
 	default:
 		panic(fmt.Sprintf("%v has unknown kind: %v", fd.FullName(), kind))
 	}
-	return nerr.E
+	return nil
 }
 
 // marshalList marshals the given protoreflect.List.
@@ -194,14 +187,13 @@ func (o MarshalOptions) marshalList(list pref.List, fd pref.FieldDescriptor) err
 	o.encoder.StartArray()
 	defer o.encoder.EndArray()
 
-	var nerr errors.NonFatal
 	for i := 0; i < list.Len(); i++ {
 		item := list.Get(i)
-		if err := o.marshalSingular(item, fd); !nerr.Merge(err) {
+		if err := o.marshalSingular(item, fd); err != nil {
 			return err
 		}
 	}
-	return nerr.E
+	return nil
 }
 
 type mapEntry struct {
@@ -223,16 +215,15 @@ func (o MarshalOptions) marshalMap(mmap pref.Map, fd pref.FieldDescriptor) error
 	sortMap(fd.MapKey().Kind(), entries)
 
 	// Write out sorted list.
-	var nerr errors.NonFatal
 	for _, entry := range entries {
-		if err := o.encoder.WriteName(entry.key.String()); !nerr.Merge(err) {
+		if err := o.encoder.WriteName(entry.key.String()); err != nil {
 			return err
 		}
-		if err := o.marshalSingular(entry.value, fd.MapValue()); !nerr.Merge(err) {
+		if err := o.marshalSingular(entry.value, fd.MapValue()); err != nil {
 			return err
 		}
 	}
-	return nerr.E
+	return nil
 }
 
 // sortMap orders list based on value of key field for deterministic ordering.
@@ -288,19 +279,18 @@ func (o MarshalOptions) marshalExtensions(m pref.Message) error {
 	})
 
 	// Write out sorted list.
-	var nerr errors.NonFatal
 	for _, entry := range entries {
 		// JSON field name is the proto field name enclosed in [], similar to
 		// textproto. This is consistent with Go v1 lib. C++ lib v3.7.0 does not
 		// marshal out extension fields.
-		if err := o.encoder.WriteName("[" + entry.key + "]"); !nerr.Merge(err) {
+		if err := o.encoder.WriteName("[" + entry.key + "]"); err != nil {
 			return err
 		}
-		if err := o.marshalValue(entry.value, entry.desc); !nerr.Merge(err) {
+		if err := o.marshalValue(entry.value, entry.desc); err != nil {
 			return err
 		}
 	}
-	return nerr.E
+	return nil
 }
 
 // isMessageSetExtension reports whether extension extends a message set.

+ 0 - 18
encoding/protojson/encode_test.go

@@ -159,7 +159,6 @@ func TestMarshal(t *testing.T) {
 		input: &pb3.Scalars{
 			SString: "abc\xff",
 		},
-		want:    "{\n  \"sString\": \"abc\xff\"\n}",
 		wantErr: true,
 	}, {
 		desc: "float nan",
@@ -1149,14 +1148,12 @@ func TestMarshal(t *testing.T) {
 	}, {
 		desc:    "StringValue with invalid UTF8 error",
 		input:   &wrapperspb.StringValue{Value: "abc\xff"},
-		want:    "\"abc\xff\"",
 		wantErr: true,
 	}, {
 		desc: "StringValue field with invalid UTF8 error",
 		input: &pb2.KnownTypes{
 			OptString: &wrapperspb.StringValue{Value: "abc\xff"},
 		},
-		want:    "{\n  \"optString\": \"abc\xff\"\n}",
 		wantErr: true,
 	}, {
 		desc:  "BytesValue",
@@ -1201,7 +1198,6 @@ func TestMarshal(t *testing.T) {
 	}, {
 		desc:    "Value contains StringValue with invalid UTF8",
 		input:   &structpb.Value{Kind: &structpb.Value_StringValue{"\xff"}},
-		want:    "\"\xff\"",
 		wantErr: true,
 	}, {
 		desc: "Value contains Struct",
@@ -1312,7 +1308,6 @@ func TestMarshal(t *testing.T) {
 				"string": {Kind: &structpb.Value_StringValue{"\xff"}},
 			},
 		},
-		want:    "{\n  \"string\": \"\xff\"\n}",
 		wantErr: true,
 	}, {
 		desc:  "ListValue with nil values",
@@ -1375,7 +1370,6 @@ func TestMarshal(t *testing.T) {
 				{Kind: &structpb.Value_StringValue{"\xff"}},
 			},
 		},
-		want:    "[\n  \"\xff\"\n]",
 		wantErr: true,
 	}, {
 		desc:  "Duration empty",
@@ -1631,10 +1625,6 @@ func TestMarshal(t *testing.T) {
 				Value:   b,
 			}
 		}(),
-		want: `{
-  "@type": "foo/pb2.Nested",
-  "optString": "` + "abc\xff" + `"
-}`,
 		wantErr: true,
 	}, {
 		desc: "Any with invalid value",
@@ -1702,10 +1692,6 @@ func TestMarshal(t *testing.T) {
 				Value:   bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
 			}
 		}(),
-		want: `{
-  "@type": "google.protobuf.StringValue",
-  "value": "` + "abc\xff" + `"
-}`,
 		wantErr: true,
 	}, {
 		desc: "Any with Int64Value",
@@ -1780,10 +1766,6 @@ func TestMarshal(t *testing.T) {
 				Value:   bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
 			}
 		}(),
-		want: `{
-  "@type": "type.googleapis.com/google.protobuf.Value",
-  "value": "` + "abc\xff" + `"
-}`,
 		wantErr: true,
 	}, {
 		desc: "Any with Value of NullValue",

+ 40 - 51
encoding/protojson/well_known_types.go

@@ -166,14 +166,13 @@ func (o MarshalOptions) marshalAny(m pref.Message) error {
 	// Marshal out @type field.
 	typeURL := typeVal.String()
 	o.encoder.WriteName("@type")
-	var nerr errors.NonFatal
-	if err := o.encoder.WriteString(typeURL); !nerr.Merge(err) {
+	if err := o.encoder.WriteString(typeURL); err != nil {
 		return err
 	}
 
 	// Resolve the type in order to unmarshal value field.
 	emt, err := o.Resolver.FindMessageByURL(typeURL)
-	if !nerr.Merge(err) {
+	if err != nil {
 		return errors.New("%s: unable to resolve %q: %v", m.Descriptor().FullName(), typeURL, err)
 	}
 
@@ -182,7 +181,7 @@ func (o MarshalOptions) marshalAny(m pref.Message) error {
 		AllowPartial: true, // never check required fields inside an Any
 		Resolver:     o.Resolver,
 	}.Unmarshal(valueVal.Bytes(), em.Interface())
-	if !nerr.Merge(err) {
+	if err != nil {
 		return errors.New("%s: unable to unmarshal %q: %v", m.Descriptor().FullName(), typeURL, err)
 	}
 
@@ -195,11 +194,11 @@ func (o MarshalOptions) marshalAny(m pref.Message) error {
 	}
 
 	// Else, marshal out the embedded message's fields in this Any object.
-	if err := o.marshalFields(em); !nerr.Merge(err) {
+	if err := o.marshalFields(em); err != nil {
 		return err
 	}
 
-	return nerr.E
+	return nil
 }
 
 func (o UnmarshalOptions) unmarshalAny(m pref.Message) error {
@@ -224,8 +223,7 @@ func (o UnmarshalOptions) unmarshalAny(m pref.Message) error {
 		// Treat all fields as unknowns, similar to an empty object.
 		return skipJSONValue(o.decoder)
 	}
-	var nerr errors.NonFatal
-	if !nerr.Merge(err) {
+	if err != nil {
 		return errors.New("google.protobuf.Any: %v", err)
 	}
 
@@ -239,12 +237,12 @@ func (o UnmarshalOptions) unmarshalAny(m pref.Message) error {
 	if isCustomType(emt.Descriptor().FullName()) {
 		// If embedded message is a custom type, unmarshal the JSON "value" field
 		// into it.
-		if err := o.unmarshalAnyValue(em); !nerr.Merge(err) {
+		if err := o.unmarshalAnyValue(em); err != nil {
 			return errors.New("google.protobuf.Any: %v", err)
 		}
 	} else {
 		// Else unmarshal the current JSON object into it.
-		if err := o.unmarshalMessage(em, true); !nerr.Merge(err) {
+		if err := o.unmarshalMessage(em, true); err != nil {
 			return errors.New("google.protobuf.Any: %v", err)
 		}
 	}
@@ -254,7 +252,7 @@ func (o UnmarshalOptions) unmarshalAny(m pref.Message) error {
 		AllowPartial:  true, // never check required fields inside an Any
 		Deterministic: true,
 	}.Marshal(em.Interface())
-	if !nerr.Merge(err) {
+	if err != nil {
 		return errors.New("google.protobuf.Any: %v", err)
 	}
 
@@ -264,7 +262,7 @@ func (o UnmarshalOptions) unmarshalAny(m pref.Message) error {
 
 	m.Set(fdType, pref.ValueOf(typeURL))
 	m.Set(fdValue, pref.ValueOf(b))
-	return nerr.E
+	return nil
 }
 
 var errEmptyObject = errors.New(`empty object`)
@@ -276,7 +274,6 @@ var errMissingType = errors.New(`missing "@type" field`)
 // does not contain the field or other decoding problems.
 func findTypeURL(dec *json.Decoder) (string, error) {
 	var typeURL string
-	var nerr errors.NonFatal
 	numFields := 0
 	// Skip start object.
 	dec.Read()
@@ -284,7 +281,7 @@ func findTypeURL(dec *json.Decoder) (string, error) {
 Loop:
 	for {
 		jval, err := dec.Read()
-		if !nerr.Merge(err) {
+		if err != nil {
 			return "", err
 		}
 
@@ -302,12 +299,12 @@ Loop:
 		case json.Name:
 			numFields++
 			name, err := jval.Name()
-			if !nerr.Merge(err) {
+			if err != nil {
 				return "", err
 			}
 			if name != "@type" {
 				// Skip value.
-				if err := skipJSONValue(dec); !nerr.Merge(err) {
+				if err := skipJSONValue(dec); err != nil {
 					return "", err
 				}
 				continue
@@ -319,7 +316,7 @@ Loop:
 			}
 			// Read field value.
 			jval, err := dec.Read()
-			if !nerr.Merge(err) {
+			if err != nil {
 				return "", err
 			}
 			if jval.Type() != json.String {
@@ -332,7 +329,7 @@ Loop:
 		}
 	}
 
-	return typeURL, nerr.E
+	return typeURL, nil
 }
 
 // skipJSONValue makes the given decoder parse a JSON value (null, boolean,
@@ -340,9 +337,8 @@ Loop:
 // JSON value. It relies on Decoder.Read returning an error if the types are
 // not in valid sequence.
 func skipJSONValue(dec *json.Decoder) error {
-	var nerr errors.NonFatal
 	jval, err := dec.Read()
-	if !nerr.Merge(err) {
+	if err != nil {
 		return err
 	}
 	// Only need to continue reading for objects and arrays.
@@ -350,7 +346,7 @@ func skipJSONValue(dec *json.Decoder) error {
 	case json.StartObject:
 		for {
 			jval, err := dec.Read()
-			if !nerr.Merge(err) {
+			if err != nil {
 				return err
 			}
 			switch jval.Type() {
@@ -358,7 +354,7 @@ func skipJSONValue(dec *json.Decoder) error {
 				return nil
 			case json.Name:
 				// Skip object field value.
-				if err := skipJSONValue(dec); !nerr.Merge(err) {
+				if err := skipJSONValue(dec); err != nil {
 					return err
 				}
 			}
@@ -375,26 +371,25 @@ func skipJSONValue(dec *json.Decoder) error {
 				return err
 			default:
 				// Skip array item.
-				if err := skipJSONValue(dec); !nerr.Merge(err) {
+				if err := skipJSONValue(dec); err != nil {
 					return err
 				}
 			}
 		}
 	}
-	return nerr.E
+	return nil
 }
 
 // unmarshalAnyValue unmarshals the given custom-type message from the JSON
 // object's "value" field.
 func (o UnmarshalOptions) unmarshalAnyValue(m pref.Message) error {
-	var nerr errors.NonFatal
 	// Skip StartObject, and start reading the fields.
 	o.decoder.Read()
 
 	var found bool // Used for detecting duplicate "value".
 	for {
 		jval, err := o.decoder.Read()
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 		switch jval.Type() {
@@ -402,17 +397,17 @@ func (o UnmarshalOptions) unmarshalAnyValue(m pref.Message) error {
 			if !found {
 				return errors.New(`missing "value" field`)
 			}
-			return nerr.E
+			return nil
 
 		case json.Name:
 			name, err := jval.Name()
-			if !nerr.Merge(err) {
+			if err != nil {
 				return err
 			}
 			switch name {
 			default:
 				if o.DiscardUnknown {
-					if err := skipJSONValue(o.decoder); !nerr.Merge(err) {
+					if err := skipJSONValue(o.decoder); err != nil {
 						return err
 					}
 					continue
@@ -428,7 +423,7 @@ func (o UnmarshalOptions) unmarshalAnyValue(m pref.Message) error {
 					return errors.New(`duplicate "value" field`)
 				}
 				// Unmarshal the field value into the given message.
-				if err := o.unmarshalCustomType(m); !nerr.Merge(err) {
+				if err := o.unmarshalCustomType(m); err != nil {
 					return err
 				}
 				found = true
@@ -451,12 +446,11 @@ func (o MarshalOptions) marshalWrapperType(m pref.Message) error {
 func (o UnmarshalOptions) unmarshalWrapperType(m pref.Message) error {
 	fd := m.Descriptor().Fields().ByNumber(wrapperFieldNumber)
 	val, err := o.unmarshalScalar(fd)
-	var nerr errors.NonFatal
-	if !nerr.Merge(err) {
+	if err != nil {
 		return err
 	}
 	m.Set(fd, val)
-	return nerr.E
+	return nil
 }
 
 // The JSON representation for Empty is an empty JSON object.
@@ -468,7 +462,6 @@ func (o MarshalOptions) marshalEmpty(pref.Message) error {
 }
 
 func (o UnmarshalOptions) unmarshalEmpty(pref.Message) error {
-	var nerr errors.NonFatal
 	jval, err := o.decoder.Read()
 	if err != nil {
 		return err
@@ -479,16 +472,16 @@ func (o UnmarshalOptions) unmarshalEmpty(pref.Message) error {
 
 	for {
 		jval, err := o.decoder.Read()
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 		switch jval.Type() {
 		case json.EndObject:
-			return nerr.E
+			return nil
 
 		case json.Name:
 			if o.DiscardUnknown {
-				if err := skipJSONValue(o.decoder); !nerr.Merge(err) {
+				if err := skipJSONValue(o.decoder); err != nil {
 					return err
 				}
 				continue
@@ -543,7 +536,6 @@ func (o MarshalOptions) marshalKnownValue(m pref.Message) error {
 }
 
 func (o UnmarshalOptions) unmarshalKnownValue(m pref.Message) error {
-	var nerr errors.NonFatal
 	switch o.decoder.Peek() {
 	case json.Null:
 		o.decoder.Read()
@@ -582,11 +574,11 @@ func (o UnmarshalOptions) unmarshalKnownValue(m pref.Message) error {
 		// always assigned to the string_value field, which means that certain
 		// encoding cannot be parsed back to the same field.
 		jval, err := o.decoder.Read()
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 		val, err := unmarshalString(jval)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 		fd := m.Descriptor().Fields().ByNumber(fieldnum.Value_StringValue)
@@ -595,7 +587,7 @@ func (o UnmarshalOptions) unmarshalKnownValue(m pref.Message) error {
 	case json.StartObject:
 		fd := m.Descriptor().Fields().ByNumber(fieldnum.Value_StructValue)
 		m2 := m.NewMessage(fd)
-		if err := o.unmarshalStruct(m2); !nerr.Merge(err) {
+		if err := o.unmarshalStruct(m2); err != nil {
 			return err
 		}
 		m.Set(fd, pref.ValueOf(m2))
@@ -603,7 +595,7 @@ func (o UnmarshalOptions) unmarshalKnownValue(m pref.Message) error {
 	case json.StartArray:
 		fd := m.Descriptor().Fields().ByNumber(fieldnum.Value_ListValue)
 		m2 := m.NewMessage(fd)
-		if err := o.unmarshalListValue(m2); !nerr.Merge(err) {
+		if err := o.unmarshalListValue(m2); err != nil {
 			return err
 		}
 		m.Set(fd, pref.ValueOf(m2))
@@ -615,7 +607,7 @@ func (o UnmarshalOptions) unmarshalKnownValue(m pref.Message) error {
 		}
 		return unexpectedJSONError{jval}
 	}
-	return nerr.E
+	return nil
 }
 
 // The JSON representation for a Duration is a JSON string that ends in the
@@ -671,9 +663,8 @@ func (o MarshalOptions) marshalDuration(m pref.Message) error {
 }
 
 func (o UnmarshalOptions) unmarshalDuration(m pref.Message) error {
-	var nerr errors.NonFatal
 	jval, err := o.decoder.Read()
-	if !nerr.Merge(err) {
+	if err != nil {
 		return err
 	}
 	if jval.Type() != json.String {
@@ -697,7 +688,7 @@ func (o UnmarshalOptions) unmarshalDuration(m pref.Message) error {
 
 	m.Set(fdSeconds, pref.ValueOf(secs))
 	m.Set(fdNanos, pref.ValueOf(nanos))
-	return nerr.E
+	return nil
 }
 
 // parseDuration parses the given input string for seconds and nanoseconds value
@@ -855,9 +846,8 @@ func (o MarshalOptions) marshalTimestamp(m pref.Message) error {
 }
 
 func (o UnmarshalOptions) unmarshalTimestamp(m pref.Message) error {
-	var nerr errors.NonFatal
 	jval, err := o.decoder.Read()
-	if !nerr.Merge(err) {
+	if err != nil {
 		return err
 	}
 	if jval.Type() != json.String {
@@ -882,7 +872,7 @@ func (o UnmarshalOptions) unmarshalTimestamp(m pref.Message) error {
 
 	m.Set(fdSeconds, pref.ValueOf(secs))
 	m.Set(fdNanos, pref.ValueOf(int32(t.Nanosecond())))
-	return nerr.E
+	return nil
 }
 
 // The JSON representation for a FieldMask is a JSON string where paths are
@@ -910,9 +900,8 @@ func (o MarshalOptions) marshalFieldMask(m pref.Message) error {
 }
 
 func (o UnmarshalOptions) unmarshalFieldMask(m pref.Message) error {
-	var nerr errors.NonFatal
 	jval, err := o.decoder.Read()
-	if !nerr.Merge(err) {
+	if err != nil {
 		return err
 	}
 	if jval.Type() != json.String {

+ 30 - 47
encoding/prototext/decode.go

@@ -45,8 +45,6 @@ type UnmarshalOptions struct {
 // Unmarshal reads the given []byte and populates the given proto.Message using options in
 // UnmarshalOptions object.
 func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
-	var nerr errors.NonFatal
-
 	// Clear all fields before populating it.
 	// TODO: Determine if this needs to be consistent with protojson and binary unmarshal where
 	// behavior is to merge values into existing message. If decision is to not clear the fields
@@ -55,7 +53,7 @@ func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
 
 	// Parse into text.Value of message type.
 	val, err := text.Unmarshal(b)
-	if !nerr.Merge(err) {
+	if err != nil {
 		return err
 	}
 
@@ -63,21 +61,18 @@ func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
 		o.Resolver = protoregistry.GlobalTypes
 	}
 	err = o.unmarshalMessage(val.Message(), m.ProtoReflect())
-	if !nerr.Merge(err) {
+	if err != nil {
 		return err
 	}
 
-	if !o.AllowPartial {
-		nerr.Merge(proto.IsInitialized(m))
+	if o.AllowPartial {
+		return nil
 	}
-
-	return nerr.E
+	return proto.IsInitialized(m)
 }
 
 // unmarshalMessage unmarshals a [][2]text.Value message into the given protoreflect.Message.
 func (o UnmarshalOptions) unmarshalMessage(tmsg [][2]text.Value, m pref.Message) error {
-	var nerr errors.NonFatal
-
 	messageDesc := m.Descriptor()
 
 	// Handle expanded Any message.
@@ -141,7 +136,7 @@ func (o UnmarshalOptions) unmarshalMessage(tmsg [][2]text.Value, m pref.Message)
 			}
 
 			list := m.Mutable(fd).List()
-			if err := o.unmarshalList(items, fd, list); !nerr.Merge(err) {
+			if err := o.unmarshalList(items, fd, list); err != nil {
 				return err
 			}
 		case fd.IsMap():
@@ -154,7 +149,7 @@ func (o UnmarshalOptions) unmarshalMessage(tmsg [][2]text.Value, m pref.Message)
 			}
 
 			mmap := m.Mutable(fd).Map()
-			if err := o.unmarshalMap(items, fd, mmap); !nerr.Merge(err) {
+			if err := o.unmarshalMap(items, fd, mmap); err != nil {
 				return err
 			}
 		default:
@@ -172,14 +167,14 @@ func (o UnmarshalOptions) unmarshalMessage(tmsg [][2]text.Value, m pref.Message)
 			if seenNums.Has(num) {
 				return errors.New("non-repeated field %v is repeated", fd.FullName())
 			}
-			if err := o.unmarshalSingular(tval, fd, m); !nerr.Merge(err) {
+			if err := o.unmarshalSingular(tval, fd, m); err != nil {
 				return err
 			}
 			seenNums.Set(num)
 		}
 	}
 
-	return nerr.E
+	return nil
 }
 
 // findExtension returns protoreflect.ExtensionType from the Resolver if found.
@@ -199,7 +194,6 @@ func (o UnmarshalOptions) findExtension(xtName pref.FullName) (pref.ExtensionTyp
 
 // unmarshalSingular unmarshals given text.Value into the non-repeated field.
 func (o UnmarshalOptions) unmarshalSingular(input text.Value, fd pref.FieldDescriptor, m pref.Message) error {
-	var nerr errors.NonFatal
 	var val pref.Value
 	switch fd.Kind() {
 	case pref.MessageKind, pref.GroupKind:
@@ -207,20 +201,20 @@ func (o UnmarshalOptions) unmarshalSingular(input text.Value, fd pref.FieldDescr
 			return errors.New("%v contains invalid message/group value: %v", fd.FullName(), input)
 		}
 		m2 := m.NewMessage(fd)
-		if err := o.unmarshalMessage(input.Message(), m2); !nerr.Merge(err) {
+		if err := o.unmarshalMessage(input.Message(), m2); err != nil {
 			return err
 		}
 		val = pref.ValueOf(m2)
 	default:
 		var err error
 		val, err = unmarshalScalar(input, fd)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 	}
 	m.Set(fd, val)
 
-	return nerr.E
+	return nil
 }
 
 // unmarshalScalar converts the given text.Value to a scalar/enum protoreflect.Value specified in
@@ -264,9 +258,7 @@ func unmarshalScalar(input text.Value, fd pref.FieldDescriptor) (pref.Value, err
 			if utf8.ValidString(s) {
 				return pref.ValueOf(s), nil
 			}
-			var nerr errors.NonFatal
-			nerr.AppendInvalidUTF8(string(fd.FullName()))
-			return pref.ValueOf(s), nerr.E
+			return pref.Value{}, errors.InvalidUTF8(string(fd.FullName()))
 		}
 	case pref.BytesKind:
 		if input.Type() == text.String {
@@ -292,8 +284,6 @@ func unmarshalScalar(input text.Value, fd pref.FieldDescriptor) (pref.Value, err
 
 // unmarshalList unmarshals given []text.Value into given protoreflect.List.
 func (o UnmarshalOptions) unmarshalList(inputList []text.Value, fd pref.FieldDescriptor, list pref.List) error {
-	var nerr errors.NonFatal
-
 	switch fd.Kind() {
 	case pref.MessageKind, pref.GroupKind:
 		for _, input := range inputList {
@@ -301,7 +291,7 @@ func (o UnmarshalOptions) unmarshalList(inputList []text.Value, fd pref.FieldDes
 				return errors.New("%v contains invalid message/group value: %v", fd.FullName(), input)
 			}
 			m := list.NewMessage()
-			if err := o.unmarshalMessage(input.Message(), m); !nerr.Merge(err) {
+			if err := o.unmarshalMessage(input.Message(), m); err != nil {
 				return err
 			}
 			list.Append(pref.ValueOf(m))
@@ -309,20 +299,18 @@ func (o UnmarshalOptions) unmarshalList(inputList []text.Value, fd pref.FieldDes
 	default:
 		for _, input := range inputList {
 			val, err := unmarshalScalar(input, fd)
-			if !nerr.Merge(err) {
+			if err != nil {
 				return err
 			}
 			list.Append(val)
 		}
 	}
 
-	return nerr.E
+	return nil
 }
 
 // unmarshalMap unmarshals given []text.Value into given protoreflect.Map.
 func (o UnmarshalOptions) unmarshalMap(input []text.Value, fd pref.FieldDescriptor, mmap pref.Map) error {
-	var nerr errors.NonFatal
-
 	// Determine ahead whether map entry is a scalar type or a message type in order to call the
 	// appropriate unmarshalMapValue func inside the for loop below.
 	unmarshalMapValue := unmarshalMapScalarValue
@@ -336,20 +324,20 @@ func (o UnmarshalOptions) unmarshalMap(input []text.Value, fd pref.FieldDescript
 			return errors.New("%v contains invalid map entry: %v", fd.FullName(), entry)
 		}
 		tkey, tval, err := parseMapEntry(entry.Message(), fd.FullName())
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 		pkey, err := unmarshalMapKey(tkey, fd.MapKey())
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 		err = unmarshalMapValue(tval, pkey, fd.MapValue(), mmap)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 	}
 
-	return nerr.E
+	return nil
 }
 
 // parseMapEntry parses [][2]text.Value for field names key and value, and return corresponding
@@ -391,46 +379,43 @@ func unmarshalMapKey(input text.Value, fd pref.FieldDescriptor) (pref.MapKey, er
 		return fd.Default().MapKey(), nil
 	}
 
-	var nerr errors.NonFatal
 	val, err := unmarshalScalar(input, fd)
-	if !nerr.Merge(err) {
+	if err != nil {
 		return pref.MapKey{}, errors.New("%v contains invalid key: %v", fd.FullName(), input)
 	}
-	return val.MapKey(), nerr.E
+	return val.MapKey(), nil
 }
 
 // unmarshalMapMessageValue unmarshals given message-type text.Value into a protoreflect.Map for
 // the given MapKey.
 func (o UnmarshalOptions) unmarshalMapMessageValue(input text.Value, pkey pref.MapKey, _ pref.FieldDescriptor, mmap pref.Map) error {
-	var nerr errors.NonFatal
 	var value [][2]text.Value
 	if input.Type() != 0 {
 		value = input.Message()
 	}
 	m := mmap.NewMessage()
-	if err := o.unmarshalMessage(value, m); !nerr.Merge(err) {
+	if err := o.unmarshalMessage(value, m); err != nil {
 		return err
 	}
 	mmap.Set(pkey, pref.ValueOf(m))
-	return nerr.E
+	return nil
 }
 
 // unmarshalMapScalarValue unmarshals given scalar-type text.Value into a protoreflect.Map
 // for the given MapKey.
 func unmarshalMapScalarValue(input text.Value, pkey pref.MapKey, fd pref.FieldDescriptor, mmap pref.Map) error {
-	var nerr errors.NonFatal
 	var val pref.Value
 	if input.Type() == 0 {
 		val = fd.Default()
 	} else {
 		var err error
 		val, err = unmarshalScalar(input, fd)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return err
 		}
 	}
 	mmap.Set(pkey, val)
-	return nerr.E
+	return nil
 }
 
 // isExpandedAny returns true if given [][2]text.Value may be an expanded Any that contains only one
@@ -447,19 +432,17 @@ func isExpandedAny(tmsg [][2]text.Value) bool {
 // unmarshalAny unmarshals an expanded Any textproto. This method assumes that the given
 // tfield has key type of text.String and value type of text.Message.
 func (o UnmarshalOptions) unmarshalAny(tfield [2]text.Value, m pref.Message) error {
-	var nerr errors.NonFatal
-
 	typeURL := tfield[0].String()
 	value := tfield[1].Message()
 
 	mt, err := o.Resolver.FindMessageByURL(typeURL)
-	if !nerr.Merge(err) {
+	if err != nil {
 		return errors.New("unable to resolve message [%v]: %v", typeURL, err)
 	}
 	// Create new message for the embedded message type and unmarshal the
 	// value into it.
 	m2 := mt.New()
-	if err := o.unmarshalMessage(value, m2); !nerr.Merge(err) {
+	if err := o.unmarshalMessage(value, m2); err != nil {
 		return err
 	}
 	// Serialize the embedded message and assign the resulting bytes to the value field.
@@ -467,7 +450,7 @@ func (o UnmarshalOptions) unmarshalAny(tfield [2]text.Value, m pref.Message) err
 		AllowPartial:  true, // never check required fields inside an Any
 		Deterministic: true,
 	}.Marshal(m2.Interface())
-	if !nerr.Merge(err) {
+	if err != nil {
 		return err
 	}
 
@@ -478,5 +461,5 @@ func (o UnmarshalOptions) unmarshalAny(tfield [2]text.Value, m pref.Message) err
 	m.Set(fdType, pref.ValueOf(typeURL))
 	m.Set(fdValue, pref.ValueOf(b))
 
-	return nerr.E
+	return nil
 }

+ 3 - 44
encoding/prototext/decode_test.go

@@ -10,7 +10,6 @@ import (
 
 	protoV1 "github.com/golang/protobuf/proto"
 	"google.golang.org/protobuf/encoding/prototext"
-	"google.golang.org/protobuf/internal/errors"
 	pimpl "google.golang.org/protobuf/internal/impl"
 	"google.golang.org/protobuf/internal/scalar"
 	"google.golang.org/protobuf/proto"
@@ -157,10 +156,7 @@ s_string: "谷歌"
 		desc:         "string with invalid UTF-8",
 		inputMessage: &pb3.Scalars{},
 		inputText:    `s_string: "abc\xff"`,
-		wantMessage: &pb3.Scalars{
-			SString: "abc\xff",
-		},
-		wantErr: true,
+		wantErr:      true,
 	}, {
 		desc:         "proto2 message contains unknown field",
 		inputMessage: &pb2.Scalars{},
@@ -459,11 +455,6 @@ s_nested: {
   s_string: "abc\xff"
 }
 `,
-		wantMessage: &pb3.Nests{
-			SNested: &pb3.Nested{
-				SString: "abc\xff",
-			},
-		},
 		wantErr: true,
 	}, {
 		desc:         "oneof set to empty string",
@@ -556,10 +547,7 @@ rpt_string: "b"
 		desc:         "repeated contains invalid UTF-8",
 		inputMessage: &pb2.Repeats{},
 		inputText:    `rpt_string: "abc\xff"`,
-		wantMessage: &pb2.Repeats{
-			RptString: []string{"abc\xff"},
-		},
-		wantErr: true,
+		wantErr:      true,
 	}, {
 		desc:         "repeated enums",
 		inputMessage: &pb2.Enums{},
@@ -878,11 +866,6 @@ int32_to_str: {}
   value: "abc\xff"
 }
 `,
-		wantMessage: &pb3.Maps{
-			Int32ToStr: map[int32]string{
-				101: "abc\xff",
-			},
-		},
 		wantErr: true,
 	}, {
 		desc:         "map field key contains invalid UTF-8",
@@ -892,11 +875,6 @@ int32_to_str: {}
   value: {}
 }
 `,
-		wantMessage: &pb3.Maps{
-			StrToNested: map[string]*pb3.Nested{
-				"abc\xff": {},
-			},
-		},
 		wantErr: true,
 	}, {
 		desc:         "map contains unknown field",
@@ -1196,12 +1174,7 @@ opt_int32: 42
 		desc:         "extension field contains invalid UTF-8",
 		inputMessage: &pb2.Extensions{},
 		inputText:    `[pb2.opt_ext_string]: "abc\xff"`,
-		wantMessage: func() proto.Message {
-			m := &pb2.Extensions{}
-			setExtension(m, pb2.E_OptExtString, "abc\xff")
-			return m
-		}(),
-		wantErr: true,
+		wantErr:      true,
 	}, {
 		desc:         "extensions of repeated fields",
 		inputMessage: &pb2.Extensions{},
@@ -1466,20 +1439,6 @@ value: "some bytes"
   s_string: "abc\xff"
 }
 `,
-		wantMessage: func() proto.Message {
-			m := &pb3.Nested{
-				SString: "abc\xff",
-			}
-			var nerr errors.NonFatal
-			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
-			if !nerr.Merge(err) {
-				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
-			}
-			return &anypb.Any{
-				TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
-				Value:   b,
-			}
-		}(),
 		wantErr: true,
 	}, {
 		desc:         "Any expanded with unregistered type",

+ 30 - 41
encoding/prototext/encode.go

@@ -53,38 +53,35 @@ func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
 		o.Resolver = protoregistry.GlobalTypes
 	}
 
-	var nerr errors.NonFatal
 	v, err := o.marshalMessage(m.ProtoReflect())
-	if !nerr.Merge(err) {
+	if err != nil {
 		return nil, err
 	}
 
 	delims := [2]byte{'{', '}'}
 	const outputASCII = false
 	b, err := text.Marshal(v, o.Indent, delims, outputASCII)
-	if !nerr.Merge(err) {
+	if err != nil {
 		return nil, err
 	}
-	if !o.AllowPartial {
-		nerr.Merge(proto.IsInitialized(m))
+	if o.AllowPartial {
+		return b, nil
 	}
-	return b, nerr.E
+	return b, proto.IsInitialized(m)
 }
 
 // marshalMessage converts a protoreflect.Message to a text.Value.
 func (o MarshalOptions) marshalMessage(m pref.Message) (text.Value, error) {
-	var nerr errors.NonFatal
 	var msgFields [][2]text.Value
 	messageDesc := m.Descriptor()
 
 	// Handle Any expansion.
 	if messageDesc.FullName() == "google.protobuf.Any" {
-		msg, err := o.marshalAny(m)
-		if err == nil || nerr.Merge(err) {
-			// Return as is for nil or non-fatal error.
-			return msg, nerr.E
+		if msg, err := o.marshalAny(m); err == nil {
+			// Return as is if no error.
+			return msg, nil
 		}
-		// For other errors, continue on to marshal Any as a regular message.
+		// Otherwise continue on to marshal Any as a regular message.
 	}
 
 	// Handle known fields.
@@ -104,7 +101,7 @@ func (o MarshalOptions) marshalMessage(m pref.Message) (text.Value, error) {
 		pval := m.Get(fd)
 		var err error
 		msgFields, err = o.appendField(msgFields, name, pval, fd)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return text.Value{}, err
 		}
 	}
@@ -112,7 +109,7 @@ func (o MarshalOptions) marshalMessage(m pref.Message) (text.Value, error) {
 	// Handle extensions.
 	var err error
 	msgFields, err = o.appendExtensions(msgFields, m)
-	if !nerr.Merge(err) {
+	if err != nil {
 		return text.Value{}, err
 	}
 
@@ -120,17 +117,15 @@ func (o MarshalOptions) marshalMessage(m pref.Message) (text.Value, error) {
 	// TODO: Provide option to exclude or include unknown fields.
 	msgFields = appendUnknown(msgFields, m.GetUnknown())
 
-	return text.ValueOf(msgFields), nerr.E
+	return text.ValueOf(msgFields), nil
 }
 
 // appendField marshals a protoreflect.Value and appends it to the given [][2]text.Value.
 func (o MarshalOptions) appendField(msgFields [][2]text.Value, name text.Value, pval pref.Value, fd pref.FieldDescriptor) ([][2]text.Value, error) {
-	var nerr errors.NonFatal
-
 	switch {
 	case fd.IsList():
 		items, err := o.marshalList(pval.List(), fd)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return msgFields, err
 		}
 
@@ -139,7 +134,7 @@ func (o MarshalOptions) appendField(msgFields [][2]text.Value, name text.Value,
 		}
 	case fd.IsMap():
 		items, err := o.marshalMap(pval.Map(), fd)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return msgFields, err
 		}
 
@@ -148,13 +143,13 @@ func (o MarshalOptions) appendField(msgFields [][2]text.Value, name text.Value,
 		}
 	default:
 		tval, err := o.marshalSingular(pval, fd)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return msgFields, err
 		}
 		msgFields = append(msgFields, [2]text.Value{name, tval})
 	}
 
-	return msgFields, nerr.E
+	return msgFields, nil
 }
 
 // marshalSingular converts a non-repeated field value to text.Value.
@@ -173,12 +168,10 @@ func (o MarshalOptions) marshalSingular(val pref.Value, fd pref.FieldDescriptor)
 
 	case pref.StringKind:
 		s := val.String()
-		if utf8.ValidString(s) {
-			return text.ValueOf(s), nil
+		if !utf8.ValidString(s) {
+			return text.Value{}, errors.InvalidUTF8(string(fd.FullName()))
 		}
-		var nerr errors.NonFatal
-		nerr.AppendInvalidUTF8(string(fd.FullName()))
-		return text.ValueOf(s), nerr.E
+		return text.ValueOf(s), nil
 
 	case pref.EnumKind:
 		num := val.Enum()
@@ -197,21 +190,20 @@ func (o MarshalOptions) marshalSingular(val pref.Value, fd pref.FieldDescriptor)
 
 // marshalList converts a protoreflect.List to []text.Value.
 func (o MarshalOptions) marshalList(list pref.List, fd pref.FieldDescriptor) ([]text.Value, error) {
-	var nerr errors.NonFatal
 	size := list.Len()
 	values := make([]text.Value, 0, size)
 
 	for i := 0; i < size; i++ {
 		item := list.Get(i)
 		val, err := o.marshalSingular(item, fd)
-		if !nerr.Merge(err) {
+		if err != nil {
 			// Return already marshaled values.
 			return values, err
 		}
 		values = append(values, val)
 	}
 
-	return values, nerr.E
+	return values, nil
 }
 
 var (
@@ -221,7 +213,6 @@ var (
 
 // marshalMap converts a protoreflect.Map to []text.Value.
 func (o MarshalOptions) marshalMap(mmap pref.Map, fd pref.FieldDescriptor) ([]text.Value, error) {
-	var nerr errors.NonFatal
 	// values is a list of messages.
 	values := make([]text.Value, 0, mmap.Len())
 
@@ -229,12 +220,12 @@ func (o MarshalOptions) marshalMap(mmap pref.Map, fd pref.FieldDescriptor) ([]te
 	mapsort.Range(mmap, fd.MapKey().Kind(), func(key pref.MapKey, val pref.Value) bool {
 		var keyTxtVal text.Value
 		keyTxtVal, err = o.marshalSingular(key.Value(), fd.MapKey())
-		if !nerr.Merge(err) {
+		if err != nil {
 			return false
 		}
 		var valTxtVal text.Value
 		valTxtVal, err = o.marshalSingular(val, fd.MapValue())
-		if !nerr.Merge(err) {
+		if err != nil {
 			return false
 		}
 		// Map entry (message) contains 2 fields, first field for key and second field for value.
@@ -250,12 +241,11 @@ func (o MarshalOptions) marshalMap(mmap pref.Map, fd pref.FieldDescriptor) ([]te
 		return nil, err
 	}
 
-	return values, nerr.E
+	return values, nil
 }
 
 // appendExtensions marshals extension fields and appends them to the given [][2]text.Value.
 func (o MarshalOptions) appendExtensions(msgFields [][2]text.Value, m pref.Message) ([][2]text.Value, error) {
-	var nerr errors.NonFatal
 	var err error
 	var entries [][2]text.Value
 	m.Range(func(fd pref.FieldDescriptor, v pref.Value) bool {
@@ -273,7 +263,7 @@ func (o MarshalOptions) appendExtensions(msgFields [][2]text.Value, m pref.Messa
 		// Use string type to produce [name] format.
 		tname := text.ValueOf(string(name))
 		entries, err = o.appendField(entries, tname, v, xt)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return false
 		}
 		err = nil
@@ -287,7 +277,7 @@ func (o MarshalOptions) appendExtensions(msgFields [][2]text.Value, m pref.Messa
 	sort.SliceStable(entries, func(i, j int) bool {
 		return entries[i][0].String() < entries[j][0].String()
 	})
-	return append(msgFields, entries...), nerr.E
+	return append(msgFields, entries...), nil
 }
 
 // isMessageSetExtension reports whether extension extends a message set.
@@ -348,9 +338,8 @@ func (o MarshalOptions) marshalAny(m pref.Message) (text.Value, error) {
 	typeURL := m.Get(fdType).String()
 	value := m.Get(fdValue)
 
-	var nerr errors.NonFatal
 	emt, err := o.Resolver.FindMessageByURL(typeURL)
-	if !nerr.Merge(err) {
+	if err != nil {
 		return text.Value{}, err
 	}
 	em := emt.New().Interface()
@@ -358,12 +347,12 @@ func (o MarshalOptions) marshalAny(m pref.Message) (text.Value, error) {
 		AllowPartial: true,
 		Resolver:     o.Resolver,
 	}.Unmarshal(value.Bytes(), em)
-	if !nerr.Merge(err) {
+	if err != nil {
 		return text.Value{}, err
 	}
 
 	msg, err := o.marshalMessage(em.ProtoReflect())
-	if !nerr.Merge(err) {
+	if err != nil {
 		return text.Value{}, err
 	}
 	// Expanded Any field value contains only a single field with the type_url field value as the
@@ -374,5 +363,5 @@ func (o MarshalOptions) marshalAny(m pref.Message) (text.Value, error) {
 			msg,
 		},
 	}
-	return text.ValueOf(msgFields), nerr.E
+	return text.ValueOf(msgFields), nil
 }

+ 0 - 44
encoding/prototext/encode_test.go

@@ -5,7 +5,6 @@
 package prototext_test
 
 import (
-	"bytes"
 	"encoding/hex"
 	"math"
 	"testing"
@@ -162,8 +161,6 @@ opt_string: "谷歌"
 		input: &pb3.Scalars{
 			SString: "abc\xff",
 		},
-		want: `s_string: "abc\xff"
-`,
 		wantErr: true,
 	}, {
 		desc: "float nan",
@@ -366,10 +363,6 @@ OptGroup: {}
 				SString: "abc\xff",
 			},
 		},
-		want: `s_nested: {
-  s_string: "abc\xff"
-}
-`,
 		wantErr: true,
 	}, {
 		desc:  "oneof not set",
@@ -485,8 +478,6 @@ rpt_bytes: "世界"
 		input: &pb2.Repeats{
 			RptString: []string{"abc\xff"},
 		},
-		want: `rpt_string: "abc\xff"
-`,
 		wantErr: true,
 	}, {
 		desc: "repeated enums",
@@ -693,11 +684,6 @@ str_to_oneofs: {
 				101: "abc\xff",
 			},
 		},
-		want: `int32_to_str: {
-  key: 101
-  value: "abc\xff"
-}
-`,
 		wantErr: true,
 	}, {
 		desc: "map field key contains invalid UTF-8",
@@ -706,11 +692,6 @@ str_to_oneofs: {
 				"abc\xff": {},
 			},
 		},
-		want: `str_to_nested: {
-  key: "abc\xff"
-  value: {}
-}
-`,
 		wantErr: true,
 	}, {
 		desc: "map field contains nil value",
@@ -967,8 +948,6 @@ opt_int32: 42
 			setExtension(m, pb2.E_OptExtString, "abc\xff")
 			return m
 		}(),
-		want: `[pb2.opt_ext_string]: "abc\xff"
-`,
 		wantErr: true,
 	}, {
 		desc: "extension partial returns error",
@@ -1220,29 +1199,6 @@ value: "\n\x13embedded inside Any\x12\x0b\n\tinception"
   opt_string: "embedded inside Any"
 }
 `,
-	}, {
-		desc: "Any with invalid UTF-8",
-		mo: prototext.MarshalOptions{
-			Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb3.Nested{})),
-		},
-		input: func() proto.Message {
-			m := &pb3.Nested{
-				SString: "abcd",
-			}
-			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
-			if err != nil {
-				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
-			}
-			return &anypb.Any{
-				TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
-				Value:   bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
-			}
-		}(),
-		want: `[pb3.Nested]: {
-  s_string: "abc\xff"
-}
-`,
-		wantErr: true,
 	}, {
 		desc: "Any with invalid value",
 		mo: prototext.MarshalOptions{

+ 8 - 12
internal/cmd/generate-types/proto.go

@@ -261,9 +261,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp wire.Type, fd protorefl
 		}
 		{{if (eq .Name "String") -}}
 		if fd.Syntax() == protoreflect.Proto3 && !utf8.Valid(v) {
-			var nerr errors.NonFatal
-			nerr.AppendInvalidUTF8(string(fd.FullName()))
-			return protoreflect.ValueOf(string(v)), n, nerr.E
+			return protoreflect.Value{}, 0, errors.InvalidUTF8(string(fd.FullName()))
 		}
 		{{end -}}
 		return protoreflect.ValueOf({{.ToValue}}), n, nil
@@ -274,7 +272,6 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp wire.Type, fd protorefl
 }
 
 func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protoreflect.List, fd protoreflect.FieldDescriptor) (n int, err error) {
-	var nerr errors.NonFatal
 	switch fd.Kind() {
 	{{- range .}}
 	case {{.Expr}}:
@@ -308,19 +305,19 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 		}
 		{{if (eq .Name "String") -}}
 		if fd.Syntax() == protoreflect.Proto3 && !utf8.Valid(v) {
-			nerr.AppendInvalidUTF8(string(fd.FullName()))
+			return 0, errors.InvalidUTF8(string(fd.FullName()))
 		}
 		{{end -}}
 		{{if or (eq .Name "Message") (eq .Name "Group") -}}
 		m := list.NewMessage()
-		if err := o.unmarshalMessage(v, m); !nerr.Merge(err) {
+		if err := o.unmarshalMessage(v, m); err != nil {
 			return 0, err
 		}
 		list.Append(protoreflect.ValueOf(m))
 		{{- else -}}
 		list.Append(protoreflect.ValueOf({{.ToValue}}))
 		{{- end}}
-		return n, nerr.E
+		return n, nil
 	{{- end}}
 	default:
 		return 0, errUnknown
@@ -340,13 +337,12 @@ var wireTypes = map[protoreflect.Kind]wire.Type{
 }
 
 func (o MarshalOptions) marshalSingular(b []byte, fd protoreflect.FieldDescriptor, v protoreflect.Value) ([]byte, error) {
-	var nerr errors.NonFatal
 	switch fd.Kind() {
 	{{- range .}}
 	case {{.Expr}}:
 		{{- if (eq .Name "String") }}
 		if fd.Syntax() == protoreflect.Proto3 && !utf8.ValidString(v.String()) {
-			nerr.AppendInvalidUTF8(string(fd.FullName()))
+			return b, errors.InvalidUTF8(string(fd.FullName()))
 		}
 		{{end -}}
 		{{- if (eq .Name "Message") -}}
@@ -354,14 +350,14 @@ func (o MarshalOptions) marshalSingular(b []byte, fd protoreflect.FieldDescripto
 		var err error
 		b, pos = appendSpeculativeLength(b)
 		b, err = o.marshalMessage(b, v.Message())
-		if !nerr.Merge(err) {
+		if err != nil {
 			return b, err
 		}
 		b = finishSpeculativeLength(b, pos)
 		{{- else if (eq .Name "Group") -}}
 		var err error
 		b, err = o.marshalMessage(b, v.Message())
-		if !nerr.Merge(err) {
+		if err != nil {
 			return b, err
 		}
 		b = wire.AppendVarint(b, wire.EncodeTag(fd.Number(), wire.EndGroupType))
@@ -372,7 +368,7 @@ func (o MarshalOptions) marshalSingular(b []byte, fd protoreflect.FieldDescripto
 	default:
 		return b, errors.New("invalid kind %v", fd.Kind())
 	}
-	return b, nerr.E
+	return b, nil
 }
 `))
 

+ 4 - 6
internal/encoding/json/decode.go

@@ -69,9 +69,8 @@ func (d *Decoder) Read() (Value, error) {
 		return d.value, d.err
 	}
 
-	var nerr errors.NonFatal
 	value, err := d.parseNext()
-	if !nerr.Merge(err) {
+	if err != nil {
 		return Value{}, err
 	}
 	n := value.size
@@ -145,7 +144,7 @@ func (d *Decoder) Read() (Value, error) {
 	if d.value.typ == comma {
 		return d.Read()
 	}
-	return value, nerr.E
+	return value, nil
 }
 
 // Any sequence that looks like a non-delimiter (for error reporting).
@@ -193,12 +192,11 @@ func (d *Decoder) parseNext() (value Value, err error) {
 		return d.newValue(Number, in, n), nil
 
 	case '"':
-		var nerr errors.NonFatal
 		s, n, err := d.parseString(in)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return Value{}, err
 		}
-		return d.newStringValue(in, n, s), nerr.E
+		return d.newStringValue(in, n, s), nil
 
 	case '{':
 		return d.newValue(StartObject, in, 1), nil

+ 1 - 4
internal/encoding/json/decode_test.go

@@ -121,10 +121,7 @@ func TestDecoder(t *testing.T) {
 		{
 			// Invalid UTF-8 error is returned in ReadString instead of Read.
 			input: "\"\xff\"",
-			want: []R{
-				{T: json.String, E: `invalid UTF-8 detected`, V: string("\xff")},
-				{T: json.EOF},
-			},
+			want:  []R{{E: `syntax error (line 1:1): invalid UTF-8 in string`}},
 		},
 		{
 			input: `"` + string(utf8.RuneError) + `"`,

+ 0 - 13
internal/encoding/json/encode_test.go

@@ -349,19 +349,6 @@ func TestEncoder(t *testing.T) {
 		]
 	]
 }`,
-		},
-		{
-			desc: "string contains rune error",
-			write: func(e *json.Encoder) {
-				// WriteString returns non-fatal error for invalid UTF sequence, but
-				// should still output the written value. See TestWriteStringError
-				// below that checks for this.
-				e.StartObject()
-				e.WriteName("invalid rune")
-				e.WriteString("abc\xff")
-				e.EndObject()
-			},
-			wantOut: "{\"invalid rune\":\"abc\xff\"}",
 		}}
 
 	for _, tc := range tests {

+ 4 - 8
internal/encoding/json/string.go

@@ -16,15 +16,13 @@ import (
 )
 
 func appendString(out []byte, in string) ([]byte, error) {
-	var nerr errors.NonFatal
 	out = append(out, '"')
 	i := indexNeedEscapeInString(in)
 	in, out = in[i:], append(out, in[:i]...)
 	for len(in) > 0 {
 		switch r, n := utf8.DecodeRuneInString(in); {
 		case r == utf8.RuneError && n == 1:
-			nerr.AppendInvalidUTF8("")
-			in, out = in[1:], append(out, in[0]) // preserve invalid byte
+			return out, errors.InvalidUTF8("")
 		case r < ' ' || r == '"' || r == '\\':
 			out = append(out, '\\')
 			switch r {
@@ -52,11 +50,10 @@ func appendString(out []byte, in string) ([]byte, error) {
 		}
 	}
 	out = append(out, '"')
-	return out, nerr.E
+	return out, nil
 }
 
 func (d *Decoder) parseString(in []byte) (string, int, error) {
-	var nerr errors.NonFatal
 	in0 := in
 	if len(in) == 0 {
 		return "", 0, io.ErrUnexpectedEOF
@@ -70,14 +67,13 @@ func (d *Decoder) parseString(in []byte) (string, int, error) {
 	for len(in) > 0 {
 		switch r, n := utf8.DecodeRune(in); {
 		case r == utf8.RuneError && n == 1:
-			nerr.AppendInvalidUTF8("")
-			in, out = in[1:], append(out, in[0]) // preserve invalid byte
+			return "", 0, d.newSyntaxError("invalid UTF-8 in string")
 		case r < ' ':
 			return "", 0, d.newSyntaxError("invalid character %q in string", r)
 		case r == '"':
 			in = in[1:]
 			n := len(in0) - len(in)
-			return string(out), n, nerr.E
+			return string(out), n, nil
 		case r == '\\':
 			if len(in) < 2 {
 				return "", 0, io.ErrUnexpectedEOF

+ 7 - 8
internal/encoding/text/decode.go

@@ -26,7 +26,7 @@ func Unmarshal(b []byte) (Value, error) {
 	p := decoder{in: b}
 	p.consume(0) // trim leading spaces or comments
 	v, err := p.unmarshalMessage(false)
-	if !p.nerr.Merge(err) {
+	if err != nil {
 		if e, ok := err.(syntaxError); ok {
 			b = b[:len(b)-len(p.in)] // consumed input
 			line := bytes.Count(b, []byte("\n")) + 1
@@ -41,12 +41,11 @@ func Unmarshal(b []byte) (Value, error) {
 	if len(p.in) > 0 {
 		return Value{}, errors.New("%d bytes of unconsumed input", len(p.in))
 	}
-	return v, p.nerr.E
+	return v, nil
 }
 
 type decoder struct {
-	nerr errors.NonFatal
-	in   []byte
+	in []byte
 }
 
 func (p *decoder) unmarshalList() (Value, error) {
@@ -58,7 +57,7 @@ func (p *decoder) unmarshalList() (Value, error) {
 	if len(p.in) > 0 && p.in[0] != ']' {
 		for len(p.in) > 0 {
 			v, err := p.unmarshalValue()
-			if !p.nerr.Merge(err) {
+			if err != nil {
 				return Value{}, err
 			}
 			elems = append(elems, v)
@@ -91,14 +90,14 @@ func (p *decoder) unmarshalMessage(checkDelims bool) (Value, error) {
 			break
 		}
 		k, err := p.unmarshalKey()
-		if !p.nerr.Merge(err) {
+		if err != nil {
 			return Value{}, err
 		}
 		if !p.tryConsumeChar(':') && len(p.in) > 0 && p.in[0] != '{' && p.in[0] != '<' {
 			return Value{}, newSyntaxError("expected ':' after message key")
 		}
 		v, err := p.unmarshalValue()
-		if !p.nerr.Merge(err) {
+		if err != nil {
 			return Value{}, err
 		}
 		if p.tryConsumeChar(';') || p.tryConsumeChar(',') {
@@ -132,7 +131,7 @@ func (p *decoder) unmarshalKey() (v Value, err error) {
 			// This is specific to Go and contrary to the C++ implementation,
 			// which does not support strings for the Any type URL.
 			v, err = p.unmarshalString()
-			if !p.nerr.Merge(err) {
+			if err != nil {
 				return Value{}, err
 			}
 		} else if n := matchWithDelim(urlRegexp, p.in); n > 0 {

+ 7 - 8
internal/encoding/text/encode.go

@@ -45,18 +45,17 @@ func Marshal(v Value, indent string, delims [2]byte, outputASCII bool) ([]byte,
 	p.outputASCII = outputASCII
 
 	err := p.marshalMessage(v, false)
-	if !p.nerr.Merge(err) {
+	if err != nil {
 		return nil, err
 	}
 	if len(indent) > 0 {
-		return append(bytes.TrimRight(p.out, "\n"), '\n'), p.nerr.E
+		return append(bytes.TrimRight(p.out, "\n"), '\n'), nil
 	}
-	return p.out, p.nerr.E
+	return p.out, nil
 }
 
 type encoder struct {
-	nerr errors.NonFatal
-	out  []byte
+	out []byte
 
 	indent      string
 	indents     []byte
@@ -77,7 +76,7 @@ func (p *encoder) marshalList(v Value) error {
 	}
 	for i, elem := range elems {
 		p.out = append(p.out, p.indents...)
-		if err := p.marshalValue(elem); !p.nerr.Merge(err) {
+		if err := p.marshalValue(elem); err != nil {
 			return err
 		}
 		if i < len(elems)-1 {
@@ -107,7 +106,7 @@ func (p *encoder) marshalMessage(v Value, emitDelims bool) error {
 	}
 	for i, item := range items {
 		p.out = append(p.out, p.indents...)
-		if err := p.marshalKey(item[0]); !p.nerr.Merge(err) {
+		if err := p.marshalKey(item[0]); err != nil {
 			return err
 		}
 		p.out = append(p.out, ':')
@@ -120,7 +119,7 @@ func (p *encoder) marshalMessage(v Value, emitDelims bool) error {
 			p.out = append(p.out, ' ')
 		}
 
-		if err := p.marshalValue(item[1]); !p.nerr.Merge(err) {
+		if err := p.marshalValue(item[1]); err != nil {
 			return err
 		}
 		if i < len(items)-1 && len(p.indent) == 0 {

+ 3 - 5
internal/encoding/text/string.go

@@ -86,7 +86,6 @@ func (p *decoder) unmarshalString() (Value, error) {
 	return v, err
 }
 func consumeString(in []byte) (Value, int, error) {
-	var nerr errors.NonFatal
 	in0 := in
 	if len(in) == 0 {
 		return Value{}, 0, io.ErrUnexpectedEOF
@@ -101,15 +100,14 @@ func consumeString(in []byte) (Value, int, error) {
 	for len(in) > 0 {
 		switch r, n := utf8.DecodeRune(in); {
 		case r == utf8.RuneError && n == 1:
-			nerr.AppendInvalidUTF8("")
-			in, out = in[1:], append(out, in[0]) // preserve invalid byte
+			return Value{}, 0, newSyntaxError("invalid UTF-8 detected")
 		case r == 0 || r == '\n':
 			return Value{}, 0, newSyntaxError("invalid character %q in string", r)
 		case r == rune(quote):
 			in = in[1:]
 			n := len(in0) - len(in)
 			v := rawValueOf(string(out), in0[:n:n])
-			return v, n, nerr.E
+			return v, n, nil
 		case r == '\\':
 			if len(in) < 2 {
 				return Value{}, 0, io.ErrUnexpectedEOF
@@ -208,7 +206,7 @@ func (p *decoder) unmarshalStrings() (Value, error) {
 	var ss []string
 	for len(p.in) > 0 && (p.in[0] == '"' || p.in[0] == '\'') {
 		v, err := p.unmarshalString()
-		if !p.nerr.Merge(err) {
+		if err != nil {
 			return Value{}, err
 		}
 		ss = append(ss, v.String())

+ 8 - 20
internal/encoding/text/text_test.go

@@ -354,32 +354,20 @@ func Test(t *testing.T) {
 		wantOut:      `str:"\x01\x02\x03\x04\x05\x06\x07\x08\t\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_` + "`abcdefghijklmnopqrstuvwxyz{|}~\x7f\"",
 		wantOutASCII: `str:"\x01\x02\x03\x04\x05\x06\x07\x08\t\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_` + "`abcdefghijklmnopqrstuvwxyz{|}~\x7f\"",
 	}, {
-		in:           "str: '\xde\xad\xbe\xef'",
-		wantVal:      V(Msg{{ID("str"), V("\xde\xad\xbe\xef")}}),
-		wantOut:      "str:\"\u07ad\\xbe\\xef\"",
-		wantOutASCII: `str:"\u07ad\xbe\xef"`,
-		wantErr:      "invalid UTF-8 detected",
+		in:      "str: '\xde\xad\xbe\xef'",
+		wantErr: "invalid UTF-8 detected",
 	}, {
 		// Valid UTF-8 wire encoding, but sub-optimal encoding.
-		in:           "str: '\xc0\x80'",
-		wantVal:      V(Msg{{ID("str"), V("\xc0\x80")}}),
-		wantOut:      `str:"\xc0\x80"`,
-		wantOutASCII: `str:"\xc0\x80"`,
-		wantErr:      "invalid UTF-8 detected",
+		in:      "str: '\xc0\x80'",
+		wantErr: "invalid UTF-8 detected",
 	}, {
 		// Valid UTF-8 wire encoding, but invalid rune (surrogate pair).
-		in:           "str: '\xed\xa0\x80'",
-		wantVal:      V(Msg{{ID("str"), V("\xed\xa0\x80")}}),
-		wantOut:      `str:"\xed\xa0\x80"`,
-		wantOutASCII: `str:"\xed\xa0\x80"`,
-		wantErr:      "invalid UTF-8 detected",
+		in:      "str: '\xed\xa0\x80'",
+		wantErr: "invalid UTF-8 detected",
 	}, {
 		// Valid UTF-8 wire encoding, but invalid rune (above max rune).
-		in:           "str: '\xf7\xbf\xbf\xbf'",
-		wantVal:      V(Msg{{ID("str"), V("\xf7\xbf\xbf\xbf")}}),
-		wantOut:      `str:"\xf7\xbf\xbf\xbf"`,
-		wantOutASCII: `str:"\xf7\xbf\xbf\xbf"`,
-		wantErr:      "invalid UTF-8 detected",
+		in:      "str: '\xf7\xbf\xbf\xbf'",
+		wantErr: "invalid UTF-8 detected",
 	}, {
 		// Valid UTF-8 wire encoding of the RuneError rune.
 		in:           "str: '\xef\xbf\xbd'",

+ 1 - 1
internal/encoding/text/value.go

@@ -327,7 +327,7 @@ func (v Value) Raw() []byte {
 		return v.raw
 	}
 	p := encoder{}
-	if err := p.marshalValue(v); !p.nerr.Merge(err) {
+	if err := p.marshalValue(v); err != nil {
 		return []byte("<invalid>")
 	}
 	return p.out

+ 8 - 103
internal/errors/errors.go

@@ -7,111 +7,8 @@ package errors
 
 import (
 	"fmt"
-	"sort"
-	"strings"
 )
 
-// TODO: This package currently only provides functionality for constructing
-// non-fatal errors. However, it does not currently provide functionality
-// to test for a specific kind of non-fatal error, which is necessary
-// for the end user.
-//
-// When that functionality is added, we need to think carefully about whether
-// a user only cares that some kind of non-fatal error was present or whether
-// all of the errors are of the same kind of non-fatal error.
-
-// NonFatalErrors is a list of non-fatal errors where each error
-// must either be a RequiredNotSet error or InvalidUTF8 error.
-// The list must not be empty.
-type NonFatalErrors []error
-
-func (es NonFatalErrors) Error() string {
-	ms := map[string]struct{}{}
-	for _, e := range es {
-		ms[e.Error()] = struct{}{}
-	}
-	var ss []string
-	for s := range ms {
-		ss = append(ss, s)
-	}
-	sort.Strings(ss)
-	return "proto: " + strings.Join(ss, "; ")
-}
-
-// NonFatal contains non-fatal errors, which are errors that permit execution
-// to continue, but should return with a non-nil error. As such, NonFatal is
-// a data structure useful for swallowing non-fatal errors, but being able to
-// reproduce them at the end of the function.
-// An error is non-fatal if it is collection of non-fatal errors, or is
-// an individual error where IsRequiredNotSet or IsInvalidUTF8 reports true.
-//
-// Typical usage pattern:
-//	var nerr errors.NonFatal
-//	...
-//	if err := MyFunction(); !nerr.Merge(err) {
-//		return nil, err // immediately return if err is fatal
-//	}
-//	...
-//	return out, nerr.E
-type NonFatal struct{ E error }
-
-// Merge merges err into nf and reports whether it was successful.
-// Otherwise it returns false for any fatal non-nil errors.
-func (nf *NonFatal) Merge(err error) (ok bool) {
-	if err == nil {
-		return true // not an error
-	}
-	if es, ok := err.(NonFatalErrors); ok {
-		nf.append(es...)
-		return true // merged a list of non-fatal errors
-	}
-	if e, ok := err.(interface{ RequiredNotSet() bool }); ok && e.RequiredNotSet() {
-		nf.append(err)
-		return true // non-fatal RequiredNotSet error
-	}
-	if e, ok := err.(interface{ InvalidUTF8() bool }); ok && e.InvalidUTF8() {
-		nf.append(err)
-		return true // non-fatal InvalidUTF8 error
-	}
-	return false // fatal error
-}
-
-// AppendRequiredNotSet appends a RequiredNotSet error.
-func (nf *NonFatal) AppendRequiredNotSet(field string) {
-	nf.append(requiredNotSetError(field))
-}
-
-// AppendInvalidUTF8 appends an InvalidUTF8 error.
-func (nf *NonFatal) AppendInvalidUTF8(field string) {
-	nf.append(invalidUTF8Error(field))
-}
-
-func (nf *NonFatal) append(errs ...error) {
-	es, _ := nf.E.(NonFatalErrors)
-	es = append(es, errs...)
-	nf.E = es
-}
-
-type requiredNotSetError string
-
-func (e requiredNotSetError) Error() string {
-	if e == "" {
-		return "required field not set"
-	}
-	return string("required field " + e + " not set")
-}
-func (requiredNotSetError) RequiredNotSet() bool { return true }
-
-type invalidUTF8Error string
-
-func (e invalidUTF8Error) Error() string {
-	if e == "" {
-		return "invalid UTF-8 detected"
-	}
-	return string("field " + e + " contains invalid UTF-8")
-}
-func (invalidUTF8Error) InvalidUTF8() bool { return true }
-
 // New formats a string according to the format specifier and arguments and
 // returns an error that has a "proto" prefix.
 func New(f string, x ...interface{}) error {
@@ -126,3 +23,11 @@ func New(f string, x ...interface{}) error {
 type prefixError struct{ s string }
 
 func (e *prefixError) Error() string { return "proto: " + e.s }
+
+func InvalidUTF8(name string) error {
+	return New("field %v contains invalid UTF-8", name)
+}
+
+func RequiredNotSet(name string) error {
+	return New("required field %v not set", name)
+}

+ 0 - 84
internal/errors/errors_test.go

@@ -5,94 +5,10 @@
 package errors
 
 import (
-	"errors"
-	"reflect"
 	"strings"
 	"testing"
 )
 
-func TestNonFatal(t *testing.T) {
-	type (
-		method = interface{} // merge | appendRequiredNotSet | appendInvalidUTF8
-		merge  struct {
-			inErr  error
-			wantOk bool
-		}
-		appendRequiredNotSet struct{ inField string }
-		appendInvalidUTF8    struct{ inField string }
-	)
-
-	tests := []struct {
-		label   string
-		methods []method
-		wantErr error
-	}{{
-		label: "IgnoreNil",
-		methods: []method{
-			merge{inErr: nil, wantOk: true},
-		},
-	}, {
-		label: "IgnoreFatal",
-		methods: []method{
-			merge{inErr: errors.New("fatal error")},
-		},
-	}, {
-		label: "MergeNonFatal",
-		methods: []method{
-			appendRequiredNotSet{"foo"},
-			merge{inErr: customRequiredNotSetError{}, wantOk: true},
-			appendInvalidUTF8{"bar"},
-			merge{inErr: customInvalidUTF8Error{}, wantOk: true},
-			merge{inErr: NonFatalErrors{
-				requiredNotSetError("fizz"),
-				invalidUTF8Error("buzz"),
-			}, wantOk: true},
-			merge{inErr: errors.New("fatal error")}, // not stored
-		},
-		wantErr: NonFatalErrors{
-			requiredNotSetError("foo"),
-			customRequiredNotSetError{},
-			invalidUTF8Error("bar"),
-			customInvalidUTF8Error{},
-			requiredNotSetError("fizz"),
-			invalidUTF8Error("buzz"),
-		},
-	}}
-
-	for _, tt := range tests {
-		t.Run(tt.label, func(t *testing.T) {
-			var nerr NonFatal
-			for _, m := range tt.methods {
-				switch m := m.(type) {
-				case merge:
-					if gotOk := nerr.Merge(m.inErr); gotOk != m.wantOk {
-						t.Errorf("Merge() = %v, want %v", gotOk, m.wantOk)
-					}
-				case appendRequiredNotSet:
-					nerr.AppendRequiredNotSet(m.inField)
-				case appendInvalidUTF8:
-					nerr.AppendInvalidUTF8(m.inField)
-				default:
-					t.Fatalf("invalid method: %T", m)
-				}
-			}
-			if !reflect.DeepEqual(nerr.E, tt.wantErr) {
-				t.Errorf("NonFatal.E = %v, want %v", nerr.E, tt.wantErr)
-			}
-		})
-	}
-}
-
-type customInvalidUTF8Error struct{}
-
-func (customInvalidUTF8Error) Error() string     { return "invalid UTF-8 detected" }
-func (customInvalidUTF8Error) InvalidUTF8() bool { return true }
-
-type customRequiredNotSetError struct{}
-
-func (customRequiredNotSetError) Error() string        { return "required field not set" }
-func (customRequiredNotSetError) RequiredNotSet() bool { return true }
-
 func TestNewPrefix(t *testing.T) {
 	e1 := New("abc")
 	got := e1.Error()

+ 5 - 8
internal/impl/encode.go

@@ -8,7 +8,6 @@ import (
 	"sort"
 	"sync/atomic"
 
-	"google.golang.org/protobuf/internal/errors"
 	proto "google.golang.org/protobuf/proto"
 	pref "google.golang.org/protobuf/reflect/protoreflect"
 	piface "google.golang.org/protobuf/runtime/protoiface"
@@ -100,13 +99,12 @@ func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOpt
 		return b, nil
 	}
 	var err error
-	var nerr errors.NonFatal
 	// The old marshaler encodes extensions at beginning.
 	if mi.extensionOffset.IsValid() {
 		e := p.Apply(mi.extensionOffset).Extensions()
 		// TODO: Special handling for MessageSet?
 		b, err = mi.appendExtensions(b, e, opts)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return b, err
 		}
 	}
@@ -119,7 +117,7 @@ func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOpt
 			continue
 		}
 		b, err = f.funcs.marshal(b, fptr, f.wiretag, opts)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return b, err
 		}
 	}
@@ -127,7 +125,7 @@ func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOpt
 		u := *p.Apply(mi.unknownOffset).Bytes()
 		b = append(b, u...)
 	}
-	return b, nerr.E
+	return b, nil
 }
 
 func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marshalOptions) (n int) {
@@ -169,15 +167,14 @@ func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField,
 		}
 		sort.Ints(keys)
 		var err error
-		var nerr errors.NonFatal
 		for _, k := range keys {
 			x := (*ext)[int32(k)]
 			xi := mi.extensionFieldInfo(x.GetType())
 			b, err = xi.funcs.marshal(b, x.GetValue(), xi.wiretag, opts)
-			if !nerr.Merge(err) {
+			if err != nil {
 				return b, err
 			}
 		}
-		return b, nerr.E
+		return b, nil
 	}
 }

+ 8 - 13
internal/impl/encode_field.go

@@ -10,7 +10,6 @@ import (
 	"unicode/utf8"
 
 	"google.golang.org/protobuf/internal/encoding/wire"
-	"google.golang.org/protobuf/internal/errors"
 	"google.golang.org/protobuf/proto"
 	pref "google.golang.org/protobuf/reflect/protoreflect"
 )
@@ -221,18 +220,17 @@ func sizeMessageSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalO
 
 func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
 	s := p.PointerSlice()
-	var nerr errors.NonFatal
 	var err error
 	for _, v := range s {
 		b = wire.AppendVarint(b, wiretag)
 		siz := mi.sizePointer(v, opts)
 		b = wire.AppendVarint(b, uint64(siz))
 		b, err = mi.marshalAppendPointer(b, v, opts)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return b, err
 		}
 	}
-	return b, nerr.E
+	return b, nil
 }
 
 func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
@@ -247,7 +245,6 @@ func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOpti
 
 func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
 	s := p.PointerSlice()
-	var nerr errors.NonFatal
 	var err error
 	for _, v := range s {
 		m := Export{}.MessageOf(v.AsValueOf(goType.Elem()).Interface()).Interface()
@@ -255,11 +252,11 @@ func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type
 		siz := proto.Size(m)
 		b = wire.AppendVarint(b, uint64(siz))
 		b, err = opts.Options().MarshalAppend(b, m)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return b, err
 		}
 	}
-	return b, nerr.E
+	return b, nil
 }
 
 // Slices of messages
@@ -312,18 +309,17 @@ func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalO
 
 func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
 	s := p.PointerSlice()
-	var nerr errors.NonFatal
 	var err error
 	for _, v := range s {
 		m := Export{}.MessageOf(v.AsValueOf(messageType.Elem()).Interface()).Interface()
 		b = wire.AppendVarint(b, wiretag) // start group
 		b, err = opts.Options().MarshalAppend(b, m)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return b, err
 		}
 		b = wire.AppendVarint(b, wiretag+1) // end group
 	}
-	return b, nerr.E
+	return b, nil
 }
 
 func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
@@ -337,17 +333,16 @@ func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOpt
 
 func appendGroupSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
 	s := p.PointerSlice()
-	var nerr errors.NonFatal
 	var err error
 	for _, v := range s {
 		b = wire.AppendVarint(b, wiretag) // start group
 		b, err = mi.marshalAppendPointer(b, v, opts)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return b, err
 		}
 		b = wire.AppendVarint(b, wiretag+1) // end group
 	}
-	return b, nerr.E
+	return b, nil
 }
 
 func sizeGroupSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {

+ 7 - 10
internal/impl/encode_map.go

@@ -10,7 +10,6 @@ import (
 	"sort"
 
 	"google.golang.org/protobuf/internal/encoding/wire"
-	"google.golang.org/protobuf/internal/errors"
 	"google.golang.org/protobuf/proto"
 	pref "google.golang.org/protobuf/reflect/protoreflect"
 )
@@ -59,7 +58,6 @@ func sizeMap(p pointer, tagsize int, goType reflect.Type, keyFuncs, valFuncs ifa
 
 func appendMap(b []byte, p pointer, wiretag, keyWiretag, valWiretag uint64, goType reflect.Type, keyFuncs, valFuncs ifaceCoderFuncs, opts marshalOptions) ([]byte, error) {
 	m := p.AsValueOf(goType).Elem()
-	var nerr errors.NonFatal
 	var err error
 
 	if m.Len() == 0 {
@@ -71,21 +69,21 @@ func appendMap(b []byte, p pointer, wiretag, keyWiretag, valWiretag uint64, goTy
 		sort.Sort(mapKeys(keys))
 		for _, k := range keys {
 			b, err = appendMapElement(b, k, m.MapIndex(k), wiretag, keyWiretag, valWiretag, keyFuncs, valFuncs, opts)
-			if !nerr.Merge(err) {
+			if err != nil {
 				return b, err
 			}
 		}
-		return b, nerr.E
+		return b, nil
 	}
 
 	iter := mapRange(m)
 	for iter.Next() {
 		b, err = appendMapElement(b, iter.Key(), iter.Value(), wiretag, keyWiretag, valWiretag, keyFuncs, valFuncs, opts)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return b, err
 		}
 	}
-	return b, nerr.E
+	return b, nil
 }
 
 func appendMapElement(b []byte, key, value reflect.Value, wiretag, keyWiretag, valWiretag uint64, keyFuncs, valFuncs ifaceCoderFuncs, opts marshalOptions) ([]byte, error) {
@@ -94,16 +92,15 @@ func appendMapElement(b []byte, key, value reflect.Value, wiretag, keyWiretag, v
 	b = wire.AppendVarint(b, wiretag)
 	size := keyFuncs.size(ki, mapKeyTagSize, opts) + valFuncs.size(vi, mapValTagSize, opts)
 	b = wire.AppendVarint(b, uint64(size))
-	var nerr errors.NonFatal
 	b, err := keyFuncs.marshal(b, ki, keyWiretag, opts)
-	if !nerr.Merge(err) {
+	if err != nil {
 		return b, err
 	}
 	b, err = valFuncs.marshal(b, vi, valWiretag, opts)
-	if !nerr.Merge(err) {
+	if err != nil {
 		return b, err
 	}
-	return b, nerr.E
+	return b, nil
 }
 
 // mapKeys returns a sort.Interface to be used for sorting the map keys.

+ 13 - 19
proto/decode.go

@@ -53,14 +53,13 @@ func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error {
 	if err == errInternalNoFast {
 		err = o.unmarshalMessage(b, m.ProtoReflect())
 	}
-	var nerr errors.NonFatal
-	if !nerr.Merge(err) {
+	if err != nil {
 		return err
 	}
-	if !o.AllowPartial {
-		nerr.Merge(IsInitialized(m))
+	if o.AllowPartial {
+		return nil
 	}
-	return nerr.E
+	return IsInitialized(m)
 }
 
 func (o UnmarshalOptions) unmarshalMessageFast(b []byte, m Message) error {
@@ -74,7 +73,6 @@ func (o UnmarshalOptions) unmarshalMessageFast(b []byte, m Message) error {
 func (o UnmarshalOptions) unmarshalMessage(b []byte, m protoreflect.Message) error {
 	messageDesc := m.Descriptor()
 	fieldDescs := messageDesc.Fields()
-	var nerr errors.NonFatal
 	for len(b) > 0 {
 		// Parse the tag (field number and wire type).
 		num, wtyp, tagLen := wire.ConsumeTag(b)
@@ -109,18 +107,17 @@ func (o UnmarshalOptions) unmarshalMessage(b []byte, m protoreflect.Message) err
 				return wire.ParseError(valLen)
 			}
 			m.SetUnknown(append(m.GetUnknown(), b[:tagLen+valLen]...))
-		} else if !nerr.Merge(err) {
+		} else if err != nil {
 			return err
 		}
 		b = b[tagLen+valLen:]
 	}
-	return nerr.E
+	return nil
 }
 
 func (o UnmarshalOptions) unmarshalSingular(b []byte, wtyp wire.Type, m protoreflect.Message, fd protoreflect.FieldDescriptor) (n int, err error) {
-	var nerr errors.NonFatal
 	v, n, err := o.unmarshalScalar(b, wtyp, fd)
-	if !nerr.Merge(err) {
+	if err != nil {
 		return 0, err
 	}
 	switch fd.Kind() {
@@ -138,14 +135,14 @@ func (o UnmarshalOptions) unmarshalSingular(b []byte, wtyp wire.Type, m protoref
 			m.Set(fd, protoreflect.ValueOf(m2))
 		}
 		// Pass up errors (fatal and otherwise).
-		if err := o.unmarshalMessage(v.Bytes(), m2); !nerr.Merge(err) {
+		if err := o.unmarshalMessage(v.Bytes(), m2); err != nil {
 			return n, err
 		}
 	default:
 		// Non-message scalars replace the previous value.
 		m.Set(fd, v)
 	}
-	return n, nerr.E
+	return n, nil
 }
 
 func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp wire.Type, mapv protoreflect.Map, fd protoreflect.FieldDescriptor) (n int, err error) {
@@ -170,7 +167,6 @@ func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp wire.Type, mapv protorefle
 	}
 	// Map entries are represented as a two-element message with fields
 	// containing the key and value.
-	var nerr errors.NonFatal
 	for len(b) > 0 {
 		num, wtyp, n := wire.ConsumeTag(b)
 		if n < 0 {
@@ -181,21 +177,19 @@ func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp wire.Type, mapv protorefle
 		switch num {
 		case 1:
 			key, n, err = o.unmarshalScalar(b, wtyp, keyField)
-			if !nerr.Merge(err) {
+			if err != nil {
 				break
 			}
-			err = nil
 			haveKey = true
 		case 2:
 			var v protoreflect.Value
 			v, n, err = o.unmarshalScalar(b, wtyp, valField)
-			if !nerr.Merge(err) {
+			if err != nil {
 				break
 			}
-			err = nil
 			switch valField.Kind() {
 			case protoreflect.GroupKind, protoreflect.MessageKind:
-				if err := o.unmarshalMessage(v.Bytes(), val.Message()); !nerr.Merge(err) {
+				if err := o.unmarshalMessage(v.Bytes(), val.Message()); err != nil {
 					return 0, err
 				}
 			default:
@@ -225,7 +219,7 @@ func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp wire.Type, mapv protorefle
 		}
 	}
 	mapv.Set(key.MapKey(), val)
-	return n, nerr.E
+	return n, nil
 }
 
 // errUnknown is used internally to indicate fields which should be added

+ 22 - 25
proto/decode_gen.go

@@ -155,9 +155,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp wire.Type, fd protorefl
 			return val, 0, wire.ParseError(n)
 		}
 		if fd.Syntax() == protoreflect.Proto3 && !utf8.Valid(v) {
-			var nerr errors.NonFatal
-			nerr.AppendInvalidUTF8(string(fd.FullName()))
-			return protoreflect.ValueOf(string(v)), n, nerr.E
+			return protoreflect.Value{}, 0, errors.InvalidUTF8(string(fd.FullName()))
 		}
 		return protoreflect.ValueOf(string(v)), n, nil
 	case protoreflect.BytesKind:
@@ -193,7 +191,6 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp wire.Type, fd protorefl
 }
 
 func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protoreflect.List, fd protoreflect.FieldDescriptor) (n int, err error) {
-	var nerr errors.NonFatal
 	switch fd.Kind() {
 	case protoreflect.BoolKind:
 		if wtyp == wire.BytesType {
@@ -219,7 +216,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(wire.DecodeBool(v)))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.EnumKind:
 		if wtyp == wire.BytesType {
 			buf, n := wire.ConsumeBytes(b)
@@ -244,7 +241,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(protoreflect.EnumNumber(v)))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.Int32Kind:
 		if wtyp == wire.BytesType {
 			buf, n := wire.ConsumeBytes(b)
@@ -269,7 +266,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(int32(v)))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.Sint32Kind:
 		if wtyp == wire.BytesType {
 			buf, n := wire.ConsumeBytes(b)
@@ -294,7 +291,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(int32(wire.DecodeZigZag(v & math.MaxUint32))))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.Uint32Kind:
 		if wtyp == wire.BytesType {
 			buf, n := wire.ConsumeBytes(b)
@@ -319,7 +316,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(uint32(v)))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.Int64Kind:
 		if wtyp == wire.BytesType {
 			buf, n := wire.ConsumeBytes(b)
@@ -344,7 +341,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(int64(v)))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.Sint64Kind:
 		if wtyp == wire.BytesType {
 			buf, n := wire.ConsumeBytes(b)
@@ -369,7 +366,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(wire.DecodeZigZag(v)))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.Uint64Kind:
 		if wtyp == wire.BytesType {
 			buf, n := wire.ConsumeBytes(b)
@@ -394,7 +391,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(v))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.Sfixed32Kind:
 		if wtyp == wire.BytesType {
 			buf, n := wire.ConsumeBytes(b)
@@ -419,7 +416,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(int32(v)))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.Fixed32Kind:
 		if wtyp == wire.BytesType {
 			buf, n := wire.ConsumeBytes(b)
@@ -444,7 +441,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(uint32(v)))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.FloatKind:
 		if wtyp == wire.BytesType {
 			buf, n := wire.ConsumeBytes(b)
@@ -469,7 +466,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(math.Float32frombits(uint32(v))))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.Sfixed64Kind:
 		if wtyp == wire.BytesType {
 			buf, n := wire.ConsumeBytes(b)
@@ -494,7 +491,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(int64(v)))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.Fixed64Kind:
 		if wtyp == wire.BytesType {
 			buf, n := wire.ConsumeBytes(b)
@@ -519,7 +516,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(v))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.DoubleKind:
 		if wtyp == wire.BytesType {
 			buf, n := wire.ConsumeBytes(b)
@@ -544,7 +541,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(math.Float64frombits(v)))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.StringKind:
 		if wtyp != wire.BytesType {
 			return 0, errUnknown
@@ -554,10 +551,10 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		if fd.Syntax() == protoreflect.Proto3 && !utf8.Valid(v) {
-			nerr.AppendInvalidUTF8(string(fd.FullName()))
+			return 0, errors.InvalidUTF8(string(fd.FullName()))
 		}
 		list.Append(protoreflect.ValueOf(string(v)))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.BytesKind:
 		if wtyp != wire.BytesType {
 			return 0, errUnknown
@@ -567,7 +564,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		list.Append(protoreflect.ValueOf(append(([]byte)(nil), v...)))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.MessageKind:
 		if wtyp != wire.BytesType {
 			return 0, errUnknown
@@ -577,11 +574,11 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		m := list.NewMessage()
-		if err := o.unmarshalMessage(v, m); !nerr.Merge(err) {
+		if err := o.unmarshalMessage(v, m); err != nil {
 			return 0, err
 		}
 		list.Append(protoreflect.ValueOf(m))
-		return n, nerr.E
+		return n, nil
 	case protoreflect.GroupKind:
 		if wtyp != wire.StartGroupType {
 			return 0, errUnknown
@@ -591,11 +588,11 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, list protorefl
 			return 0, wire.ParseError(n)
 		}
 		m := list.NewMessage()
-		if err := o.unmarshalMessage(v, m); !nerr.Merge(err) {
+		if err := o.unmarshalMessage(v, m); err != nil {
 			return 0, err
 		}
 		list.Append(protoreflect.ValueOf(m))
-		return n, nerr.E
+		return n, nil
 	default:
 		return 0, errUnknown
 	}

+ 1 - 19
proto/decode_test.go

@@ -12,7 +12,6 @@ import (
 	protoV1 "github.com/golang/protobuf/proto"
 	"google.golang.org/protobuf/encoding/prototext"
 	"google.golang.org/protobuf/internal/encoding/pack"
-	"google.golang.org/protobuf/internal/errors"
 	"google.golang.org/protobuf/internal/scalar"
 	"google.golang.org/protobuf/proto"
 	pref "google.golang.org/protobuf/reflect/protoreflect"
@@ -89,12 +88,9 @@ func TestDecodeInvalidUTF8(t *testing.T) {
 			t.Run(fmt.Sprintf("%s (%T)", test.desc, want), func(t *testing.T) {
 				got := reflect.New(reflect.TypeOf(want).Elem()).Interface().(proto.Message)
 				err := proto.Unmarshal(test.wire, got)
-				if !isErrInvalidUTF8(err) {
+				if err == nil {
 					t.Errorf("Unmarshal did not return expected error for invalid UTF8: %v\nMessage:\n%v", err, marshalText(want))
 				}
-				if !protoV1.Equal(got.(protoV1.Message), want.(protoV1.Message)) {
-					t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", marshalText(got), marshalText(want))
-				}
 			})
 		}
 	}
@@ -1362,17 +1358,3 @@ func marshalText(m proto.Message) string {
 	b, _ := prototext.Marshal(m)
 	return string(b)
 }
-
-func isErrInvalidUTF8(err error) bool {
-	nerr, ok := err.(errors.NonFatalErrors)
-	if !ok || len(nerr) == 0 {
-		return false
-	}
-	for _, err := range nerr {
-		if e, ok := err.(interface{ InvalidUTF8() bool }); ok && e.InvalidUTF8() {
-			continue
-		}
-		return false
-	}
-	return true
-}

+ 14 - 29
proto/encode.go

@@ -8,7 +8,6 @@ import (
 	"sort"
 
 	"google.golang.org/protobuf/internal/encoding/wire"
-	"google.golang.org/protobuf/internal/errors"
 	"google.golang.org/protobuf/internal/mapsort"
 	"google.golang.org/protobuf/internal/pragma"
 	"google.golang.org/protobuf/reflect/protoreflect"
@@ -92,14 +91,13 @@ func (o MarshalOptions) MarshalAppend(b []byte, m Message) ([]byte, error) {
 	if err == errInternalNoFast {
 		out, err = o.marshalMessage(b, m.ProtoReflect())
 	}
-	var nerr errors.NonFatal
-	if !nerr.Merge(err) {
-		return out, err
+	if err != nil {
+		return nil, err
 	}
-	if !allowPartial {
-		nerr.Merge(IsInitialized(m))
+	if allowPartial {
+		return out, nil
 	}
-	return out, nerr.E
+	return out, IsInitialized(m)
 }
 
 func (o MarshalOptions) marshalMessageFast(b []byte, m Message) ([]byte, error) {
@@ -129,20 +127,15 @@ func (o MarshalOptions) marshalMessage(b []byte, m protoreflect.Message) ([]byte
 	//
 	// When using deterministic serialization, we sort the known fields by field number.
 	var err error
-	var nerr errors.NonFatal
 	o.rangeFields(m, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
 		b, err = o.marshalField(b, fd, v)
-		if nerr.Merge(err) {
-			err = nil
-			return true
-		}
-		return false
+		return err == nil
 	})
 	if err != nil {
 		return b, err
 	}
 	b = append(b, m.GetUnknown()...)
-	return b, nerr.E
+	return b, nil
 }
 
 // rangeFields visits fields in field number order when deterministic
@@ -183,35 +176,32 @@ func (o MarshalOptions) marshalList(b []byte, fd protoreflect.FieldDescriptor, l
 	if fd.IsPacked() && list.Len() > 0 {
 		b = wire.AppendTag(b, fd.Number(), wire.BytesType)
 		b, pos := appendSpeculativeLength(b)
-		var nerr errors.NonFatal
 		for i, llen := 0, list.Len(); i < llen; i++ {
 			var err error
 			b, err = o.marshalSingular(b, fd, list.Get(i))
-			if !nerr.Merge(err) {
+			if err != nil {
 				return b, err
 			}
 		}
 		b = finishSpeculativeLength(b, pos)
-		return b, nerr.E
+		return b, nil
 	}
 
 	kind := fd.Kind()
-	var nerr errors.NonFatal
 	for i, llen := 0, list.Len(); i < llen; i++ {
 		var err error
 		b = wire.AppendTag(b, fd.Number(), wireTypes[kind])
 		b, err = o.marshalSingular(b, fd, list.Get(i))
-		if !nerr.Merge(err) {
+		if err != nil {
 			return b, err
 		}
 	}
-	return b, nerr.E
+	return b, nil
 }
 
 func (o MarshalOptions) marshalMap(b []byte, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) ([]byte, error) {
 	keyf := fd.MapKey()
 	valf := fd.MapValue()
-	var nerr errors.NonFatal
 	var err error
 	o.rangeMap(mapv, keyf.Kind(), func(key protoreflect.MapKey, value protoreflect.Value) bool {
 		b = wire.AppendTag(b, fd.Number(), wire.BytesType)
@@ -219,22 +209,17 @@ func (o MarshalOptions) marshalMap(b []byte, fd protoreflect.FieldDescriptor, ma
 		b, pos = appendSpeculativeLength(b)
 
 		b, err = o.marshalField(b, keyf, key.Value())
-		if !nerr.Merge(err) {
+		if err != nil {
 			return false
 		}
 		b, err = o.marshalField(b, valf, value)
-		if !nerr.Merge(err) {
+		if err != nil {
 			return false
 		}
-		err = nil
-
 		b = finishSpeculativeLength(b, pos)
 		return true
 	})
-	if err != nil {
-		return b, err
-	}
-	return b, nerr.E
+	return b, err
 }
 
 func (o MarshalOptions) rangeMap(mapv protoreflect.Map, kind protoreflect.Kind, f func(protoreflect.MapKey, protoreflect.Value) bool) {

+ 4 - 5
proto/encode_gen.go

@@ -37,7 +37,6 @@ var wireTypes = map[protoreflect.Kind]wire.Type{
 }
 
 func (o MarshalOptions) marshalSingular(b []byte, fd protoreflect.FieldDescriptor, v protoreflect.Value) ([]byte, error) {
-	var nerr errors.NonFatal
 	switch fd.Kind() {
 	case protoreflect.BoolKind:
 		b = wire.AppendVarint(b, wire.EncodeBool(v.Bool()))
@@ -69,7 +68,7 @@ func (o MarshalOptions) marshalSingular(b []byte, fd protoreflect.FieldDescripto
 		b = wire.AppendFixed64(b, math.Float64bits(v.Float()))
 	case protoreflect.StringKind:
 		if fd.Syntax() == protoreflect.Proto3 && !utf8.ValidString(v.String()) {
-			nerr.AppendInvalidUTF8(string(fd.FullName()))
+			return b, errors.InvalidUTF8(string(fd.FullName()))
 		}
 		b = wire.AppendBytes(b, []byte(v.String()))
 	case protoreflect.BytesKind:
@@ -79,19 +78,19 @@ func (o MarshalOptions) marshalSingular(b []byte, fd protoreflect.FieldDescripto
 		var err error
 		b, pos = appendSpeculativeLength(b)
 		b, err = o.marshalMessage(b, v.Message())
-		if !nerr.Merge(err) {
+		if err != nil {
 			return b, err
 		}
 		b = finishSpeculativeLength(b, pos)
 	case protoreflect.GroupKind:
 		var err error
 		b, err = o.marshalMessage(b, v.Message())
-		if !nerr.Merge(err) {
+		if err != nil {
 			return b, err
 		}
 		b = wire.AppendVarint(b, wire.EncodeTag(fd.Number(), wire.EndGroupType))
 	default:
 		return b, errors.New("invalid kind %v", fd.Kind())
 	}
-	return b, nerr.E
+	return b, nil
 }

+ 2 - 10
proto/encode_test.go

@@ -99,18 +99,10 @@ func TestEncodeInvalidUTF8(t *testing.T) {
 	for _, test := range invalidUTF8TestProtos {
 		for _, want := range test.decodeTo {
 			t.Run(fmt.Sprintf("%s (%T)", test.desc, want), func(t *testing.T) {
-				wire, err := proto.Marshal(want)
-				if !isErrInvalidUTF8(err) {
+				_, err := proto.Marshal(want)
+				if err == nil {
 					t.Errorf("Marshal did not return expected error for invalid UTF8: %v\nMessage:\n%v", err, marshalText(want))
 				}
-				got := want.ProtoReflect().New().Interface()
-				if err := proto.Unmarshal(wire, got); !isErrInvalidUTF8(err) {
-					t.Errorf("Unmarshal error: %v\nMessage:\n%v", err, marshalText(want))
-					return
-				}
-				if !proto.Equal(got, want) {
-					t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", marshalText(got), marshalText(want))
-				}
 			})
 		}
 	}

+ 1 - 3
proto/isinit.go

@@ -75,7 +75,5 @@ func newRequiredNotSetError(stack []interface{}) error {
 	for _, s := range stack {
 		fmt.Fprint(&buf, s)
 	}
-	var nerr errors.NonFatal
-	nerr.AppendRequiredNotSet(buf.String())
-	return nerr.E
+	return errors.RequiredNotSet(buf.String())
 }