Commit 444039e0 authored by Damien Neil's avatar Damien Neil

fmt: fix %d and other non-string verbs on errors

When formatting an error with a non-string formatting verb such as %d,
use the default formatting behavior rather than treating this as a bad
verb.

For example, this should print 42, not %!d(main.E=42):

  var E int
  func (E) Error() string { return "error" }
  fmt.Printf("%d", E(42))

Fixes #30472

Change-Id: I62fd309c8ee9839a69052b0ec7f1808449dcee8e
Reviewed-on: https://go-review.googlesource.com/c/164557Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 72d24a74
...@@ -130,8 +130,7 @@ func fmtError(p *pp, verb rune, err error) (handled bool) { ...@@ -130,8 +130,7 @@ func fmtError(p *pp, verb rune, err error) (handled bool) {
w = newPrinter() w = newPrinter()
defer w.free() defer w.free()
default: default:
w.badVerb(verb) return false
return true
} }
} }
......
...@@ -327,7 +327,7 @@ func TestErrorFormatter(t *testing.T) { ...@@ -327,7 +327,7 @@ func TestErrorFormatter(t *testing.T) {
}, { }, {
err: &wrapped{"simple", nil}, err: &wrapped{"simple", nil},
fmt: "%🤪", fmt: "%🤪",
want: "%!🤪(*fmt_test.wrapped=&{simple <nil>})", want: "&{%!🤪(string=simple) <nil>}",
}, { }, {
err: formatError("use fmt.Formatter"), err: formatError("use fmt.Formatter"),
fmt: "%#v", fmt: "%#v",
...@@ -345,6 +345,14 @@ func TestErrorFormatter(t *testing.T) { ...@@ -345,6 +345,14 @@ func TestErrorFormatter(t *testing.T) {
err: fmtTwice("%o %s", panicValue{}, "ok"), err: fmtTwice("%o %s", panicValue{}, "ok"),
fmt: "%s", fmt: "%s",
want: "{} ok/{} ok", want: "{} ok/{} ok",
}, {
err: intError(4),
fmt: "%v",
want: "error 4",
}, {
err: intError(4),
fmt: "%d",
want: "4",
}} }}
for i, tc := range testCases { for i, tc := range testCases {
t.Run(fmt.Sprintf("%d/%s", i, tc.fmt), func(t *testing.T) { t.Run(fmt.Sprintf("%d/%s", i, tc.fmt), func(t *testing.T) {
...@@ -434,6 +442,15 @@ func (e detail) FormatError(p errors.Printer) (next error) { ...@@ -434,6 +442,15 @@ func (e detail) FormatError(p errors.Printer) (next error) {
return e.next return e.next
} }
type intError int
func (e intError) Error() string { return fmt.Sprint(e) }
func (e intError) FormatError(p errors.Printer) (next error) {
p.Printf("error %d", e)
return nil
}
// formatError is an error implementing Format instead of errors.Formatter. // formatError is an error implementing Format instead of errors.Formatter.
// The implementation mimics the implementation of github.com/pkg/errors. // The implementation mimics the implementation of github.com/pkg/errors.
type formatError string type formatError string
......
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