xerrors: fix Is panics if target is uncomparable

Analogous change to golang.org/cl/175260

Fixes golang/go#31841

Change-Id: I93bf093e8d5c13269fe7164a3a1b6956450998e5
Reviewed-on: https://go-review.googlesource.com/c/xerrors/+/174980
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/wrap.go b/wrap.go
index ebfe244..50de474 100644
--- a/wrap.go
+++ b/wrap.go
@@ -51,8 +51,10 @@
 	if target == nil {
 		return err == target
 	}
+
+	isComparable := target == nil || reflect.TypeOf(target).Comparable()
 	for {
-		if err == target {
+		if isComparable && err == target {
 			return true
 		}
 		if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
diff --git a/wrap_test.go b/wrap_test.go
index 1aec966..e9e1675 100644
--- a/wrap_test.go
+++ b/wrap_test.go
@@ -47,6 +47,12 @@
 		{poser, errb, false},
 		{poser, erro, false},
 		{poser, errco, false},
+		{errorUncomparable{}, errorUncomparable{}, true},
+		{errorUncomparable{}, &errorUncomparable{}, false},
+		{&errorUncomparable{}, errorUncomparable{}, true},
+		{&errorUncomparable{}, &errorUncomparable{}, false},
+		{errorUncomparable{}, err1, false},
+		{&errorUncomparable{}, err1, false},
 	}
 	for _, tc := range testCases {
 		t.Run("", func(t *testing.T) {
@@ -237,3 +243,16 @@
 func (errWrap) Error() string { return "wrapped" }
 
 func (errWrap) Unwrap() error { return nil }
+
+type errorUncomparable struct {
+	f []string
+}
+
+func (errorUncomparable) Error() string {
+	return "uncomparable error"
+}
+
+func (errorUncomparable) Is(target error) bool {
+	_, ok := target.(errorUncomparable)
+	return ok
+}