}
isComparable := reflectlite.TypeOf(target).Comparable()
+ return is(err, target, isComparable)
+}
+
+func is(err, target error, targetComparable bool) bool {
for {
- if isComparable && err == target {
+ if targetComparable && err == target {
return true
}
if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
}
case interface{ Unwrap() []error }:
for _, err := range x.Unwrap() {
- if Is(err, target) {
+ if is(err, target, targetComparable) {
return true
}
}
if targetType.Kind() != reflectlite.Interface && !targetType.Implements(errorType) {
panic("errors: *target must be interface or implement error")
}
+ return as(err, target, val, targetType)
+}
+
+func as(err error, target any, targetVal reflectlite.Value, targetType reflectlite.Type) bool {
for {
if reflectlite.TypeOf(err).AssignableTo(targetType) {
- val.Elem().Set(reflectlite.ValueOf(err))
+ targetVal.Elem().Set(reflectlite.ValueOf(err))
return true
}
if x, ok := err.(interface{ As(any) bool }); ok && x.As(target) {
}
case interface{ Unwrap() []error }:
for _, err := range x.Unwrap() {
- if As(err, target) {
+ if err == nil {
+ continue
+ }
+ if as(err, target, targetVal, targetType) {
return true
}
}
}
}
+func BenchmarkIs(b *testing.B) {
+ err1 := errors.New("1")
+ err2 := multiErr{multiErr{multiErr{err1, errorT{"a"}}, errorT{"b"}}}
+
+ for i := 0; i < b.N; i++ {
+ if !errors.Is(err2, err1) {
+ b.Fatal("Is failed")
+ }
+ }
+}
+
+func BenchmarkAs(b *testing.B) {
+ err := multiErr{multiErr{multiErr{errors.New("a"), errorT{"a"}}, errorT{"b"}}}
+ for i := 0; i < b.N; i++ {
+ var target errorT
+ if !errors.As(err, &target) {
+ b.Fatal("As failed")
+ }
+ }
+}
+
func TestUnwrap(t *testing.T) {
err1 := errors.New("1")
erra := wrapped{"wrap 2", err1}