diff --git a/go/analysis/passes/sortslice/analyzer.go b/go/analysis/passes/sortslice/analyzer.go index 5eb957a188..f85837d66b 100644 --- a/go/analysis/passes/sortslice/analyzer.go +++ b/go/analysis/passes/sortslice/analyzer.go @@ -52,11 +52,20 @@ func run(pass *analysis.Pass) (interface{}, error) { arg := call.Args[0] typ := pass.TypesInfo.Types[arg].Type + + if tuple, ok := typ.(*types.Tuple); ok { + typ = tuple.At(0).Type() // special case for Slice(f(...)) + } + switch typ.Underlying().(type) { case *types.Slice, *types.Interface: return } + // Restore typ to the original type, we may unwrap the tuple above, + // typ might not be the type of arg. + typ = pass.TypesInfo.Types[arg].Type + var fixes []analysis.SuggestedFix switch v := typ.Underlying().(type) { case *types.Array: diff --git a/go/analysis/passes/sortslice/testdata/src/a/a.go b/go/analysis/passes/sortslice/testdata/src/a/a.go index bc6cc16e9f..c6aca8df13 100644 --- a/go/analysis/passes/sortslice/testdata/src/a/a.go +++ b/go/analysis/passes/sortslice/testdata/src/a/a.go @@ -6,8 +6,8 @@ import "sort" func IncorrectSort() { i := 5 sortFn := func(i, j int) bool { return false } - sort.Slice(i, sortFn) // want "sort.Slice's argument must be a slice; is called with int" - sort.SliceStable(i, sortFn) // want "sort.SliceStable's argument must be a slice; is called with int" + sort.Slice(i, sortFn) // want "sort.Slice's argument must be a slice; is called with int" + sort.SliceStable(i, sortFn) // want "sort.SliceStable's argument must be a slice; is called with int" sort.SliceIsSorted(i, sortFn) // want "sort.SliceIsSorted's argument must be a slice; is called with int" } @@ -62,3 +62,23 @@ func UnderlyingSlice() { sort.SliceStable(s, sortFn) sort.SliceIsSorted(s, sortFn) } + +// FunctionResultsAsArguments passes a function which returns two values +// that satisfy sort.Slice signature. It should not produce a diagnostic. +func FunctionResultsAsArguments() { + s := []string{"a", "z", "ooo"} + sort.Slice(less(s)) + sort.Slice(lessPtr(s)) // want `sort.Slice's argument must be a slice; is called with \(\*\[\]string,.*` +} + +func less(s []string) ([]string, func(i, j int) bool) { + return s, func(i, j int) bool { + return s[i] < s[j] + } +} + +func lessPtr(s []string) (*[]string, func(i, j int) bool) { + return &s, func(i, j int) bool { + return s[i] < s[j] + } +}