aboutsummaryrefslogtreecommitdiff
path: root/cmp
diff options
context:
space:
mode:
authorJoe Tsai <joetsai@digital-static.net>2020-08-18 12:37:11 -0700
committerGitHub <noreply@github.com>2020-08-18 12:37:11 -0700
commitd2fcc899bdc2d134b7c00e36137260db963e193c (patch)
treec8b2079fb7f32dab92d072a80cfb45688b9a0f94 /cmp
parentdb9de4321f4e5db7c6f996d170ebce7953f22f8e (diff)
downloadgo-cmp-d2fcc899bdc2d134b7c00e36137260db963e193c.tar.gz
Suggest use of cmpopts.EquateErrors (#234)
If cmp panics because it is trying to access an unexported field, specially suggest the use of cmpopts.EquateErrors if the parent type implements the error interface. Fixes #233
Diffstat (limited to 'cmp')
-rw-r--r--cmp/compare_test.go13
-rw-r--r--cmp/options.go5
2 files changed, 17 insertions, 1 deletions
diff --git a/cmp/compare_test.go b/cmp/compare_test.go
index ba39bde..bdcc06b 100644
--- a/cmp/compare_test.go
+++ b/cmp/compare_test.go
@@ -696,6 +696,19 @@ func comparerTests() []test {
},
wantEqual: true,
reason: "verify that exporter does not leak implementation details",
+ }, {
+ label: label + "/ErrorPanic",
+ x: io.EOF,
+ y: io.EOF,
+ wantPanic: "consider using cmpopts.EquateErrors",
+ reason: "suggest cmpopts.EquateErrors when accessing unexported fields of error types",
+ }, {
+ label: label + "/ErrorEqual",
+ x: io.EOF,
+ y: io.EOF,
+ opts: []cmp.Option{cmpopts.EquateErrors()},
+ wantEqual: true,
+ reason: "cmpopts.EquateErrors should equate these two errors as sentinel values",
}}
}
diff --git a/cmp/options.go b/cmp/options.go
index abbd2a6..4b0407a 100644
--- a/cmp/options.go
+++ b/cmp/options.go
@@ -225,11 +225,14 @@ func (validator) apply(s *state, vx, vy reflect.Value) {
// Unable to Interface implies unexported field without visibility access.
if !vx.CanInterface() || !vy.CanInterface() {
- const help = "consider using a custom Comparer; if you control the implementation of type, you can also consider using an Exporter, AllowUnexported, or cmpopts.IgnoreUnexported"
+ help := "consider using a custom Comparer; if you control the implementation of type, you can also consider using an Exporter, AllowUnexported, or cmpopts.IgnoreUnexported"
var name string
if t := s.curPath.Index(-2).Type(); t.Name() != "" {
// Named type with unexported fields.
name = fmt.Sprintf("%q.%v", t.PkgPath(), t.Name()) // e.g., "path/to/package".MyType
+ if _, ok := reflect.New(t).Interface().(error); ok {
+ help = "consider using cmpopts.EquateErrors to compare error values"
+ }
} else {
// Unnamed type with unexported fields. Derive PkgPath from field.
var pkgPath string