]> Cypherpunks repositories - gostls13.git/commitdiff
fmt: make type of fmt.Errorf the same as that of errors.New
authorMarcel van Lohuizen <mpvl@golang.org>
Wed, 13 Mar 2019 15:25:02 +0000 (16:25 +0100)
committerMarcel van Lohuizen <mpvl@golang.org>
Thu, 14 Mar 2019 09:45:22 +0000 (09:45 +0000)
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 <mpvl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
src/errors/errors.go
src/fmt/errors.go
src/fmt/errors_test.go
src/go/build/deps_test.go
src/internal/errinternal/errinternal.go [new file with mode: 0644]

index ebb136cdd452f77da26e2d3c2fdf315b54284131..51175b13c8710609f3b8ce7333e895ba654ecd5a 100644 (file)
@@ -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
 }
index 7506b6a20b41100577795306f491cedbaf8f03ca..06416425c3dac738de560054793596f074ccbc00 100644 (file)
@@ -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) {
index a3cd26ef3e3fd938a52ee6fb3a31f0568b824431..ed77709ea015f6ec1e1f9eae3a2cc73fc84a9c51 100644 (file)
@@ -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 {
index f9e5c4dec0faff3dfd2ab53d60e5afb3355484b3..31a5d2741d77f1851957e2acd04f3b2ad28317eb 100644 (file)
@@ -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 (file)
index 0000000..f484ac0
--- /dev/null
@@ -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