design: add error values proposal

After approval, I'll create an issue and change the name of this file to match.

Change-Id: I710fbad3f37ef03ab256c1422007b63b664e9e06
Reviewed-on: https://go-review.googlesource.com/c/159497
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/design/29934-error-values.md b/design/29934-error-values.md
new file mode 100644
index 0000000..c3fe5fc
--- /dev/null
+++ b/design/29934-error-values.md
@@ -0,0 +1,312 @@
+# Proposal: Go 2 Error Inspection
+
+Jonathan Amsterdam\
+Russ Cox\
+Marcel van Lohuizen\
+Damien Neil
+
+Last updated: January 24, 2019
+
+Discussion at: TODO NEW ISSUE
+
+Past discussion at:
+- https://golang.org/design/go2draft-error-inspection
+- https://golang.org/design/go2draft-error-printing
+- https://golang.org/wiki/Go2ErrorValuesFeedback
+
+## Abstract
+
+We propose several additions and changes to the standard library’s `errors` and
+`fmt` packages, with the goal of making errors more informative for both
+programs and people. We codify the common practice of wrapping one error in
+another, and provide two convenience functions, `Is` and `As`, for traversing
+the chain of wrapped errors.
+
+We enrich error formatting by making it easy for error types to display
+additional information when detailed output is requested with the `%+v`
+formatting directive.
+
+We add function, file and line information to the errors returned by
+`errors.New` and `fmt.Errorf`, and provide a `Frame` type to simplify adding
+location information to any error type.
+
+We add support for detail formatting and wrapping to `fmt.Errorf`.
+
+## Background
+
+We provided background and a rationale in our [draft designs for error
+inspection](https://go.googlesource.com/proposal/+/master/design/go2draft-error-inspection.md)
+and
+[printing](https://go.googlesource.com/proposal/+/master/design/go2draft-error-printing.md).
+Here we provide a brief summary.
+
+While Go 1’s definition of errors is open-ended, its actual support for errors
+is minimal, providing only string messages. Many Go programmers want to provide
+additional information with errors, and of course nothing has stopped them from
+doing so. But one pattern has become so pervasive that we feel it is worth
+enshrining in the standard library: the idea of wrapping one error in another
+that provides additional information. Several packages provide wrapping support,
+including the popular
+[github.com/pkg/errors](https://godoc.org/github.com/pkg/errors).
+
+Others have pointed out that indiscriminate wrapping can expose implementation
+details, introducing undesired coupling between packages. As an example, the
+[`errgo`](https://godoc.org/gopkg.in/errgo.v2) package lets users control
+wrapping to hide details.
+
+Another popular request is for location information in the form of stack frames.
+Some advocate for complete stack traces, while others prefer to add location
+information only at certain points.
+
+## Proposal
+
+We add a standard way to wrap errors to the standard library, to encourage the
+practice and to make it easy to use. We separate error wrapping, designed for
+programs, from error formatting, designed for people. This makes it possible to
+hide implementation details from programs while displaying them for diagnosis.
+We also add location (stack frame) information to standard errors and make it
+easy for developers to include location information in their own errors.
+
+All of the API changes are in the `errors` package. We also change the behavior
+of parts of the `fmt` package.
+
+### Wrapping
+
+An error that wraps another error should implement `Wrapper` by defining an `Unwrap` method.
+```
+type Wrapper interface {
+        // Unwrap returns the next error in the error chain.
+        // If there is no next error, Unwrap returns nil.
+        Unwrap() error
+}
+```
+The `Unwrap` function is a convenience for calling the `Unwrap` method if one exists.
+```
+// Unwrap returns the result of calling the Unwrap method on err, if err implements Unwrap.
+// Otherwise, Unwrap returns nil.
+func Unwrap(err error) error
+```
+
+The `Is` function follows the chain of errors by calling `Unwrap`, searching for
+one that matches a target. It is intended to be used instead of equality for
+matching sentinel errors (unique error values). An error type can implement an
+`Is` method to override the default behavior.
+
+```
+// 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.
+func Is(err, target error) bool
+```
+
+The `As` function searches the wrapping chain for an error whose type matches
+that of a target. An error type can implement `As` to override the default
+behavior.
+```
+// 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 and returns true. An error
+// matches a type if it is of the same type, or if it has a method As(interface{}) bool
+// such that As(target) returns true. As will panic if target is nil or not a pointer.
+//
+// The As method should set the target to its value and return true if err
+// matches the type to which target points.
+func As(err error, target interface{}) bool
+```
+
+The `Opaque` function hides a wrapped error from programmatic inspection.
+```
+// Opaque returns an error with the same error formatting as err
+// but that does not match err and cannot be unwrapped.
+func Opaque(err error) error
+```
+
+### Stack Frames
+
+The `Frame` type holds location information: the function name, file and line of
+a single stack frame.
+```
+type Frame struct {
+	// unexported fields
+}
+```
+
+The `Caller` function returns a `Frame` at a given distance from the call site.
+It is a convenience wrapper around `runtime.Callers`.
+```
+func Caller(skip int) Frame
+```
+
+To display itself, `Frame` implements a `Format` method that takes a `Printer`.
+See [Formatting](#formatting) below for the definition of `Printer`.
+```
+// Format prints the stack as error detail.
+// It should be called from an error's FormatError implementation,
+// before printing any other error detail.
+func (f Frame) Format(p Printer)
+```
+
+The errors returned from `errors.New` and `fmt.Errorf` include a `Frame` which
+will be displayed when the error is formatted with additional detail (see
+below).
+
+### Formatting
+
+We introduce two interfaces for error formatting into the `errors` package and
+change the behavior of formatted output (the `Print`, `Println` and `Printf`
+functions of the `fmt` package and their `S` and `F` variants) to recognize
+them.
+
+The `errors.Formatter` interface adds the `FormatError` method to the `error` interface.
+```
+type Formatter interface {
+	error
+
+	// FormatError prints the receiver's first error and returns the next error to
+	// be formatted, if any.
+	FormatError(p Printer) (next error)
+}
+```
+An error type that wants to control its formatted output should implement
+`Formatter`. During formatted output, `FormatError` will be called if it is
+implemented, in preference to both the `Error` and `Format` methods.
+
+`FormatError` returns an error, which will also be output if it is not `nil`. If
+an error type implements `Wrapper`, then it would likely return the result of
+`Unwrap` from `FormatError`, but it is not required to do so. An error that does
+not implement `Wrapper` may still return a non-nil value from `FormatError`,
+hiding implementation detail from programs while still displaying it to users.
+
+The `Printer` passed to `FormatError` provides `Print` and `Printf` methods to
+generate output, as well as a `Detail` method that reports whether the printing
+is happening in "detail mode" (triggered by `%+v`). Implementations should first
+call `Printer.Detail`, and if it returns true should then print detailed
+information like the location of the error.
+```
+type Printer interface {
+	// Print appends args to the message output.
+	Print(args ...interface{})
+
+	// Printf writes a formatted string.
+	Printf(format string, args ...interface{})
+
+	// Detail reports whether error detail is requested.
+	// After the first call to Detail, all text written to the Printer
+	// is formatted as additional detail, or ignored when
+	// detail has not been requested.
+	// If Detail returns false, the caller can avoid printing the detail at all.
+	Detail() bool
+}
+```
+
+When not in detail mode (`%v`, or in `Print` and `Println` functions and their
+variants), errors print on a single line. In detail mode, errors print over
+multiple lines, as shown here:
+```
+write users database:
+    more detail here
+    /path/to/database.go:111
+  - call myserver.Method:
+    /path/to/grpc.go:222
+  - dial myserver:3333:
+    /path/to/net/dial.go:333
+  - open /etc/resolv.conf:
+    /path/to/os/open.go:444
+  - permission denied
+```
+
+### Changes to `fmt.Errorf`
+
+We modify the behavior of `fmt.Errorf` in the following case: if the last
+argument is an error `err` and the format string ends with `: %s`, `: %v`, or
+`: %w`, then the returned error will implement `FormatError` to return `err`. In
+the case of the new verb `%w`, the returned error will also implement
+`errors.Wrapper` with an `Unwrap` method returning `err`.
+
+### Transition
+
+If we add this functionality to the standard library in Go 1.13, code that needs
+to keep building with previous versions of Go will not be able to depend on the
+new standard library. While every such package could use build tags and multiple
+source files, that seems like too much work for a smooth transition.
+
+To help the transition, we will publish a new package
+[golang.org/x/xerrors](https://godoc.org/golang.org/x/xerrors), which will work
+with both Go 1.13 and earlier versions and will provide the following:
+
+- The `Wrapper`, `Frame`, `Formatter` and `Printer` types described above.
+- The `Unwrap`, `Is`, `As`, `Opaque` and `Caller` functions described above.
+- A `New` function that is a drop-in replacement for `errors.New`, but returns
+  an error that behaves as described above.
+- An `Errorf` function that is a drop-in replacement for `fmt.Errorf`, except
+  that it behaves as described above.
+- A `FormatError` function that adapts the `Format` method to use the new
+  formatting implementation. An error implementation can make sure earlier Go
+  versions call its `FormatError` method by adding this `Format` method:
+  ```
+  type MyError …
+  func (m *MyError) Format(f fmt.State, c rune) { // implements fmt.Formatter
+      xerrors.FormatError(m, f, c)
+  }
+  ```
+
+## Rationale
+
+We provided a rationale for most of these changes in the draft designs (linked
+above). Here we justify the parts of the design that have changed or been added
+since those documents were written.
+
+- The original draft design proposed that the `As` function use generics, and
+  suggested an `AsValue` function as a temporary alternative until generics were
+  available. We find that the `As` function in the form we describe here is just
+  as concise and readable as a generic version would be, if not more so.
+
+- We added the ability for error types to modify the default behavior of the
+  `Is` and `As` functions by implementing `Is` and `As` methods, respectively.
+  We felt that the extra power these give to error implementers was worth the
+  slight additional complexity.
+
+- We included a `Frame` in the errors returned by `errors.New` and `fmt.Errorf`
+  so that existing Go programs could reap the benefits of location information.
+  We benchmarked the slowdown from fetching stack information and felt that it
+  was tolerable.
+
+- We changed the behavior of `fmt.Errorf` for the same reason: so existing Go
+  programs could enjoy the new formatting behavior without modification. We
+  decided against wrapping errors passed to `fmt.Errorf` by default, since doing
+  so would effectively change the exposed surface of a package by revealing the
+  types of the wrapped errors. Instead, we require that programmers opt in to
+  wrapping by using the new formatting verb `%w`.
+
+- Lastly, we want to acknowledge the several comments on the [feedback
+  wiki](https://golang.org/wiki/Go2ErrorValuesFeedback) that suggested that we
+  go further by incorporating a way to represent multiple errors as a single
+  error value. We understand that this is a popular request, but at this point
+  we feel we have introduced enough new features for one proposal, and we’d like
+  to see how these work out before adding more. We can always add a multi-error
+  type in a later proposal, and meanwhile it remains easy to write your own.
+
+## Compatibility
+
+None of the proposed changes violates the [Go 1 compatibility
+guidelines](https://golang.org/doc/go1compat). Gathering frame information may
+slow down `errors.New` slightly, but this is unlikely to affect practical
+programs. Errors constructed with `errors.New` and `fmt.Errorf` will display
+differently with `%+v`.
+
+## Implementation
+
+The implementation requires changes to the standard library.
+
+The [golang.org/x/exp/errors](https://godoc.org/golang.org/x/exp/errors) package
+contains a proposed implementation by Marcel van Lohuizen. We intend to make the
+changes to the main tree at the start of the Go 1.13 cycle, around February 1.
+
+As noted in our blog post ["Go 2, here we
+come!"](https://blog.golang.org/go2-here-we-come), the development cycle will
+serve as a way to collect experience about these new features and feedback from
+(very) early adopters.
+
+As noted above, the
+[golang.org/x/xerrors](https://godoc.org/golang.org/x/xerrors) package, also by
+Marcel, will provide code that can be used with earlier Go versions.