xerrors: copied files from x/exp/errors

changed paths and removed experimental notice

Also made panic test pass: the output differed
for different Go versions.

Change-Id: Iadd367fb253459d288c3ec7e3aaafce9af939983
Reviewed-on: https://go-review.googlesource.com/c/159777
Run-TryBot: Marcel van Lohuizen <mpvl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/adaptor.go b/adaptor.go
new file mode 100644
index 0000000..83a7945
--- /dev/null
+++ b/adaptor.go
@@ -0,0 +1,188 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"strconv"
+)
+
+// FormatError calls the FormatError method of f with an errors.Printer
+// configured according to s and verb, and writes the result to s.
+func FormatError(f Formatter, s fmt.State, verb rune) {
+	// Assuming this function is only called from the Format method, and given
+	// that FormatError takes precedence over Format, it cannot be called from
+	// any package that supports errors.Formatter. It is therefore safe to
+	// disregard that State may be a specific printer implementation and use one
+	// of our choice instead.
+
+	// limitations: does not support printing error as Go struct.
+
+	var (
+		sep    = " " // separator before next error
+		p      = &state{State: s}
+		direct = true
+	)
+
+	var err error = f
+
+	switch verb {
+	// Note that this switch must match the preference order
+	// for ordinary string printing (%#v before %+v, and so on).
+
+	case 'v':
+		if s.Flag('#') {
+			if stringer, ok := err.(fmt.GoStringer); ok {
+				io.WriteString(&p.buf, stringer.GoString())
+				goto exit
+			}
+			// proceed as if it were %v
+		} else if s.Flag('+') {
+			p.printDetail = true
+			sep = "\n  - "
+		}
+	case 's':
+	case 'q', 'x', 'X':
+		// Use an intermediate buffer in the rare cases that precision,
+		// truncation, or one of the alternative verbs (q, x, and X) are
+		// specified.
+		direct = false
+
+	default:
+		p.buf.WriteString("%!")
+		p.buf.WriteRune(verb)
+		p.buf.WriteByte('(')
+		switch {
+		case err != nil:
+			p.buf.WriteString(reflect.TypeOf(f).String())
+		default:
+			p.buf.WriteString("<nil>")
+		}
+		p.buf.WriteByte(')')
+		io.Copy(s, &p.buf)
+		return
+	}
+
+loop:
+	for {
+		p.inDetail = false
+
+		switch v := err.(type) {
+		case Formatter:
+			err = v.FormatError((*printer)(p))
+		case fmt.Formatter:
+			v.Format(p, 'v')
+			break loop
+		default:
+			io.WriteString(&p.buf, v.Error())
+			break loop
+		}
+		if err == nil {
+			break
+		}
+		if !p.inDetail || !p.printDetail {
+			p.buf.WriteByte(':')
+		}
+		// Strip last newline of detail.
+		if bytes.HasSuffix(p.buf.Bytes(), detailSep) {
+			p.buf.Truncate(p.buf.Len() - len(detailSep))
+		}
+		p.buf.WriteString(sep)
+		p.inDetail = false
+	}
+
+exit:
+	width, okW := s.Width()
+	prec, okP := s.Precision()
+
+	if !direct || (okW && width > 0) || okP {
+		// Construct format string from State s.
+		format := []byte{'%'}
+		if s.Flag('-') {
+			format = append(format, '-')
+		}
+		if s.Flag('+') {
+			format = append(format, '+')
+		}
+		if s.Flag(' ') {
+			format = append(format, ' ')
+		}
+		if okW {
+			format = strconv.AppendInt(format, int64(width), 10)
+		}
+		if okP {
+			format = append(format, '.')
+			format = strconv.AppendInt(format, int64(prec), 10)
+		}
+		format = append(format, string(verb)...)
+		fmt.Fprintf(s, string(format), p.buf.String())
+	} else {
+		io.Copy(s, &p.buf)
+	}
+}
+
+var detailSep = []byte("\n    ")
+
+// state tracks error printing state. It implements fmt.State.
+type state struct {
+	fmt.State
+	buf bytes.Buffer
+
+	printDetail bool
+	inDetail    bool
+	needNewline bool
+}
+
+func (s *state) Write(b []byte) (n int, err error) {
+	if s.printDetail {
+		if len(b) == 0 {
+			return 0, nil
+		}
+		if s.inDetail && s.needNewline {
+			s.needNewline = false
+			s.buf.WriteByte(':')
+			s.buf.Write(detailSep)
+			if b[0] == '\n' {
+				b = b[1:]
+			}
+		}
+		k := 0
+		for i, c := range b {
+			if c == '\n' {
+				s.buf.Write(b[k:i])
+				s.buf.Write(detailSep)
+				k = i + 1
+			}
+		}
+		s.buf.Write(b[k:])
+		s.needNewline = !s.inDetail
+	} else if !s.inDetail {
+		s.buf.Write(b)
+	}
+	return len(b), nil
+}
+
+// printer wraps a state to implement an xerrors.Printer.
+type printer state
+
+func (s *printer) Print(args ...interface{}) {
+	if !s.inDetail || s.printDetail {
+		fmt.Fprint((*state)(s), args...)
+	}
+}
+
+func (s *printer) Printf(format string, args ...interface{}) {
+	if !s.inDetail || s.printDetail {
+		fmt.Fprintf((*state)(s), format, args...)
+	}
+}
+
+func (s *printer) Detail() bool {
+	s.inDetail = true
+	return s.printDetail
+}
diff --git a/doc.go b/doc.go
new file mode 100644
index 0000000..1ad48f5
--- /dev/null
+++ b/doc.go
@@ -0,0 +1,25 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package xerrors implements functions to manipulate errors.
+//
+// This package supports transitioning to the Go 2 proposal for error values:
+//   https://golang.org/design/29934-error-values
+//
+// Most of the functions and types in this package will be incorporated into the
+// standard library's errors package in Go 1.13; the behavior of this package's
+// Errorf function will be incorporated into the standard library's fmt.Errorf.
+// Use this package to get equivalent behavior in all supported Go versions. For
+// example, create errors using
+//
+//    xerrors.New("write failed")
+//
+// or
+//
+//    xerrors.Errorf("while reading: %v", err)
+//
+// If you want your error type to participate in the new formatting
+// implementation for %v and %+v, provide it with a Format method that calls
+// xerrors.FormatError, as shown in the example for FormatError.
+package xerrors // import "golang.org/x/xerrors"
diff --git a/errors.go b/errors.go
new file mode 100644
index 0000000..0a812bd
--- /dev/null
+++ b/errors.go
@@ -0,0 +1,29 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors
+
+// errorString is a trivial implementation of error.
+type errorString struct {
+	s     string
+	frame Frame
+}
+
+// New returns an error that formats as the given text.
+//
+// The returned error contains a Frame set to the caller's location and
+// implements Formatter to show this information when printed with details.
+func New(text string) error {
+	return &errorString{text, Caller(1)}
+}
+
+func (e *errorString) Error() string {
+	return e.s
+}
+
+func (e *errorString) FormatError(p Printer) (next error) {
+	p.Print(e.s)
+	e.frame.Format(p)
+	return nil
+}
diff --git a/errors_test.go b/errors_test.go
new file mode 100644
index 0000000..3417ee6
--- /dev/null
+++ b/errors_test.go
@@ -0,0 +1,54 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors_test
+
+import (
+	"fmt"
+	"testing"
+
+	"golang.org/x/xerrors"
+)
+
+func TestNewEqual(t *testing.T) {
+	// Different allocations should not be equal.
+	if xerrors.New("abc") == xerrors.New("abc") {
+		t.Errorf(`New("abc") == New("abc")`)
+	}
+	if xerrors.New("abc") == xerrors.New("xyz") {
+		t.Errorf(`New("abc") == New("xyz")`)
+	}
+
+	// Same allocation should be equal to itself (not crash).
+	err := xerrors.New("jkl")
+	if err != err {
+		t.Errorf(`err != err`)
+	}
+}
+
+func TestErrorMethod(t *testing.T) {
+	err := xerrors.New("abc")
+	if err.Error() != "abc" {
+		t.Errorf(`New("abc").Error() = %q, want %q`, err.Error(), "abc")
+	}
+}
+
+func ExampleNew() {
+	err := xerrors.New("emit macho dwarf: elf header corrupted")
+	if err != nil {
+		fmt.Print(err)
+	}
+	// Output: emit macho dwarf: elf header corrupted
+}
+
+// The fmt package's Errorf function lets us use the package's formatting
+// features to create descriptive error messages.
+func ExampleNew_errorf() {
+	const name, id = "bimmler", 17
+	err := fmt.Errorf("user %q (id %d) not found", name, id)
+	if err != nil {
+		fmt.Print(err)
+	}
+	// Output: user "bimmler" (id 17) not found
+}
diff --git a/example_As_test.go b/example_As_test.go
new file mode 100644
index 0000000..647afdd
--- /dev/null
+++ b/example_As_test.go
@@ -0,0 +1,25 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors_test
+
+import (
+	"fmt"
+	"os"
+
+	"golang.org/x/xerrors"
+)
+
+func ExampleAs() {
+	_, err := os.Open("non-existing")
+	if err != nil {
+		var pathError *os.PathError
+		if xerrors.As(err, &pathError) {
+			fmt.Println("Failed at path:", pathError.Path)
+		}
+	}
+
+	// Output:
+	// Failed at path: non-existing
+}
diff --git a/example_FormatError_test.go b/example_FormatError_test.go
new file mode 100644
index 0000000..3e712c9
--- /dev/null
+++ b/example_FormatError_test.go
@@ -0,0 +1,39 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors_test
+
+import (
+	"fmt"
+
+	"golang.org/x/xerrors"
+)
+
+type MyError2 struct {
+	Message string
+	frame   xerrors.Frame
+}
+
+func (m *MyError2) Error() string {
+	return m.Message
+}
+
+func (m *MyError2) Format(f fmt.State, c rune) { // implements fmt.Formatter
+	xerrors.FormatError(m, f, c)
+}
+
+func (m *MyError2) FormatError(p xerrors.Printer) error { // implements xerrors.Formatter
+	p.Print(m.Message)
+	if p.Detail() {
+		m.frame.Format(p)
+	}
+	return nil
+}
+
+func ExampleFormatError() {
+	err := &MyError2{Message: "oops", frame: xerrors.Caller(1)}
+	fmt.Printf("%v\n", err)
+	fmt.Println()
+	fmt.Printf("%+v\n", err)
+}
diff --git a/example_test.go b/example_test.go
new file mode 100644
index 0000000..107f80c
--- /dev/null
+++ b/example_test.go
@@ -0,0 +1,34 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors_test
+
+import (
+	"fmt"
+	"time"
+)
+
+// MyError is an error implementation that includes a time and message.
+type MyError struct {
+	When time.Time
+	What string
+}
+
+func (e MyError) Error() string {
+	return fmt.Sprintf("%v: %v", e.When, e.What)
+}
+
+func oops() error {
+	return MyError{
+		time.Date(1989, 3, 15, 22, 30, 0, 0, time.UTC),
+		"the file system has gone away",
+	}
+}
+
+func Example() {
+	if err := oops(); err != nil {
+		fmt.Println(err)
+	}
+	// Output: 1989-03-15 22:30:00 +0000 UTC: the file system has gone away
+}
diff --git a/fmt.go b/fmt.go
new file mode 100644
index 0000000..74c1c93
--- /dev/null
+++ b/fmt.go
@@ -0,0 +1,109 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors
+
+import (
+	"fmt"
+	"strings"
+
+	"golang.org/x/xerrors/internal"
+)
+
+// Errorf formats according to a format specifier and returns the string as a
+// value that satisfies error.
+//
+// The returned error includes the file and line number of the caller when
+// formatted with additional detail enabled. If the last argument is an error
+// the returned error's Format method will return it if the format string ends
+// with ": %s", ": %v", or ": %w". If the last argument is an error and the
+// format string ends with ": %w", the returned error implements Wrapper
+// with an Unwrap method returning it.
+func Errorf(format string, a ...interface{}) error {
+	err, wrap := lastError(format, a)
+	format = formatPlusW(format)
+	if err == nil {
+		return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)}
+	}
+
+	// TODO: this is not entirely correct. The error value could be
+	// printed elsewhere in format if it mixes numbered with unnumbered
+	// substitutions. With relatively small changes to doPrintf we can
+	// have it optionally ignore extra arguments and pass the argument
+	// list in its entirety.
+	msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...)
+	frame := Frame{}
+	if internal.EnableTrace {
+		frame = Caller(1)
+	}
+	if wrap {
+		return &wrapError{msg, err, frame}
+	}
+	return &noWrapError{msg, err, frame}
+}
+
+// formatPlusW is used to avoid the vet check that will barf at %w.
+func formatPlusW(s string) string {
+	return s
+}
+
+func lastError(format string, a []interface{}) (err error, wrap bool) {
+	wrap = strings.HasSuffix(format, ": %w")
+	if !wrap &&
+		!strings.HasSuffix(format, ": %s") &&
+		!strings.HasSuffix(format, ": %v") {
+		return nil, false
+	}
+
+	if len(a) == 0 {
+		return nil, false
+	}
+
+	err, ok := a[len(a)-1].(error)
+	if !ok {
+		return nil, false
+	}
+
+	return err, wrap
+}
+
+type noWrapError struct {
+	msg   string
+	err   error
+	frame Frame
+}
+
+func (e *noWrapError) Error() string {
+	return fmt.Sprint(e)
+}
+
+func (e *noWrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) }
+
+func (e *noWrapError) FormatError(p Printer) (next error) {
+	p.Print(e.msg)
+	e.frame.Format(p)
+	return e.err
+}
+
+type wrapError struct {
+	msg   string
+	err   error
+	frame Frame
+}
+
+func (e *wrapError) Error() string {
+	return fmt.Sprint(e)
+}
+
+func (e *wrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) }
+
+func (e *wrapError) FormatError(p Printer) (next error) {
+	p.Print(e.msg)
+	e.frame.Format(p)
+	return e.err
+}
+
+func (e *wrapError) Unwrap() error {
+	return e.err
+}
diff --git a/fmt_test.go b/fmt_test.go
new file mode 100644
index 0000000..e524285
--- /dev/null
+++ b/fmt_test.go
@@ -0,0 +1,542 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors_test
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"path"
+	"reflect"
+	"regexp"
+	"strconv"
+	"strings"
+	"testing"
+
+	"golang.org/x/xerrors"
+)
+
+func TestErrorf(t *testing.T) {
+	chained := &wrapped{"chained", nil}
+	chain := func(s ...string) (a []string) {
+		for _, s := range s {
+			a = append(a, cleanPath(s))
+		}
+		return a
+	}
+	testCases := []struct {
+		got  error
+		want []string
+	}{{
+		xerrors.Errorf("no args"),
+		chain("no args/path.TestErrorf/path.go:xxx"),
+	}, {
+		xerrors.Errorf("no args: %s"),
+		chain("no args: %!s(MISSING)/path.TestErrorf/path.go:xxx"),
+	}, {
+		xerrors.Errorf("nounwrap: %s", "simple"),
+		chain(`nounwrap: simple/path.TestErrorf/path.go:xxx`),
+	}, {
+		xerrors.Errorf("nounwrap: %v", "simple"),
+		chain(`nounwrap: simple/path.TestErrorf/path.go:xxx`),
+	}, {
+		xerrors.Errorf("%s failed: %v", "foo", chained),
+		chain("foo failed/path.TestErrorf/path.go:xxx",
+			"chained/somefile.go:xxx"),
+	}, {
+		xerrors.Errorf("no wrap: %s", chained),
+		chain("no wrap/path.TestErrorf/path.go:xxx",
+			"chained/somefile.go:xxx"),
+	}, {
+		xerrors.Errorf("%s failed: %w", "foo", chained),
+		chain("wraps:foo failed/path.TestErrorf/path.go:xxx",
+			"chained/somefile.go:xxx"),
+	}, {
+		xerrors.Errorf("nowrapv: %v", chained),
+		chain("nowrapv/path.TestErrorf/path.go:xxx",
+			"chained/somefile.go:xxx"),
+	}, {
+		xerrors.Errorf("wrapw: %w", chained),
+		chain("wraps:wrapw/path.TestErrorf/path.go:xxx",
+			"chained/somefile.go:xxx"),
+	}, {
+		xerrors.Errorf("not wrapped: %+v", chained),
+		chain("not wrapped: chained: somefile.go:123/path.TestErrorf/path.go:xxx"),
+	}}
+	for i, tc := range testCases {
+		t.Run(strconv.Itoa(i)+"/"+path.Join(tc.want...), func(t *testing.T) {
+			got := errToParts(tc.got)
+			if !reflect.DeepEqual(got, tc.want) {
+				t.Errorf("Format:\n got: %#v\nwant: %#v", got, tc.want)
+			}
+
+			gotStr := tc.got.Error()
+			wantStr := fmt.Sprint(tc.got)
+			if gotStr != wantStr {
+				t.Errorf("Error:\n got: %#v\nwant: %#v", got, tc.want)
+			}
+		})
+	}
+}
+
+func TestErrorFormatter(t *testing.T) {
+	var (
+		simple   = &wrapped{"simple", nil}
+		elephant = &wrapped{
+			"can't adumbrate elephant",
+			detailed{},
+		}
+		nonascii = &wrapped{"café", nil}
+		newline  = &wrapped{"msg with\nnewline",
+			&wrapped{"and another\none", nil}}
+		fallback  = &wrapped{"fallback", os.ErrNotExist}
+		oldAndNew = &wrapped{"new style", formatError("old style")}
+		framed    = &withFrameAndMore{
+			frame: xerrors.Caller(0),
+		}
+		opaque = &wrapped{"outer",
+			xerrors.Opaque(&wrapped{"mid",
+				&wrapped{"inner", nil}})}
+	)
+	testCases := []struct {
+		err    error
+		fmt    string
+		want   string
+		regexp bool
+	}{{
+		err:  simple,
+		fmt:  "%s",
+		want: "simple",
+	}, {
+		err:  elephant,
+		fmt:  "%s",
+		want: "can't adumbrate elephant: out of peanuts",
+	}, {
+		err:  &wrapped{"a", &wrapped{"b", &wrapped{"c", nil}}},
+		fmt:  "%s",
+		want: "a: b: c",
+	}, {
+		err: simple,
+		fmt: "%+v",
+		want: "simple:" +
+			"\n    somefile.go:123",
+	}, {
+		err: elephant,
+		fmt: "%+v",
+		want: "can't adumbrate elephant:" +
+			"\n    somefile.go:123" +
+			"\n  - out of peanuts:" +
+			"\n    the elephant is on strike" +
+			"\n    and the 12 monkeys" +
+			"\n    are laughing",
+	}, {
+		err: framed,
+		fmt: "%+v",
+		want: "something:" +
+			"\n    golang.org/x/xerrors_test.TestErrorFormatter" +
+			"\n        .+/golang.org/x/xerrors/fmt_test.go:97" +
+			"\n    something more",
+		regexp: true,
+	}, {
+		err:  fmtTwice("Hello World!"),
+		fmt:  "%#v",
+		want: "2 times Hello World!",
+	}, {
+		err:  fallback,
+		fmt:  "%s",
+		want: "fallback: file does not exist",
+	}, {
+		err: fallback,
+		fmt: "%+v",
+		// Note: no colon after the last error, as there are no details.
+		want: "fallback:" +
+			"\n    somefile.go:123" +
+			"\n  - file does not exist",
+	}, {
+		err:  opaque,
+		fmt:  "%s",
+		want: "outer: mid: inner",
+	}, {
+		err: opaque,
+		fmt: "%+v",
+		want: "outer:" +
+			"\n    somefile.go:123" +
+			"\n  - mid:" +
+			"\n    somefile.go:123" +
+			"\n  - inner:" +
+			"\n    somefile.go:123",
+	}, {
+		err:  oldAndNew,
+		fmt:  "%v",
+		want: "new style: old style",
+	}, {
+		err:  oldAndNew,
+		fmt:  "%q",
+		want: `"new style: old style"`,
+	}, {
+		err: oldAndNew,
+		fmt: "%+v",
+		// Note the extra indentation.
+		// Colon for old style error is rendered by the fmt.Formatter
+		// implementation of the old-style error.
+		want: "new style:" +
+			"\n    somefile.go:123" +
+			"\n  - old style:" +
+			"\n    otherfile.go:456",
+	}, {
+		err:  simple,
+		fmt:  "%-12s",
+		want: "simple      ",
+	}, {
+		// Don't use formatting flags for detailed view.
+		err: simple,
+		fmt: "%+12v",
+		want: "simple:" +
+			"\n    somefile.go:123",
+	}, {
+		err:  elephant,
+		fmt:  "%+50s",
+		want: "          can't adumbrate elephant: out of peanuts",
+	}, {
+		err:  nonascii,
+		fmt:  "%q",
+		want: `"café"`,
+	}, {
+		err:  nonascii,
+		fmt:  "%+q",
+		want: `"caf\u00e9"`,
+	}, {
+		err:  simple,
+		fmt:  "% x",
+		want: "73 69 6d 70 6c 65",
+	}, {
+		err: newline,
+		fmt: "%s",
+		want: "msg with" +
+			"\nnewline: and another" +
+			"\none",
+	}, {
+		err: newline,
+		fmt: "%+v",
+		want: "msg with" +
+			"\n    newline:" +
+			"\n    somefile.go:123" +
+			"\n  - and another" +
+			"\n    one:" +
+			"\n    somefile.go:123",
+	}, {
+		err: &wrapped{"", &wrapped{"inner message", nil}},
+		fmt: "%+v",
+		want: "somefile.go:123" +
+			"\n  - inner message:" +
+			"\n    somefile.go:123",
+	}, {
+		err:  spurious(""),
+		fmt:  "%s",
+		want: "spurious",
+	}, {
+		err:  spurious(""),
+		fmt:  "%+v",
+		want: "spurious",
+	}, {
+		err:  spurious("extra"),
+		fmt:  "%s",
+		want: "spurious",
+	}, {
+		err: spurious("extra"),
+		fmt: "%+v",
+		want: "spurious:\n" +
+			"    extra",
+	}, {
+		err:  nil,
+		fmt:  "%+v",
+		want: "<nil>",
+	}, {
+		err:  (*wrapped)(nil),
+		fmt:  "%+v",
+		want: "<nil>",
+	}, {
+		err:  simple,
+		fmt:  "%T",
+		want: "*xerrors_test.wrapped",
+	}, {
+		err:  simple,
+		fmt:  "%🤪",
+		want: "%!🤪(*xerrors_test.wrapped)",
+		// For 1.13:
+		//  want: "%!🤪(*xerrors_test.wrapped=&{simple <nil>})",
+	}, {
+		err:  formatError("use fmt.Formatter"),
+		fmt:  "%#v",
+		want: "use fmt.Formatter",
+	}, {
+		err: fmtTwice("%s %s", "ok", panicValue{}),
+		fmt: "%s",
+		// Different Go versions produce different results.
+		want:   `ok %!s\(PANIC=(String method: )?panic\)/ok %!s\(PANIC=(String method: )?panic\)`,
+		regexp: true,
+	}, {
+		err:  fmtTwice("%o %s", panicValue{}, "ok"),
+		fmt:  "%s",
+		want: "{} ok/{} ok",
+	}, {
+		err: adapted{"adapted", nil},
+		fmt: "%+v",
+		want: "adapted:" +
+			"\n    detail",
+	}, {
+		err: adapted{"outer", adapted{"mid", adapted{"inner", nil}}},
+		fmt: "%+v",
+		want: "outer:" +
+			"\n    detail" +
+			"\n  - mid:" +
+			"\n    detail" +
+			"\n  - inner:" +
+			"\n    detail",
+	}}
+	for i, tc := range testCases {
+		t.Run(fmt.Sprintf("%d/%s", i, tc.fmt), func(t *testing.T) {
+			got := fmt.Sprintf(tc.fmt, tc.err)
+			var ok bool
+			if tc.regexp {
+				var err error
+				ok, err = regexp.MatchString(tc.want, got)
+				if err != nil {
+					t.Fatal(err)
+				}
+			} else {
+				ok = got == tc.want
+			}
+			if !ok {
+				t.Errorf("\n got: %q\nwant: %q", got, tc.want)
+			}
+		})
+	}
+}
+
+func TestAdaptor(t *testing.T) {
+	testCases := []struct {
+		err    error
+		fmt    string
+		want   string
+		regexp bool
+	}{{
+		err: adapted{"adapted", nil},
+		fmt: "%+v",
+		want: "adapted:" +
+			"\n    detail",
+	}, {
+		err: adapted{"outer", adapted{"mid", adapted{"inner", nil}}},
+		fmt: "%+v",
+		want: "outer:" +
+			"\n    detail" +
+			"\n  - mid:" +
+			"\n    detail" +
+			"\n  - inner:" +
+			"\n    detail",
+	}}
+	for i, tc := range testCases {
+		t.Run(fmt.Sprintf("%d/%s", i, tc.fmt), func(t *testing.T) {
+			got := fmt.Sprintf(tc.fmt, tc.err)
+			if got != tc.want {
+				t.Errorf("\n got: %q\nwant: %q", got, tc.want)
+			}
+		})
+	}
+}
+
+var _ xerrors.Formatter = wrapped{}
+
+type wrapped struct {
+	msg string
+	err error
+}
+
+func (e wrapped) Error() string { return "should call Format" }
+
+func (e wrapped) Format(s fmt.State, verb rune) {
+	xerrors.FormatError(&e, s, verb)
+}
+
+func (e wrapped) FormatError(p xerrors.Printer) (next error) {
+	p.Print(e.msg)
+	p.Detail()
+	p.Print("somefile.go:123")
+	return e.err
+}
+
+var _ xerrors.Formatter = detailed{}
+
+type detailed struct{}
+
+func (e detailed) Error() string { return fmt.Sprint(e) }
+
+func (detailed) FormatError(p xerrors.Printer) (next error) {
+	p.Printf("out of %s", "peanuts")
+	p.Detail()
+	p.Print("the elephant is on strike\n")
+	p.Printf("and the %d monkeys\nare laughing", 12)
+	return nil
+}
+
+type withFrameAndMore struct {
+	frame xerrors.Frame
+}
+
+func (e *withFrameAndMore) Error() string { return fmt.Sprint(e) }
+
+func (e *withFrameAndMore) Format(s fmt.State, v rune) {
+	xerrors.FormatError(e, s, v)
+}
+
+func (e *withFrameAndMore) FormatError(p xerrors.Printer) (next error) {
+	p.Print("something")
+	if p.Detail() {
+		e.frame.Format(p)
+		p.Print("something more")
+	}
+	return nil
+}
+
+type spurious string
+
+func (e spurious) Error() string { return fmt.Sprint(e) }
+
+// move to 1_12 test file
+func (e spurious) Format(s fmt.State, verb rune) {
+	xerrors.FormatError(e, s, verb)
+}
+
+func (e spurious) FormatError(p xerrors.Printer) (next error) {
+	p.Print("spurious")
+	p.Detail() // Call detail even if we don't print anything
+	if e == "" {
+		p.Print()
+	} else {
+		p.Print("\n", string(e)) // print extraneous leading newline
+	}
+	return nil
+}
+
+type adapted struct {
+	msg string
+	err error
+}
+
+func (e adapted) Error() string { return string(e.msg) }
+
+func (e adapted) Format(s fmt.State, verb rune) {
+	xerrors.FormatError(e, s, verb)
+}
+
+func (e adapted) FormatError(p xerrors.Printer) error {
+	p.Print(e.msg)
+	p.Detail()
+	p.Print("detail")
+	return e.err
+}
+
+// formatError is an error implementing Format instead of xerrors.Formatter.
+// The implementation mimics the implementation of github.com/pkg/errors.
+type formatError string
+
+func (e formatError) Error() string { return string(e) }
+
+func (e formatError) Format(s fmt.State, verb rune) {
+	// Body based on pkg/errors/errors.go
+	switch verb {
+	case 'v':
+		if s.Flag('+') {
+			io.WriteString(s, string(e))
+			fmt.Fprintf(s, ":\n%s", "otherfile.go:456")
+			return
+		}
+		fallthrough
+	case 's':
+		io.WriteString(s, string(e))
+	case 'q':
+		fmt.Fprintf(s, "%q", string(e))
+	}
+}
+
+func (e formatError) GoString() string {
+	panic("should never be called")
+}
+
+type fmtTwiceErr struct {
+	format string
+	args   []interface{}
+}
+
+func fmtTwice(format string, a ...interface{}) error {
+	return fmtTwiceErr{format, a}
+}
+
+func (e fmtTwiceErr) Error() string { return fmt.Sprint(e) }
+
+func (e fmtTwiceErr) Format(s fmt.State, verb rune) {
+	xerrors.FormatError(e, s, verb)
+}
+
+func (e fmtTwiceErr) FormatError(p xerrors.Printer) (next error) {
+	p.Printf(e.format, e.args...)
+	p.Print("/")
+	p.Printf(e.format, e.args...)
+	return nil
+}
+
+func (e fmtTwiceErr) GoString() string {
+	return "2 times " + fmt.Sprintf(e.format, e.args...)
+}
+
+type panicValue struct{}
+
+func (panicValue) String() string { panic("panic") }
+
+var rePath = regexp.MustCompile(`( [^ ]*)xerrors.*test\.`)
+var reLine = regexp.MustCompile(":[0-9]*\n?$")
+
+func cleanPath(s string) string {
+	s = rePath.ReplaceAllString(s, "/path.")
+	s = reLine.ReplaceAllString(s, ":xxx")
+	s = strings.Replace(s, "\n   ", "", -1)
+	s = strings.Replace(s, " /", "/", -1)
+	return s
+}
+
+func errToParts(err error) (a []string) {
+	for err != nil {
+		var p testPrinter
+		if xerrors.Unwrap(err) != nil {
+			p.str += "wraps:"
+		}
+		f, ok := err.(xerrors.Formatter)
+		if !ok {
+			a = append(a, err.Error())
+			break
+		}
+		err = f.FormatError(&p)
+		a = append(a, cleanPath(p.str))
+	}
+	return a
+
+}
+
+type testPrinter struct {
+	str string
+}
+
+func (p *testPrinter) Print(a ...interface{}) {
+	p.str += fmt.Sprint(a...)
+}
+
+func (p *testPrinter) Printf(format string, a ...interface{}) {
+	p.str += fmt.Sprintf(format, a...)
+}
+
+func (p *testPrinter) Detail() bool {
+	p.str += " /"
+	return true
+}
diff --git a/format.go b/format.go
new file mode 100644
index 0000000..1bc9c26
--- /dev/null
+++ b/format.go
@@ -0,0 +1,34 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors
+
+// A Formatter formats error messages.
+type Formatter interface {
+	error
+
+	// FormatError prints the receiver's first error and returns the next error in
+	// the error chain, if any.
+	FormatError(p Printer) (next error)
+}
+
+// A Printer formats error messages.
+//
+// The most common implementation of Printer is the one provided by package fmt
+// during Printf (as of Go 1.13). Localization packages such as golang.org/x/text/message
+// typically provide their own implementations.
+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
+}
diff --git a/frame.go b/frame.go
new file mode 100644
index 0000000..0de628e
--- /dev/null
+++ b/frame.go
@@ -0,0 +1,56 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors
+
+import (
+	"runtime"
+)
+
+// A Frame contains part of a call stack.
+type Frame struct {
+	// Make room for three PCs: the one we were asked for, what it called,
+	// and possibly a PC for skipPleaseUseCallersFrames. See:
+	// https://go.googlesource.com/go/+/032678e0fb/src/runtime/extern.go#169
+	frames [3]uintptr
+}
+
+// Caller returns a Frame that describes a frame on the caller's stack.
+// The argument skip is the number of frames to skip over.
+// Caller(0) returns the frame for the caller of Caller.
+func Caller(skip int) Frame {
+	var s Frame
+	runtime.Callers(skip+1, s.frames[:])
+	return s
+}
+
+// location reports the file, line, and function of a frame.
+//
+// The returned function may be "" even if file and line are not.
+func (f Frame) location() (function, file string, line int) {
+	frames := runtime.CallersFrames(f.frames[:])
+	if _, ok := frames.Next(); !ok {
+		return "", "", 0
+	}
+	fr, ok := frames.Next()
+	if !ok {
+		return "", "", 0
+	}
+	return fr.Function, fr.File, fr.Line
+}
+
+// Format prints the stack as error detail.
+// It should be called from an error's Format implementation
+// after printing any other error detail.
+func (f Frame) Format(p Printer) {
+	if p.Detail() {
+		function, file, line := f.location()
+		if function != "" {
+			p.Printf("%s\n    ", function)
+		}
+		if file != "" {
+			p.Printf("%s:%d\n", file, line)
+		}
+	}
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..eb71df3
--- /dev/null
+++ b/go.mod
@@ -0,0 +1 @@
+module golang.org/x/xerrors
diff --git a/internal/internal.go b/internal/internal.go
new file mode 100644
index 0000000..89f4eca
--- /dev/null
+++ b/internal/internal.go
@@ -0,0 +1,8 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+// EnableTrace indicates whether stack information should be recorded in errors.
+var EnableTrace = true
diff --git a/stack_test.go b/stack_test.go
new file mode 100644
index 0000000..e13f319
--- /dev/null
+++ b/stack_test.go
@@ -0,0 +1,60 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors_test
+
+import (
+	"bytes"
+	"fmt"
+	"math/big"
+	"testing"
+
+	"golang.org/x/xerrors"
+	"golang.org/x/xerrors/internal"
+)
+
+type myType struct{}
+
+func (myType) Format(s fmt.State, v rune) {
+	s.Write(bytes.Repeat([]byte("Hi! "), 10))
+}
+
+func BenchmarkErrorf(b *testing.B) {
+	err := xerrors.New("foo")
+	// pi := big.NewFloat(3.14) // Something expensive.
+	num := big.NewInt(5)
+	args := func(a ...interface{}) []interface{} { return a }
+	benchCases := []struct {
+		name   string
+		format string
+		args   []interface{}
+	}{
+		{"no_format", "msg: %v", args(err)},
+		{"with_format", "failed %d times: %v", args(5, err)},
+		{"method: mytype", "pi: %v", args("myfile.go", myType{}, err)},
+		{"method: number", "pi: %v", args("myfile.go", num, err)},
+	}
+	for _, bc := range benchCases {
+		b.Run(bc.name, func(b *testing.B) {
+			b.Run("ExpWithTrace", func(b *testing.B) {
+				for i := 0; i < b.N; i++ {
+					xerrors.Errorf(bc.format, bc.args...)
+				}
+			})
+			b.Run("ExpNoTrace", func(b *testing.B) {
+				internal.EnableTrace = false
+				defer func() { internal.EnableTrace = true }()
+
+				for i := 0; i < b.N; i++ {
+					xerrors.Errorf(bc.format, bc.args...)
+				}
+			})
+			b.Run("Core", func(b *testing.B) {
+				for i := 0; i < b.N; i++ {
+					fmt.Errorf(bc.format, bc.args...)
+				}
+			})
+		})
+	}
+}
diff --git a/wrap.go b/wrap.go
new file mode 100644
index 0000000..eee732b
--- /dev/null
+++ b/wrap.go
@@ -0,0 +1,98 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors
+
+import (
+	"reflect"
+)
+
+// A Wrapper provides context around another error.
+type Wrapper interface {
+	// Unwrap returns the next error in the error chain.
+	// If there is no next error, Unwrap returns nil.
+	Unwrap() error
+}
+
+// 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 {
+	return noWrapper{err}
+}
+
+type noWrapper struct {
+	error
+}
+
+func (e noWrapper) FormatError(p Printer) (next error) {
+	if f, ok := e.error.(Formatter); ok {
+		return f.FormatError(p)
+	}
+	p.Print(e.error)
+	return nil
+}
+
+// Unwrap returns the result of calling the Unwrap method on err, if err implements
+// Unwrap. Otherwise, Unwrap returns nil.
+func Unwrap(err error) error {
+	u, ok := err.(Wrapper)
+	if !ok {
+		return nil
+	}
+	return u.Unwrap()
+}
+
+// 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 {
+	if target == nil {
+		return err == target
+	}
+	for {
+		if 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
+		}
+	}
+}
+
+// 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 {
+	if target == nil {
+		panic("errors: target cannot be nil")
+	}
+	typ := reflect.TypeOf(target)
+	if typ.Kind() != reflect.Ptr {
+		panic("errors: target must be a pointer")
+	}
+	targetType := typ.Elem()
+	for {
+		if reflect.TypeOf(err) == targetType {
+			reflect.ValueOf(target).Elem().Set(reflect.ValueOf(err))
+			return true
+		}
+		if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) {
+			return true
+		}
+		if err = Unwrap(err); err == nil {
+			return false
+		}
+	}
+}
diff --git a/wrap_test.go b/wrap_test.go
new file mode 100644
index 0000000..677b209
--- /dev/null
+++ b/wrap_test.go
@@ -0,0 +1,202 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors_test
+
+import (
+	"fmt"
+	"os"
+	"testing"
+
+	"golang.org/x/xerrors"
+)
+
+func TestIs(t *testing.T) {
+	err1 := xerrors.New("1")
+	erra := xerrors.Errorf("wrap 2: %w", err1)
+	errb := xerrors.Errorf("wrap 3: %w", erra)
+	erro := xerrors.Opaque(err1)
+	errco := xerrors.Errorf("opaque: %w", erro)
+	err3 := xerrors.New("3")
+
+	poser := &poser{"either 1 or 3", func(err error) bool {
+		return err == err1 || err == err3
+	}}
+
+	testCases := []struct {
+		err    error
+		target error
+		match  bool
+	}{
+		{nil, nil, true},
+		{err1, nil, false},
+		{err1, err1, true},
+		{erra, err1, true},
+		{errb, err1, true},
+		{errco, erro, true},
+		{errco, err1, false},
+		{erro, erro, true},
+		{err1, err3, false},
+		{erra, err3, false},
+		{errb, err3, false},
+		{poser, err1, true},
+		{poser, err3, true},
+		{poser, erra, false},
+		{poser, errb, false},
+		{poser, erro, false},
+		{poser, errco, false},
+	}
+	for _, tc := range testCases {
+		t.Run("", func(t *testing.T) {
+			if got := xerrors.Is(tc.err, tc.target); got != tc.match {
+				t.Errorf("Is(%v, %v) = %v, want %v", tc.err, tc.target, got, tc.match)
+			}
+		})
+	}
+}
+
+type poser struct {
+	msg string
+	f   func(error) bool
+}
+
+func (p *poser) Error() string     { return p.msg }
+func (p *poser) Is(err error) bool { return p.f(err) }
+func (p *poser) As(err interface{}) bool {
+	switch x := err.(type) {
+	case **poser:
+		*x = p
+	case *errorT:
+		*x = errorT{}
+	case **os.PathError:
+		*x = &os.PathError{}
+	default:
+		return false
+	}
+	return true
+}
+
+func TestAs(t *testing.T) {
+	var errT errorT
+	var errP *os.PathError
+	var p *poser
+	_, errF := os.Open("non-existing")
+
+	testCases := []struct {
+		err    error
+		target interface{}
+		match  bool
+	}{{
+		xerrors.Errorf("pittied the fool: %w", errorT{}),
+		&errT,
+		true,
+	}, {
+		errF,
+		&errP,
+		true,
+	}, {
+		xerrors.Opaque(errT),
+		&errT,
+		false,
+	}, {
+		errorT{},
+		&errP,
+		false,
+	}, {
+		errWrap{nil},
+		&errT,
+		false,
+	}, {
+		&poser{"error", nil},
+		&errT,
+		true,
+	}, {
+		&poser{"path", nil},
+		&errP,
+		true,
+	}, {
+		&poser{"oh no", nil},
+		&p,
+		true,
+	}, {
+		&poser{"oo", nil},
+		&errF,
+		false,
+	}}
+	for _, tc := range testCases {
+		name := fmt.Sprintf("As(Errorf(..., %v), %v)", tc.err, tc.target)
+		t.Run(name, func(t *testing.T) {
+			match := xerrors.As(tc.err, tc.target)
+			if match != tc.match {
+				t.Fatalf("match: got %v; want %v", match, tc.match)
+			}
+			if !match {
+				return
+			}
+			if tc.target == nil {
+				t.Fatalf("non-nil result after match")
+			}
+		})
+	}
+}
+
+func TestUnwrap(t *testing.T) {
+	err1 := xerrors.New("1")
+	erra := xerrors.Errorf("wrap 2: %w", err1)
+	erro := xerrors.Opaque(err1)
+
+	testCases := []struct {
+		err  error
+		want error
+	}{
+		{nil, nil},
+		{errWrap{nil}, nil},
+		{err1, nil},
+		{erra, err1},
+		{xerrors.Errorf("wrap 3: %w", erra), erra},
+
+		{erro, nil},
+		{xerrors.Errorf("opaque: %w", erro), erro},
+	}
+	for _, tc := range testCases {
+		if got := xerrors.Unwrap(tc.err); got != tc.want {
+			t.Errorf("Unwrap(%v) = %v, want %v", tc.err, got, tc.want)
+		}
+	}
+}
+
+func TestOpaque(t *testing.T) {
+	got := fmt.Sprintf("%v", xerrors.Errorf("foo: %v", xerrors.Opaque(errorT{})))
+	want := "foo: errorT"
+	if got != want {
+		t.Errorf("error without Format: got %v; want %v", got, want)
+	}
+
+	got = fmt.Sprintf("%v", xerrors.Errorf("foo: %v", xerrors.Opaque(errorD{})))
+	want = "foo: errorD"
+	if got != want {
+		t.Errorf("error with Format: got %v; want %v", got, want)
+	}
+}
+
+type errorT struct{}
+
+func (errorT) Error() string { return "errorT" }
+
+type errorD struct{}
+
+func (errorD) Error() string { return "errorD" }
+
+func (errorD) FormatError(p xerrors.Printer) error {
+	p.Print("errorD")
+	p.Detail()
+	p.Print("detail")
+	return nil
+}
+
+type errWrap struct{ error }
+
+func (errWrap) Error() string { return "wrapped" }
+
+func (errWrap) Unwrap() error { return nil }