Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/xerrors.As and x/xerrors.Is are deprecated but still used #321

Open
kortschak opened this issue Nov 13, 2022 · 0 comments · May be fixed by #405
Open

x/xerrors.As and x/xerrors.Is are deprecated but still used #321

kortschak opened this issue Nov 13, 2022 · 0 comments · May be fixed by #405

Comments

@kortschak
Copy link

kortschak commented Nov 13, 2022

The xerrors.As and xerrors.Is functions are deprecated and completely equivalent to the functions of the same name provided by the stdlib errors package. The only minor difference between the pairs of functions is that the errors package functions use the stdlib internal reflectlite package instead of full reflect.

  • https://pkg.go.dev/golang.org/x/xerrors#As

    Deprecated: As of Go 1.13, use errors.As instead.

    https://github.com/golang/xerrors/blob/04be3eba64a22a838cdb17b8dca15a52871c08b4/wrap.go#L76-L110

     // As finds the first error in err's chain that matches the type to which target
     // points, and if so, sets the target to its value and returns true. An error
     // matches a type if it is assignable to the target type, or if it has a method
     // As(interface{}) bool such that As(target) returns true. As will panic if target
     // is not a non-nil pointer to a type which implements error or is of interface type.
     //
     // The As method should set the target to its value and return true if err
     // matches the type to which target points.
     //
     // Deprecated: As of Go 1.13, use errors.As instead.
     func As(err error, target interface{}) bool {
     	if target == nil {
     		panic("errors: target cannot be nil")
     	}
     	val := reflect.ValueOf(target)
     	typ := val.Type()
     	if typ.Kind() != reflect.Ptr || val.IsNil() {
     		panic("errors: target must be a non-nil pointer")
     	}
     	if e := typ.Elem(); e.Kind() != reflect.Interface && !e.Implements(errorType) {
     		panic("errors: *target must be interface or implement error")
     	}
     	targetType := typ.Elem()
     	for err != nil {
     		if reflect.TypeOf(err).AssignableTo(targetType) {
     			val.Elem().Set(reflect.ValueOf(err))
     			return true
     		}
     		if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) {
     			return true
     		}
     		err = Unwrap(err)
     	}
     	return false
     }
    

    equivalent code in stdlib errors package

     // As finds the first error in err's chain that matches target, and if one is found, sets
     // target to that error value and returns true. Otherwise, it returns false.
     //
     // The chain consists of err itself followed by the sequence of errors obtained by
     // repeatedly calling Unwrap.
     //
     // An error matches target if the error's concrete value is assignable to the value
     // pointed to by target, or if the error has a method As(interface{}) bool such that
     // As(target) returns true. In the latter case, the As method is responsible for
     // setting target.
     //
     // An error type might provide an As method so it can be treated as if it were a
     // different error type.
     //
     // As panics if target is not a non-nil pointer to either a type that implements
     // error, or to any interface type.
     func As(err error, target any) bool {
     	if target == nil {
     		panic("errors: target cannot be nil")
     	}
     	val := reflectlite.ValueOf(target)
     	typ := val.Type()
     	if typ.Kind() != reflectlite.Ptr || val.IsNil() {
     		panic("errors: target must be a non-nil pointer")
     	}
     	targetType := typ.Elem()
     	if targetType.Kind() != reflectlite.Interface && !targetType.Implements(errorType) {
     		panic("errors: *target must be interface or implement error")
     	}
     	for err != nil {
     		if reflectlite.TypeOf(err).AssignableTo(targetType) {
     			val.Elem().Set(reflectlite.ValueOf(err))
     			return true
     		}
     		if x, ok := err.(interface{ As(any) bool }); ok && x.As(target) {
     			return true
     		}
     		err = Unwrap(err)
     	}
     	return false
     }
    
  • https://pkg.go.dev/golang.org/x/xerrors#Is

    Deprecated: As of Go 1.13, use errors.Is instead.

    https://github.com/golang/xerrors/blob/04be3eba64a22a838cdb17b8dca15a52871c08b4/wrap.go#L48-L74

     // Is reports whether any error in err's chain matches target.
     //
     // An error is considered to match a target if it is equal to that target or if
     // it implements a method Is(error) bool such that Is(target) returns true.
     //
     // Deprecated: As of Go 1.13, use errors.Is instead.
     func Is(err, target error) bool {
     	if target == nil {
     		return err == target
     	}
    
    
     	isComparable := reflect.TypeOf(target).Comparable()
     	for {
     		if isComparable && err == target {
     			return true
     		}
     		if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
     			return true
     		}
     		// TODO: consider supporing target.Is(err). This would allow
     		// user-definable predicates, but also may allow for coping with sloppy
     		// APIs, thereby making it easier to get away with them.
     		if err = Unwrap(err); err == nil {
     			return false
     		}
     	}
     }
    

    equivalent code in stdlib errors package

     // Is reports whether any error in err's chain matches target.
     //
     // The chain consists of err itself followed by the sequence of errors obtained by
     // repeatedly calling Unwrap.
     //
     // An error is considered to match a target if it is equal to that target or if
     // it implements a method Is(error) bool such that Is(target) returns true.
     //
     // An error type might provide an Is method so it can be treated as equivalent
     // to an existing error. For example, if MyError defines
     //
     //	func (m MyError) Is(target error) bool { return target == fs.ErrExist }
     //
     // then Is(MyError{}, fs.ErrExist) returns true. See syscall.Errno.Is for
     // an example in the standard library. An Is method should only shallowly
     // compare err and the target and not call Unwrap on either.
     func Is(err, target error) bool {
     	if target == nil {
     		return err == target
     	}
    
    
     	isComparable := reflectlite.TypeOf(target).Comparable()
     	for {
     		if isComparable && err == target {
     			return true
     		}
     		if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
     			return true
     		}
     		// TODO: consider supporting target.Is(err). This would allow
     		// user-definable predicates, but also may allow for coping with sloppy
     		// APIs, thereby making it easier to get away with them.
     		if err = Unwrap(err); err == nil {
     			return false
     		}
     	}
     }
    
@nervo nervo linked a pull request Oct 11, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant