@@ -80,6 +80,10 @@ func is(err, target error, targetComparable bool) bool {
8080// As finds the first error in err's tree that matches target, and if one is found, sets
8181// target to that error value and returns true. Otherwise, it returns false.
8282//
83+ // For most uses, prefer [AsType]. As is equivalent to [AsType] but sets its target
84+ // argument rather than returning the matching error and doesn't require its target
85+ // argument to implement error.
86+ //
8387// The tree consists of err itself, followed by the errors obtained by repeatedly
8488// calling its Unwrap() error or Unwrap() []error method. When err wraps multiple
8589// errors, As examines err followed by a depth-first traversal of its children.
@@ -145,3 +149,60 @@ func as(err error, target any, targetVal reflectlite.Value, targetType reflectli
145149}
146150
147151var errorType = reflectlite .TypeOf ((* error )(nil )).Elem ()
152+
153+ // AsType finds the first error in err's tree that matches the type E, and
154+ // if one is found, returns that error value and true. Otherwise, it
155+ // returns the zero value of E and false.
156+ //
157+ // The tree consists of err itself, followed by the errors obtained by
158+ // repeatedly calling its Unwrap() error or Unwrap() []error method. When
159+ // err wraps multiple errors, AsType examines err followed by a
160+ // depth-first traversal of its children.
161+ //
162+ // An error err matches the type E if the type assertion err.(E) holds,
163+ // or if the error has a method As(any) bool such that err.As(target)
164+ // returns true when target is a non-nil *E. In the latter case, the As
165+ // method is responsible for setting target.
166+ func AsType [E error ](err error ) (E , bool ) {
167+ if err == nil {
168+ var zero E
169+ return zero , false
170+ }
171+ var pe * E // lazily initialized
172+ return asType (err , & pe )
173+ }
174+
175+ func asType [E error ](err error , ppe * * E ) (_ E , _ bool ) {
176+ for {
177+ if e , ok := err .(E ); ok {
178+ return e , true
179+ }
180+ if x , ok := err .(interface { As (any ) bool }); ok {
181+ if * ppe == nil {
182+ * ppe = new (E )
183+ }
184+ if x .As (* ppe ) {
185+ return * * ppe , true
186+ }
187+ }
188+ switch x := err .(type ) {
189+ case interface { Unwrap () error }:
190+ err = x .Unwrap ()
191+ if err == nil {
192+ return
193+ }
194+ case interface { Unwrap () []error }:
195+ for _ , err := range x .Unwrap () {
196+ if err == nil {
197+ continue
198+ }
199+ if x , ok := asType (err , ppe ); ok {
200+ return x , true
201+ }
202+ }
203+ return
204+ default :
205+ return
206+ }
207+ }
208+ }
0 commit comments