Make errors.stack comparable (#30)
Fixed #29
errors.New, etc values are not expected to be compared by value but
the change in errors#27 made them incomparable. Assert that various
kinds of errors have a functional equality operator, even if the
result of that equality is always false.
diff --git a/errors.go b/errors.go
index 9b057f6..4f128df 100644
--- a/errors.go
+++ b/errors.go
@@ -64,17 +64,17 @@
// stack represents a stack of programm counters.
type stack []uintptr
-func (s stack) Stack() []uintptr { return s }
+func (s *stack) Stack() []uintptr { return *s }
-func (s stack) Location() (string, int) {
- return location(s[0] - 1)
+func (s *stack) Location() (string, int) {
+ return location((*s)[0] - 1)
}
// New returns an error that formats as the given text.
func New(text string) error {
return struct {
error
- stack
+ *stack
}{
errors.New(text),
callers(),
@@ -95,7 +95,7 @@
func Errorf(format string, args ...interface{}) error {
return struct {
error
- stack
+ *stack
}{
fmt.Errorf(format, args...),
callers(),
@@ -120,10 +120,10 @@
return wrap(cause, fmt.Sprintf(format, args...), callers())
}
-func wrap(err error, msg string, st stack) error {
+func wrap(err error, msg string, st *stack) error {
return struct {
cause
- stack
+ *stack
}{
cause{
cause: err,
@@ -198,11 +198,12 @@
}
}
-func callers() stack {
+func callers() *stack {
const depth = 32
var pcs [depth]uintptr
n := runtime.Callers(3, pcs[:])
- return pcs[0:n]
+ var st stack = pcs[0:n]
+ return &st
}
// location returns the source file and line matching pc.
diff --git a/errors_test.go b/errors_test.go
index 7ffd7db..2795bb2 100644
--- a/errors_test.go
+++ b/errors_test.go
@@ -241,3 +241,24 @@
}
}
}
+
+// errors.New, etc values are not expected to be compared by value
+// but the change in errors#27 made them incomparable. Assert that
+// various kinds of errors have a functional equality operator, even
+// if the result of that equality is always false.
+func TestErrorEquality(t *testing.T) {
+ tests := []struct {
+ err1, err2 error
+ }{
+ {io.EOF, io.EOF},
+ {io.EOF, nil},
+ {io.EOF, errors.New("EOF")},
+ {io.EOF, New("EOF")},
+ {New("EOF"), New("EOF")},
+ {New("EOF"), Errorf("EOF")},
+ {New("EOF"), Wrap(io.EOF, "EOF")},
+ }
+ for _, tt := range tests {
+ _ = tt.err1 == tt.err2 // mustn't panic
+ }
+}