codeberg.org/gruf/go-errors/v2@v2.3.1/standard.go (about) 1 package errors 2 3 import ( 4 _ "unsafe" 5 ) 6 7 // Is reports whether any error in err's tree matches target. 8 // 9 // The tree consists of err itself, followed by the errors obtained by repeatedly 10 // calling Unwrap. When err wraps multiple errors, Is examines err followed by a 11 // depth-first traversal of its children. 12 // 13 // An error is considered to match a target if it is equal to that target or if 14 // it implements a method Is(error) bool such that Is(target) returns true. 15 // 16 // An error type might provide an Is method so it can be treated as equivalent 17 // to an existing error. For example, if MyError defines 18 // 19 // func (m MyError) Is(target error) bool { return target == fs.ErrExist } 20 // 21 // then Is(MyError{}, fs.ErrExist) returns true. See [syscall.Errno.Is] for 22 // an example in the standard library. An Is method should only shallowly 23 // compare err and the target and not call Unwrap on either. 24 // 25 //go:linkname Is errors.Is 26 func Is(err error, target error) bool 27 28 // IsV2 calls Is(err, target) for each target within targets. 29 func IsV2(err error, targets ...error) bool { 30 for _, target := range targets { 31 if Is(err, target) { 32 return true 33 } 34 } 35 return false 36 } 37 38 // As finds the first error in err's tree that matches target, and if one is found, sets 39 // target to that error value and returns true. Otherwise, it returns false. 40 // 41 // The tree consists of err itself, followed by the errors obtained by repeatedly 42 // calling Unwrap. When err wraps multiple errors, As examines err followed by a 43 // depth-first traversal of its children. 44 // 45 // An error matches target if the error's concrete value is assignable to the value 46 // pointed to by target, or if the error has a method As(interface{}) bool such that 47 // As(target) returns true. In the latter case, the As method is responsible for 48 // setting target. 49 // 50 // An error type might provide an As method so it can be treated as if it were a 51 // different error type. 52 // 53 // As panics if target is not a non-nil pointer to either a type that implements 54 // error, or to any interface type. 55 // 56 //go:linkname As errors.As 57 func As(err error, target any) bool 58 59 // AsV2 is functionally similar to As(), instead 60 // leveraging generics to handle allocation and 61 // returning of a concrete generic parameter type. 62 func AsV2[Type any](err error) Type { 63 var t Type 64 var ok bool 65 errs := []error{err} 66 for len(errs) > 0 { 67 // Pop next error to check. 68 err := errs[len(errs)-1] 69 errs = errs[:len(errs)-1] 70 71 // Check direct type. 72 t, ok = err.(Type) 73 if ok { 74 return t 75 } 76 77 // Look for .As() support. 78 as, ok := err.(interface { 79 As(target any) bool 80 }) 81 82 if ok { 83 // Attempt .As(). 84 if as.As(&t) { 85 return t 86 } 87 } 88 89 // Try unwrap errors. 90 switch u := err.(type) { 91 case interface{ Unwrap() error }: 92 errs = append(errs, u.Unwrap()) 93 case interface{ Unwrap() []error }: 94 errs = append(errs, u.Unwrap()...) 95 } 96 } 97 return t 98 } 99 100 // Unwrap returns the result of calling the Unwrap method on err, if err's 101 // type contains an Unwrap method returning error. 102 // Otherwise, Unwrap returns nil. 103 // 104 // Unwrap only calls a method of the form "Unwrap() error". 105 // In particular Unwrap does not unwrap errors returned by [Join]. 106 // 107 //go:linkname Unwrap errors.Unwrap 108 func Unwrap(err error) error 109 110 // UnwrapV2 is functionally similar to Unwrap(), except that 111 // it also handles the case of interface{ Unwrap() []error }. 112 func UnwrapV2(err error) []error { 113 switch u := err.(type) { 114 case interface{ Unwrap() error }: 115 if e := u.Unwrap(); err != nil { 116 return []error{e} 117 } 118 case interface{ Unwrap() []error }: 119 return u.Unwrap() 120 } 121 return nil 122 } 123 124 // Join returns an error that wraps the given errors. 125 // Any nil error values are discarded. 126 // Join returns nil if every value in errs is nil. 127 // The error formats as the concatenation of the strings obtained 128 // by calling the Error method of each element of errs, with a newline 129 // between each string. 130 // 131 // A non-nil error returned by Join implements the Unwrap() []error method. 132 // 133 //go:linkname Join errors.Join 134 func Join(errs ...error) error