Skip to content

Commit

Permalink
go/analysis/passes/stdmethods: recognize Unwrap() []error
Browse files Browse the repository at this point in the history
Recognize the new multiple-error-wrapping method signature.

For golang/go#53435

Change-Id: Ifba25746323d036d1e6d3e6d3c34cd6ce904b60a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/432575
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Damien Neil <dneil@google.com>
Reviewed-by: Joseph Tsai <joetsai@digital-static.net>
  • Loading branch information
neild committed Sep 22, 2022
1 parent 62ae586 commit b3ab50b
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 4 deletions.
13 changes: 13 additions & 0 deletions go/analysis/passes/stdmethods/stdmethods.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,19 @@ func canonicalMethod(pass *analysis.Pass, id *ast.Ident) {
}
}

// Special case: Unwrap has two possible signatures.
// Check for Unwrap() []error here.
if id.Name == "Unwrap" {
if args.Len() == 0 && results.Len() == 1 {
t := typeString(results.At(0).Type())
if t == "error" || t == "[]error" {
return
}
}
pass.ReportRangef(id, "method Unwrap() should have signature Unwrap() error or Unwrap() []error")
return
}

// Do the =s (if any) all match?
if !matchParams(pass, expect.args, args, "=") || !matchParams(pass, expect.results, results, "=") {
return
Expand Down
14 changes: 12 additions & 2 deletions go/analysis/passes/stdmethods/testdata/src/a/a.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,26 @@ func (E) Error() string { return "" } // E implements error.

func (E) As() {} // want `method As\(\) should have signature As\((any|interface\{\})\) bool`
func (E) Is() {} // want `method Is\(\) should have signature Is\(error\) bool`
func (E) Unwrap() {} // want `method Unwrap\(\) should have signature Unwrap\(\) error`
func (E) Unwrap() {} // want `method Unwrap\(\) should have signature Unwrap\(\) error or Unwrap\(\) \[\]error`

type F int

func (F) Error() string { return "" } // Both F and *F implement error.

func (*F) As() {} // want `method As\(\) should have signature As\((any|interface\{\})\) bool`
func (*F) Is() {} // want `method Is\(\) should have signature Is\(error\) bool`
func (*F) Unwrap() {} // want `method Unwrap\(\) should have signature Unwrap\(\) error`
func (*F) Unwrap() {} // want `method Unwrap\(\) should have signature Unwrap\(\) error or Unwrap\(\) \[\]error`

type G int

func (G) As(interface{}) bool // ok

type W int

func (W) Error() string { return "" }
func (W) Unwrap() error { return nil } // ok

type M int

func (M) Error() string { return "" }
func (M) Unwrap() []error { return nil } // ok
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ func (E[_]) Error() string { return "" } // E implements error.

func (E[P]) As() {} // want `method As\(\) should have signature As\((any|interface\{\})\) bool`
func (E[_]) Is() {} // want `method Is\(\) should have signature Is\(error\) bool`
func (E[_]) Unwrap() {} // want `method Unwrap\(\) should have signature Unwrap\(\) error`
func (E[_]) Unwrap() {} // want `method Unwrap\(\) should have signature Unwrap\(\) error or Unwrap\(\) \[\]error`

type F[P any] int

func (F[_]) Error() string { return "" } // Both F and *F implement error.

func (*F[_]) As() {} // want `method As\(\) should have signature As\((any|interface\{\})\) bool`
func (*F[_]) Is() {} // want `method Is\(\) should have signature Is\(error\) bool`
func (*F[_]) Unwrap() {} // want `method Unwrap\(\) should have signature Unwrap\(\) error`
func (*F[_]) Unwrap() {} // want `method Unwrap\(\) should have signature Unwrap\(\) error or Unwrap\(\) \[\]error`

0 comments on commit b3ab50b

Please sign in to comment.