diff options
Diffstat (limited to 'src/errors')
| -rw-r--r-- | src/errors/errors.go | 34 | ||||
| -rw-r--r-- | src/errors/format.go | 34 | ||||
| -rw-r--r-- | src/errors/frame.go | 47 | ||||
| -rw-r--r-- | src/errors/frame_test.go | 66 | ||||
| -rw-r--r-- | src/errors/wrap.go | 29 | ||||
| -rw-r--r-- | src/errors/wrap_test.go | 61 |
6 files changed, 5 insertions, 266 deletions
diff --git a/src/errors/errors.go b/src/errors/errors.go index 51175b13c8..b8a46921be 100644 --- a/src/errors/errors.go +++ b/src/errors/errors.go @@ -5,46 +5,16 @@ // Package errors implements functions to manipulate errors. package errors -import ( - "internal/errinternal" - "runtime" -) - // 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 { - // Inline call to errors.Callers to improve performance. - var s Frame - runtime.Callers(2, s.frames[:]) - return &errorString{text, nil, s} -} - -func init() { - errinternal.NewError = func(text string, err error) error { - var s Frame - runtime.Callers(3, s.frames[:]) - return &errorString{text, err, s} - } + return &errorString{text} } // errorString is a trivial implementation of error. type errorString struct { - s string - err error - frame Frame + s string } func (e *errorString) Error() string { - if e.err != nil { - return e.s + ": " + e.err.Error() - } return e.s } - -func (e *errorString) FormatError(p Printer) (next error) { - p.Print(e.s) - e.frame.Format(p) - return e.err -} diff --git a/src/errors/format.go b/src/errors/format.go deleted file mode 100644 index 12deed3cf7..0000000000 --- a/src/errors/format.go +++ /dev/null @@ -1,34 +0,0 @@ -// 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 errors - -// 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. 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/src/errors/frame.go b/src/errors/frame.go deleted file mode 100644 index 487092fa89..0000000000 --- a/src/errors/frame.go +++ /dev/null @@ -1,47 +0,0 @@ -// 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 errors - -import ( - "runtime" -) - -// A Frame contains part of a call stack. -type Frame struct { - frames [1]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+2, 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[:]) - fr, _ := frames.Next() - return fr.Function, fr.File, fr.Line -} - -// Format prints the stack as error detail. -// It should be called from an error's Format implementation, -// before 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/src/errors/frame_test.go b/src/errors/frame_test.go deleted file mode 100644 index ba08166966..0000000000 --- a/src/errors/frame_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// 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 errors_test - -import ( - "bytes" - "errors" - "fmt" - "math/big" - "regexp" - "strings" - "testing" -) - -func TestFrame(t *testing.T) { - - // Extra line - got := fmt.Sprintf("%+v", errors.New("Test")) - got = got[strings.Index(got, "Test"):] - const want = "^Test:" + - "\n errors_test.TestFrame" + - "\n .*/errors/frame_test.go:20$" - ok, err := regexp.MatchString(want, got) - if err != nil { - t.Fatal(err) - } - if !ok { - t.Errorf("\n got %v;\nwant %v", got, want) - } -} - -type myType struct{} - -func (myType) Format(s fmt.State, v rune) { - s.Write(bytes.Repeat([]byte("Hi! "), 10)) -} - -func BenchmarkNew(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = errors.New("new error") - } -} - -func BenchmarkErrorf(b *testing.B) { - err := errors.New("foo") - 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 %s %v: %v", args("myfile.go", myType{}, err)}, - {"method: number", "pi %s %d: %v", args("myfile.go", big.NewInt(5), err)}, - } - for _, bc := range benchCases { - b.Run(bc.name, func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = fmt.Errorf(bc.format, bc.args...) - } - }) - } -} diff --git a/src/errors/wrap.go b/src/errors/wrap.go index b53caa6fc9..62332b1a88 100644 --- a/src/errors/wrap.go +++ b/src/errors/wrap.go @@ -8,35 +8,12 @@ import ( "internal/reflectlite" ) -// 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 Wrapper. Otherwise, Unwrap returns nil. func Unwrap(err error) error { - u, ok := err.(Wrapper) + u, ok := err.(interface { + Unwrap() error + }) if !ok { return nil } diff --git a/src/errors/wrap_test.go b/src/errors/wrap_test.go index f8e907cff7..2055316756 100644 --- a/src/errors/wrap_test.go +++ b/src/errors/wrap_test.go @@ -5,7 +5,6 @@ package errors_test import ( - "bytes" "errors" "fmt" "os" @@ -16,8 +15,6 @@ func TestIs(t *testing.T) { err1 := errors.New("1") erra := wrapped{"wrap 2", err1} errb := wrapped{"wrap 3", erra} - erro := errors.Opaque(err1) - errco := wrapped{"opaque", erro} err3 := errors.New("3") @@ -35,9 +32,6 @@ func TestIs(t *testing.T) { {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}, @@ -45,8 +39,6 @@ func TestIs(t *testing.T) { {poser, err3, true}, {poser, erra, false}, {poser, errb, false}, - {poser, erro, false}, - {poser, errco, false}, {errorUncomparable{}, errorUncomparable{}, true}, {errorUncomparable{}, &errorUncomparable{}, false}, {&errorUncomparable{}, errorUncomparable{}, true}, @@ -108,10 +100,6 @@ func TestAs(t *testing.T) { &errP, true, }, { - errors.Opaque(errT), - &errT, - false, - }, { errorT{}, &errP, false, @@ -187,7 +175,6 @@ func TestAsValidation(t *testing.T) { func TestUnwrap(t *testing.T) { err1 := errors.New("1") erra := wrapped{"wrap 2", err1} - erro := errors.Opaque(err1) testCases := []struct { err error @@ -198,9 +185,6 @@ func TestUnwrap(t *testing.T) { {err1, nil}, {erra, err1}, {wrapped{"wrap 3", erra}, erra}, - - {erro, nil}, - {wrapped{"opaque", erro}, erro}, } for _, tc := range testCases { if got := errors.Unwrap(tc.err); got != tc.want { @@ -209,39 +193,6 @@ func TestUnwrap(t *testing.T) { } } -func TestOpaque(t *testing.T) { - someError := errors.New("some error") - testCases := []struct { - err error - next error - }{ - {errorT{}, nil}, - {wrapped{"b", nil}, nil}, - {wrapped{"c", someError}, someError}, - } - for _, tc := range testCases { - t.Run("", func(t *testing.T) { - opaque := errors.Opaque(tc.err) - - f, ok := opaque.(errors.Formatter) - if !ok { - t.Fatal("Opaque error does not implement Formatter") - } - var p printer - next := f.FormatError(&p) - if next != tc.next { - t.Errorf("next was %v; want %v", next, tc.next) - } - if got, want := p.buf.String(), tc.err.Error(); got != want { - t.Errorf("error was %q; want %q", got, want) - } - if got := errors.Unwrap(opaque); got != nil { - t.Errorf("Unwrap returned non-nil error (%v)", got) - } - }) - } -} - type errorT struct{} func (errorT) Error() string { return "errorT" } @@ -255,18 +206,6 @@ func (e wrapped) Error() string { return e.msg } func (e wrapped) Unwrap() error { return e.err } -func (e wrapped) FormatError(p errors.Printer) error { - p.Print(e.msg) - return e.err -} - -type printer struct { - errors.Printer - buf bytes.Buffer -} - -func (p *printer) Print(args ...interface{}) { fmt.Fprint(&p.buf, args...) } - type errorUncomparable struct { f []string } |
