wrap.mx raw

   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.
   4  
   5  package errors
   6  
   7  // No imports needed — reflectlite removed.
   8  
   9  // Unwrap returns the result of calling the Unwrap method on err, if err's
  10  // type contains an Unwrap method returning error.
  11  // Otherwise, Unwrap returns nil.
  12  //
  13  // Unwrap only calls a method of the form "Unwrap() error".
  14  // In particular Unwrap does not unwrap errors returned by [Join].
  15  func Unwrap(err error) error {
  16  	u, ok := err.(interface {
  17  		Unwrap() error
  18  	})
  19  	if !ok {
  20  		return nil
  21  	}
  22  	return u.Unwrap()
  23  }
  24  
  25  // Is reports whether any error in err's tree matches target.
  26  //
  27  // The tree consists of err itself, followed by the errors obtained by repeatedly
  28  // calling its Unwrap() error or Unwrap() []error method. When err wraps multiple
  29  // errors, Is examines err followed by a depth-first traversal of its children.
  30  //
  31  // An error is considered to match a target if it is equal to that target or if
  32  // it implements a method Is(error) bool such that Is(target) returns true.
  33  //
  34  // An error type might provide an Is method so it can be treated as equivalent
  35  // to an existing error. For example, if MyError defines
  36  //
  37  //	func (m MyError) Is(target error) bool { return target == fs.ErrExist }
  38  //
  39  // then Is(MyError{}, fs.ErrExist) returns true. See [syscall.Errno.Is] for
  40  // an example in the standard library. An Is method should only shallowly
  41  // compare err and the target and not call [Unwrap] on either.
  42  func Is(err, target error) bool {
  43  	if err == nil || target == nil {
  44  		return err == target
  45  	}
  46  
  47  	return is(err, target, true)
  48  }
  49  
  50  func is(err, target error, targetComparable bool) bool {
  51  	for {
  52  		if targetComparable && err == target {
  53  			return true
  54  		}
  55  		if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
  56  			return true
  57  		}
  58  		switch x := err.(type) {
  59  		case interface{ Unwrap() error }:
  60  			err = x.Unwrap()
  61  			if err == nil {
  62  				return false
  63  			}
  64  		case interface{ Unwrap() []error }:
  65  			for _, err := range x.Unwrap() {
  66  				if is(err, target, targetComparable) {
  67  					return true
  68  				}
  69  			}
  70  			return false
  71  		default:
  72  			return false
  73  		}
  74  	}
  75  }
  76  
  77  // As was removed — it requires reflect for runtime type matching.
  78  // Use type assertions or errors.Is instead.
  79