Commit 1f90d081 authored by Marcel van Lohuizen's avatar Marcel van Lohuizen

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 <mpvl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDamien Neil <dneil@google.com>
parent 8bf18b56
...@@ -5,7 +5,10 @@ ...@@ -5,7 +5,10 @@
// Package errors implements functions to manipulate errors. // Package errors implements functions to manipulate errors.
package errors package errors
import "runtime" import (
"internal/errinternal"
"runtime"
)
// New returns an error that formats as the given text. // New returns an error that formats as the given text.
// //
...@@ -15,21 +18,33 @@ func New(text string) error { ...@@ -15,21 +18,33 @@ func New(text string) error {
// Inline call to errors.Callers to improve performance. // Inline call to errors.Callers to improve performance.
var s Frame var s Frame
runtime.Callers(2, s.frames[:]) 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. // errorString is a trivial implementation of error.
type errorString struct { type errorString struct {
s string s string
err error
frame Frame frame Frame
} }
func (e *errorString) Error() string { func (e *errorString) Error() string {
if e.err != nil {
return e.s + ": " + e.err.Error()
}
return e.s return e.s
} }
func (e *errorString) FormatError(p Printer) (next error) { func (e *errorString) FormatError(p Printer) (next error) {
p.Print(e.s) p.Print(e.s)
e.frame.Format(p) e.frame.Format(p)
return nil return e.err
} }
...@@ -6,6 +6,7 @@ package fmt ...@@ -6,6 +6,7 @@ package fmt
import ( import (
"errors" "errors"
"internal/errinternal"
"strings" "strings"
) )
...@@ -21,7 +22,7 @@ import ( ...@@ -21,7 +22,7 @@ import (
func Errorf(format string, a ...interface{}) error { func Errorf(format string, a ...interface{}) error {
err, wrap := lastError(format, a) err, wrap := lastError(format, a)
if err == nil { 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 // TODO: this is not entirely correct. The error value could be
...@@ -33,7 +34,7 @@ func Errorf(format string, a ...interface{}) error { ...@@ -33,7 +34,7 @@ func Errorf(format string, a ...interface{}) error {
if wrap { if wrap {
return &wrapError{msg, err, errors.Caller(1)} 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) { func lastError(format string, a []interface{}) (err error, wrap bool) {
......
...@@ -378,6 +378,21 @@ func TestErrorFormatter(t *testing.T) { ...@@ -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{} var _ errors.Formatter = wrapped{}
type wrapped struct { type wrapped struct {
......
...@@ -34,7 +34,7 @@ import ( ...@@ -34,7 +34,7 @@ import (
// //
var pkgDeps = map[string][]string{ var pkgDeps = map[string][]string{
// L0 is the lowest level, core, nearly unavoidable packages. // L0 is the lowest level, core, nearly unavoidable packages.
"errors": {"runtime", "internal/reflectlite"}, "errors": {"runtime", "internal/errinternal", "internal/reflectlite"},
"io": {"errors", "sync", "sync/atomic"}, "io": {"errors", "sync", "sync/atomic"},
"runtime": {"unsafe", "runtime/internal/atomic", "runtime/internal/sys", "runtime/internal/math", "internal/cpu", "internal/bytealg"}, "runtime": {"unsafe", "runtime/internal/atomic", "runtime/internal/sys", "runtime/internal/math", "internal/cpu", "internal/bytealg"},
"runtime/internal/sys": {}, "runtime/internal/sys": {},
...@@ -46,6 +46,7 @@ var pkgDeps = map[string][]string{ ...@@ -46,6 +46,7 @@ var pkgDeps = map[string][]string{
"unsafe": {}, "unsafe": {},
"internal/cpu": {}, "internal/cpu": {},
"internal/bytealg": {"unsafe", "internal/cpu"}, "internal/bytealg": {"unsafe", "internal/cpu"},
"internal/errinternal": {},
"internal/reflectlite": {"runtime", "unsafe"}, "internal/reflectlite": {"runtime", "unsafe"},
"L0": { "L0": {
...@@ -183,7 +184,7 @@ var pkgDeps = map[string][]string{ ...@@ -183,7 +184,7 @@ var pkgDeps = map[string][]string{
}, },
// Formatted I/O: few dependencies (L1) but we must add reflect and internal/fmtsort. // 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"}, "log": {"L1", "os", "fmt", "time"},
// Packages used by testing must be low-level (L2+fmt). // Packages used by testing must be low-level (L2+fmt).
......
// 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment