From 1f90d081391d4f5911960fd28d81d7ea5e554a8f Mon Sep 17 00:00:00 2001 From: Marcel van Lohuizen Date: Wed, 13 Mar 2019 16:25:02 +0100 Subject: [PATCH] fmt: make type of fmt.Errorf the same as that of errors.New This applies only for cases where %w is not used. The purpose of this change is to reduce test failures where tests depend on these two being the same type, as they previously were. Change-Id: I2dd28b93fe1d59f3cfbb4eb0875d1fb8ee699746 Reviewed-on: https://go-review.googlesource.com/c/go/+/167402 Run-TryBot: Marcel van Lohuizen TryBot-Result: Gobot Gobot Reviewed-by: Damien Neil --- src/errors/errors.go | 21 ++++++++++++++++++--- src/fmt/errors.go | 5 +++-- src/fmt/errors_test.go | 15 +++++++++++++++ src/go/build/deps_test.go | 5 +++-- src/internal/errinternal/errinternal.go | 9 +++++++++ 5 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 src/internal/errinternal/errinternal.go diff --git a/src/errors/errors.go b/src/errors/errors.go index ebb136cdd4..51175b13c8 100644 --- a/src/errors/errors.go +++ b/src/errors/errors.go @@ -5,7 +5,10 @@ // Package errors implements functions to manipulate errors. package errors -import "runtime" +import ( + "internal/errinternal" + "runtime" +) // New returns an error that formats as the given text. // @@ -15,21 +18,33 @@ func New(text string) error { // Inline call to errors.Callers to improve performance. var s Frame runtime.Callers(2, s.frames[:]) - return &errorString{text, s} + 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} + } } // errorString is a trivial implementation of error. type errorString struct { s string + err error frame Frame } 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 nil + return e.err } diff --git a/src/fmt/errors.go b/src/fmt/errors.go index 7506b6a20b..06416425c3 100644 --- a/src/fmt/errors.go +++ b/src/fmt/errors.go @@ -6,6 +6,7 @@ package fmt import ( "errors" + "internal/errinternal" "strings" ) @@ -21,7 +22,7 @@ import ( func Errorf(format string, a ...interface{}) error { err, wrap := lastError(format, a) if err == nil { - return &noWrapError{Sprintf(format, a...), nil, errors.Caller(1)} + return errinternal.NewError(Sprintf(format, a...), nil) } // TODO: this is not entirely correct. The error value could be @@ -33,7 +34,7 @@ func Errorf(format string, a ...interface{}) error { if wrap { return &wrapError{msg, err, errors.Caller(1)} } - return &noWrapError{msg, err, errors.Caller(1)} + return errinternal.NewError(msg, err) } func lastError(format string, a []interface{}) (err error, wrap bool) { diff --git a/src/fmt/errors_test.go b/src/fmt/errors_test.go index a3cd26ef3e..ed77709ea0 100644 --- a/src/fmt/errors_test.go +++ b/src/fmt/errors_test.go @@ -378,6 +378,21 @@ func TestErrorFormatter(t *testing.T) { } } +func TestSameType(t *testing.T) { + err0 := errors.New("inner") + want := fmt.Sprintf("%T", err0) + + err := fmt.Errorf("foo: %v", err0) + if got := fmt.Sprintf("%T", err); got != want { + t.Errorf("got %v; want %v", got, want) + } + + err = fmt.Errorf("foo %s", "bar") + if got := fmt.Sprintf("%T", err); got != want { + t.Errorf("got %v; want %v", got, want) + } +} + var _ errors.Formatter = wrapped{} type wrapped struct { diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index f9e5c4dec0..31a5d2741d 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -34,7 +34,7 @@ import ( // var pkgDeps = map[string][]string{ // L0 is the lowest level, core, nearly unavoidable packages. - "errors": {"runtime", "internal/reflectlite"}, + "errors": {"runtime", "internal/errinternal", "internal/reflectlite"}, "io": {"errors", "sync", "sync/atomic"}, "runtime": {"unsafe", "runtime/internal/atomic", "runtime/internal/sys", "runtime/internal/math", "internal/cpu", "internal/bytealg"}, "runtime/internal/sys": {}, @@ -46,6 +46,7 @@ var pkgDeps = map[string][]string{ "unsafe": {}, "internal/cpu": {}, "internal/bytealg": {"unsafe", "internal/cpu"}, + "internal/errinternal": {}, "internal/reflectlite": {"runtime", "unsafe"}, "L0": { @@ -183,7 +184,7 @@ var pkgDeps = map[string][]string{ }, // Formatted I/O: few dependencies (L1) but we must add reflect and internal/fmtsort. - "fmt": {"L1", "bytes", "strings", "os", "reflect", "internal/fmtsort"}, + "fmt": {"L1", "bytes", "strings", "os", "reflect", "internal/errinternal", "internal/fmtsort"}, "log": {"L1", "os", "fmt", "time"}, // Packages used by testing must be low-level (L2+fmt). diff --git a/src/internal/errinternal/errinternal.go b/src/internal/errinternal/errinternal.go new file mode 100644 index 0000000000..f484ac03e8 --- /dev/null +++ b/src/internal/errinternal/errinternal.go @@ -0,0 +1,9 @@ +// 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 errinternal + +// NewError creates a new error as created by errors.New, but with one +// additional stack frame depth. +var NewError func(msg string, err error) error -- 2.50.0