go/analysis/passes/stdmethods: recognize any as alias for interface{}, for errors.As check
Now that any is an alias for interface{}, we need to recognize both
func (T) As(any) bool
func (T) As(interface{}) bool
as satisfying errors.As.
For golang/go#33232.
Change-Id: Ie5a992c37da8020e80367528bc23370227a70f75
Reviewed-on: https://go-review.googlesource.com/c/tools/+/369954
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/go/analysis/passes/stdmethods/stdmethods.go b/go/analysis/passes/stdmethods/stdmethods.go
index 64a28ac..cc94971 100644
--- a/go/analysis/passes/stdmethods/stdmethods.go
+++ b/go/analysis/passes/stdmethods/stdmethods.go
@@ -61,7 +61,7 @@
// we let it go. But if it does have a fmt.ScanState, then the
// rest has to match.
var canonicalMethods = map[string]struct{ args, results []string }{
- "As": {[]string{"interface{}"}, []string{"bool"}}, // errors.As
+ "As": {[]string{"any"}, []string{"bool"}}, // errors.As
// "Flush": {{}, {"error"}}, // http.Flusher and jpeg.writer conflict
"Format": {[]string{"=fmt.State", "rune"}, []string{}}, // fmt.Formatter
"GobDecode": {[]string{"[]byte"}, []string{"error"}}, // gob.GobDecoder
@@ -194,7 +194,9 @@
func matchParamType(expect string, actual types.Type) bool {
expect = strings.TrimPrefix(expect, "=")
// Overkill but easy.
- return typeString(actual) == expect
+ t := typeString(actual)
+ return t == expect ||
+ (t == "any" || t == "interface{}") && (expect == "any" || expect == "interface{}")
}
var errorType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface)
diff --git a/go/analysis/passes/stdmethods/testdata/src/a/a.go b/go/analysis/passes/stdmethods/testdata/src/a/a.go
index 7f9e9ae..c95cf5d 100644
--- a/go/analysis/passes/stdmethods/testdata/src/a/a.go
+++ b/go/analysis/passes/stdmethods/testdata/src/a/a.go
@@ -47,7 +47,7 @@
func (E) Error() string { return "" } // E implements error.
-func (E) As() {} // want `method As\(\) should have signature As\(interface{}\) bool`
+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`
@@ -55,6 +55,10 @@
func (F) Error() string { return "" } // Both F and *F implement error.
-func (*F) As() {} // want `method As\(\) should have signature As\(interface{}\) bool`
+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`
+
+type G int
+
+func (G) As(interface{}) bool // ok
diff --git a/go/analysis/passes/stdmethods/testdata/src/a/b.go b/go/analysis/passes/stdmethods/testdata/src/a/b.go
new file mode 100644
index 0000000..c0a16fb
--- /dev/null
+++ b/go/analysis/passes/stdmethods/testdata/src/a/b.go
@@ -0,0 +1,12 @@
+// Copyright 2021 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.
+
+//go:build go1.18
+// +build go1.18
+
+package a
+
+type H int
+
+func (H) As(any) bool // ok
diff --git a/go/analysis/passes/stdmethods/testdata/src/typeparams/typeparams.go b/go/analysis/passes/stdmethods/testdata/src/typeparams/typeparams.go
index 8ff8b35..72df30d 100644
--- a/go/analysis/passes/stdmethods/testdata/src/typeparams/typeparams.go
+++ b/go/analysis/passes/stdmethods/testdata/src/typeparams/typeparams.go
@@ -28,7 +28,7 @@
func (E[_]) Error() string { return "" } // E implements error.
-func (E[P]) As() {} // want `method As\(\) should have signature As\(interface{}\) bool`
+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`
@@ -36,6 +36,6 @@
func (F[_]) Error() string { return "" } // Both F and *F implement error.
-func (*F[_]) As() {} // want `method As\(\) should have signature As\(interface{}\) bool`
+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`