internal/impl: fix Has behavior for floats

According to IEEE-754, equality on floats reports true for both +0 and -0.
However, this definition causes us to lose information. Instead, we want
a definition that checks for exact equality with +0.
Otherwise, we would lose the ability to serialize -0.

Change-Id: I36450c24258fc4f856bfd4bc4c53a90199b216b9
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/172970
Reviewed-by: Herbie Ong <herbie@google.com>
This commit is contained in:
Joe Tsai 2019-04-22 11:44:49 -07:00 committed by Joe Tsai
parent c90b6ada23
commit 060cdacd3b
2 changed files with 7 additions and 1 deletions

View File

@ -6,6 +6,7 @@ package impl
import (
"fmt"
"math"
"reflect"
"github.com/golang/protobuf/v2/internal/flags"
@ -197,7 +198,7 @@ func fieldInfoForScalar(fd pref.FieldDescriptor, fs reflect.StructField) fieldIn
case reflect.Uint32, reflect.Uint64:
return rv.Uint() != 0
case reflect.Float32, reflect.Float64:
return rv.Float() != 0
return rv.Float() != 0 || math.Signbit(rv.Float())
case reflect.String, reflect.Slice:
return rv.Len() > 0
default:

View File

@ -387,6 +387,11 @@ func TestScalarProto3(t *testing.T) {
},
clearFields{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22},
equalMessage{&ScalarProto3{}},
// Verify that -0 triggers proper Has behavior.
hasFields{6: false, 7: false},
setFields{6: V(float32(math.Copysign(0, -1))), 7: V(float64(math.Copysign(0, -1)))},
hasFields{6: true, 7: true},
})
// Test read-only operations on nil message.