1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
11 // Unwrap returns the result of calling the Unwrap method on err, if err's
12 // type contains an Unwrap method returning error.
13 // Otherwise, Unwrap returns nil.
15 // Unwrap only calls a method of the form "Unwrap() error".
16 // In particular Unwrap does not unwrap errors returned by [Join].
17 func Unwrap(err error) error {
18 u, ok := err.(interface {
27 // Is reports whether any error in err's tree matches target.
29 // The tree consists of err itself, followed by the errors obtained by repeatedly
30 // calling [Unwrap]. When err wraps multiple errors, Is examines err followed by a
31 // depth-first traversal of its children.
33 // An error is considered to match a target if it is equal to that target or if
34 // it implements a method Is(error) bool such that Is(target) returns true.
36 // An error type might provide an Is method so it can be treated as equivalent
37 // to an existing error. For example, if MyError defines
39 // func (m MyError) Is(target error) bool { return target == fs.ErrExist }
41 // then Is(MyError{}, fs.ErrExist) returns true. See [syscall.Errno.Is] for
42 // an example in the standard library. An Is method should only shallowly
43 // compare err and the target and not call [Unwrap] on either.
44 func Is(err, target error) bool {
49 isComparable := reflectlite.TypeOf(target).Comparable()
50 return is(err, target, isComparable)
53 func is(err, target error, targetComparable bool) bool {
55 if targetComparable && err == target {
58 if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
61 switch x := err.(type) {
62 case interface{ Unwrap() error }:
67 case interface{ Unwrap() []error }:
68 for _, err := range x.Unwrap() {
69 if is(err, target, targetComparable) {
80 // As finds the first error in err's tree that matches target, and if one is found, sets
81 // target to that error value and returns true. Otherwise, it returns false.
83 // The tree consists of err itself, followed by the errors obtained by repeatedly
84 // calling [Unwrap]. When err wraps multiple errors, As examines err followed by a
85 // depth-first traversal of its children.
87 // An error matches target if the error's concrete value is assignable to the value
88 // pointed to by target, or if the error has a method As(interface{}) bool such that
89 // As(target) returns true. In the latter case, the As method is responsible for
92 // An error type might provide an As method so it can be treated as if it were a
93 // different error type.
95 // As panics if target is not a non-nil pointer to either a type that implements
96 // error, or to any interface type.
97 func As(err error, target any) bool {
102 panic("errors: target cannot be nil")
104 val := reflectlite.ValueOf(target)
106 if typ.Kind() != reflectlite.Ptr || val.IsNil() {
107 panic("errors: target must be a non-nil pointer")
109 targetType := typ.Elem()
110 if targetType.Kind() != reflectlite.Interface && !targetType.Implements(errorType) {
111 panic("errors: *target must be interface or implement error")
113 return as(err, target, val, targetType)
116 func as(err error, target any, targetVal reflectlite.Value, targetType reflectlite.Type) bool {
118 if reflectlite.TypeOf(err).AssignableTo(targetType) {
119 targetVal.Elem().Set(reflectlite.ValueOf(err))
122 if x, ok := err.(interface{ As(any) bool }); ok && x.As(target) {
125 switch x := err.(type) {
126 case interface{ Unwrap() error }:
131 case interface{ Unwrap() []error }:
132 for _, err := range x.Unwrap() {
136 if as(err, target, targetVal, targetType) {
147 var errorType = reflectlite.TypeOf((*error)(nil)).Elem()