Skip to content

Commit

Permalink
Print type name in unexported panic (#171)
Browse files Browse the repository at this point in the history
In the panic message when accessing an unexported field,
print the full name of the type for user convenience.
  • Loading branch information
dsnet committed Nov 5, 2019
1 parent 481baca commit 776445f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
17 changes: 17 additions & 0 deletions cmp/compare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"reflect"
"regexp"
"sort"
"strconv"
"strings"
"sync"
"testing"
Expand Down Expand Up @@ -119,6 +120,10 @@ func comparerTests() []test {
Xattrs map[string]string
}

type namedWithUnexported struct {
unexported string
}

makeTarHeaders := func(tf byte) (hs []tarHeader) {
for i := 0; i < 5; i++ {
hs = append(hs, tarHeader{
Expand Down Expand Up @@ -673,6 +678,18 @@ func comparerTests() []test {
}
`,
reason: "all zero map entries are ignored (even if missing)",
}, {
label: label,
x: namedWithUnexported{},
y: namedWithUnexported{},
wantPanic: strconv.Quote(reflect.TypeOf(namedWithUnexported{}).PkgPath()) + ".namedWithUnexported",
reason: "panic on named struct type with unexported field",
}, {
label: label,
x: struct{ a int }{},
y: struct{ a int }{},
wantPanic: strconv.Quote(reflect.TypeOf(namedWithUnexported{}).PkgPath()) + ".(struct { a int })",
reason: "panic on unnamed struct type with unexported field",
}}
}

Expand Down
14 changes: 13 additions & 1 deletion cmp/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,19 @@ 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 AllowUnexported or cmpopts.IgnoreUnexported"
panic(fmt.Sprintf("cannot handle unexported field: %#v\n%s", s.curPath, help))
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
} else {
// Unnamed type with unexported fields. Derive PkgPath from field.
var pkgPath string
for i := 0; i < t.NumField() && pkgPath == ""; i++ {
pkgPath = t.Field(i).PkgPath
}
name = fmt.Sprintf("%q.(%v)", pkgPath, t.String()) // e.g., "path/to/package".(struct { a int })
}
panic(fmt.Sprintf("cannot handle unexported field at %#v:\n\t%v\n%s", s.curPath, name, help))
}

panic("not reachable")
Expand Down

0 comments on commit 776445f

Please sign in to comment.