-
Notifications
You must be signed in to change notification settings - Fork 11
Description
Named returns with defer can modify the return error through indirect assignments, e.g., passing a pointer to the error to a function that modifies it.
Example:
func main() {
fmt.Printf("%+v\n", getErr())
}
func getErr() (err error) {
defer func() {
setErr(&err)
}()
return
}
func setErr(err *error) {
*err = fmt.Errorf("err")
}errtrace modifies getErr() by adding a wrap before the return:
func getErr() (err error) {
defer func() {
setErr(&err)
}()
err = errtrace.Wrap(err)
return
}However, the defer is not handled, since it's not clear whether the error will be modified by the function.
We could assume that anytime a pointer to the error is referenced, that it's used to modify the error, and add a wrap (though that could end up double-wrapping in the same function).
Another option, if we see named error returns, and defers that reference the named error return, rather than wrap at return time, we can add an additional defer that wraps the error. We may want to add a WrapInto(*error) to make this cleaner, so callers can do defer errtrace.WrapInto(&err)