From 2a666afbb0a0f44a06053eeb0bd88a09990cb030 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Mar 2021 07:28:37 +0000 Subject: [PATCH] build(deps): bump honnef.co/go/tools from 0.1.1 to 0.1.3 Bumps [honnef.co/go/tools](https://github.com/dominikh/go-tools) from 0.1.1 to 0.1.3. - [Release notes](https://github.com/dominikh/go-tools/releases) - [Commits](https://github.com/dominikh/go-tools/compare/v0.1.1...v0.1.3) Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 +- vendor/honnef.co/go/tools/go/ir/exits.go | 13 + .../go/tools/lintcmd/version/version.go | 4 +- vendor/honnef.co/go/tools/pattern/match.go | 122 ++++--- vendor/honnef.co/go/tools/staticcheck/lint.go | 38 ++- vendor/honnef.co/go/tools/stylecheck/lint.go | 3 + .../go/tools/unused/typemap/identical.go | 149 ++++++++ .../honnef.co/go/tools/unused/typemap/map.go | 318 ++++++++++++++++++ vendor/honnef.co/go/tools/unused/unused.go | 38 +-- vendor/modules.txt | 3 +- 11 files changed, 600 insertions(+), 94 deletions(-) create mode 100644 vendor/honnef.co/go/tools/unused/typemap/identical.go create mode 100644 vendor/honnef.co/go/tools/unused/typemap/map.go diff --git a/go.mod b/go.mod index cab9c91ce..92d0d47e9 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( google.golang.org/grpc v1.35.0 google.golang.org/protobuf v1.25.0 gopkg.in/yaml.v2 v2.4.0 - honnef.co/go/tools v0.1.1 + honnef.co/go/tools v0.1.3 ) // Replace directives from github.com/cilium/cilium. Keep in sync when updating Cilium! diff --git a/go.sum b/go.sum index f6b05c24f..b92023a40 100644 --- a/go.sum +++ b/go.sum @@ -1246,8 +1246,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.1.1 h1:EVDuO03OCZwpV2t/tLLxPmPiomagMoBOgfPt0FM+4IY= -honnef.co/go/tools v0.1.1/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +honnef.co/go/tools v0.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8= k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= diff --git a/vendor/honnef.co/go/tools/go/ir/exits.go b/vendor/honnef.co/go/tools/go/ir/exits.go index 2166f74d6..0abf58089 100644 --- a/vendor/honnef.co/go/tools/go/ir/exits.go +++ b/vendor/honnef.co/go/tools/go/ir/exits.go @@ -58,6 +58,19 @@ func (b *builder) buildExits(fn *Function) { // via the first argument. We don't currently support // call-site-specific exit information. } + case "github.com/golang/glog": + switch obj.(*types.Func).FullName() { + case "github.com/golang/glog.Exit", + "github.com/golang/glog.ExitDepth", + "github.com/golang/glog.Exitf", + "github.com/golang/glog.Exitln", + "github.com/golang/glog.Fatal", + "github.com/golang/glog.FatalDepth", + "github.com/golang/glog.Fatalf", + "github.com/golang/glog.Fatalln": + // all of these call os.Exit after logging + fn.NoReturn = AlwaysExits + } } } diff --git a/vendor/honnef.co/go/tools/lintcmd/version/version.go b/vendor/honnef.co/go/tools/lintcmd/version/version.go index 8337c9e9a..aa99ecb90 100644 --- a/vendor/honnef.co/go/tools/lintcmd/version/version.go +++ b/vendor/honnef.co/go/tools/lintcmd/version/version.go @@ -7,8 +7,8 @@ import ( "runtime" ) -const Version = "2020.2.1" -const MachineVersion = "v0.1.1" +const Version = "2020.2.3" +const MachineVersion = "v0.1.3" // version returns a version descriptor and reports whether the // version is a known release. diff --git a/vendor/honnef.co/go/tools/pattern/match.go b/vendor/honnef.co/go/tools/pattern/match.go index 88c0818fb..ebbbdd469 100644 --- a/vendor/honnef.co/go/tools/pattern/match.go +++ b/vendor/honnef.co/go/tools/pattern/match.go @@ -9,52 +9,56 @@ import ( ) var tokensByString = map[string]Token{ - "INT": Token(token.INT), - "FLOAT": Token(token.FLOAT), - "IMAG": Token(token.IMAG), - "CHAR": Token(token.CHAR), - "STRING": Token(token.STRING), - "+": Token(token.ADD), - "-": Token(token.SUB), - "*": Token(token.MUL), - "/": Token(token.QUO), - "%": Token(token.REM), - "&": Token(token.AND), - "|": Token(token.OR), - "^": Token(token.XOR), - "<<": Token(token.SHL), - ">>": Token(token.SHR), - "&^": Token(token.AND_NOT), - "+=": Token(token.ADD_ASSIGN), - "-=": Token(token.SUB_ASSIGN), - "*=": Token(token.MUL_ASSIGN), - "/=": Token(token.QUO_ASSIGN), - "%=": Token(token.REM_ASSIGN), - "&=": Token(token.AND_ASSIGN), - "|=": Token(token.OR_ASSIGN), - "^=": Token(token.XOR_ASSIGN), - "<<=": Token(token.SHL_ASSIGN), - ">>=": Token(token.SHR_ASSIGN), - "&^=": Token(token.AND_NOT_ASSIGN), - "&&": Token(token.LAND), - "||": Token(token.LOR), - "<-": Token(token.ARROW), - "++": Token(token.INC), - "--": Token(token.DEC), - "==": Token(token.EQL), - "<": Token(token.LSS), - ">": Token(token.GTR), - "=": Token(token.ASSIGN), - "!": Token(token.NOT), - "!=": Token(token.NEQ), - "<=": Token(token.LEQ), - ">=": Token(token.GEQ), - ":=": Token(token.DEFINE), - "...": Token(token.ELLIPSIS), - "IMPORT": Token(token.IMPORT), - "VAR": Token(token.VAR), - "TYPE": Token(token.TYPE), - "CONST": Token(token.CONST), + "INT": Token(token.INT), + "FLOAT": Token(token.FLOAT), + "IMAG": Token(token.IMAG), + "CHAR": Token(token.CHAR), + "STRING": Token(token.STRING), + "+": Token(token.ADD), + "-": Token(token.SUB), + "*": Token(token.MUL), + "/": Token(token.QUO), + "%": Token(token.REM), + "&": Token(token.AND), + "|": Token(token.OR), + "^": Token(token.XOR), + "<<": Token(token.SHL), + ">>": Token(token.SHR), + "&^": Token(token.AND_NOT), + "+=": Token(token.ADD_ASSIGN), + "-=": Token(token.SUB_ASSIGN), + "*=": Token(token.MUL_ASSIGN), + "/=": Token(token.QUO_ASSIGN), + "%=": Token(token.REM_ASSIGN), + "&=": Token(token.AND_ASSIGN), + "|=": Token(token.OR_ASSIGN), + "^=": Token(token.XOR_ASSIGN), + "<<=": Token(token.SHL_ASSIGN), + ">>=": Token(token.SHR_ASSIGN), + "&^=": Token(token.AND_NOT_ASSIGN), + "&&": Token(token.LAND), + "||": Token(token.LOR), + "<-": Token(token.ARROW), + "++": Token(token.INC), + "--": Token(token.DEC), + "==": Token(token.EQL), + "<": Token(token.LSS), + ">": Token(token.GTR), + "=": Token(token.ASSIGN), + "!": Token(token.NOT), + "!=": Token(token.NEQ), + "<=": Token(token.LEQ), + ">=": Token(token.GEQ), + ":=": Token(token.DEFINE), + "...": Token(token.ELLIPSIS), + "IMPORT": Token(token.IMPORT), + "VAR": Token(token.VAR), + "TYPE": Token(token.TYPE), + "CONST": Token(token.CONST), + "BREAK": Token(token.BREAK), + "CONTINUE": Token(token.CONTINUE), + "GOTO": Token(token.GOTO), + "FALLTHROUGH": Token(token.FALLTHROUGH), } func maybeToken(node Node) (Node, bool) { @@ -438,26 +442,28 @@ func (tok Token) Match(m *Matcher, node interface{}) (interface{}, bool) { } func (Nil) Match(m *Matcher, node interface{}) (interface{}, bool) { - return nil, isNil(node) + return nil, isNil(node) || reflect.ValueOf(node).IsNil() } func (builtin Builtin) Match(m *Matcher, node interface{}) (interface{}, bool) { - ident, ok := node.(*ast.Ident) + r, ok := match(m, Ident(builtin), node) if !ok { return nil, false } + ident := r.(*ast.Ident) obj := m.TypesInfo.ObjectOf(ident) if obj != types.Universe.Lookup(ident.Name) { return nil, false } - return match(m, builtin.Name, ident.Name) + return ident, true } func (obj Object) Match(m *Matcher, node interface{}) (interface{}, bool) { - ident, ok := node.(*ast.Ident) + r, ok := match(m, Ident(obj), node) if !ok { return nil, false } + ident := r.(*ast.Ident) id := m.TypesInfo.ObjectOf(ident) _, ok = match(m, obj.Name, ident.Name) @@ -467,9 +473,15 @@ func (obj Object) Match(m *Matcher, node interface{}) (interface{}, bool) { func (fn Function) Match(m *Matcher, node interface{}) (interface{}, bool) { var name string var obj types.Object - switch node := node.(type) { + + r, ok := match(m, Or{Nodes: []Node{Ident{Any{}}, SelectorExpr{Any{}, Any{}}}}, node) + if !ok { + return nil, false + } + + switch r := r.(type) { case *ast.Ident: - obj = m.TypesInfo.ObjectOf(node) + obj = m.TypesInfo.ObjectOf(r) switch obj := obj.(type) { case *types.Func: // OPT(dh): optimize this similar to code.FuncName @@ -481,16 +493,16 @@ func (fn Function) Match(m *Matcher, node interface{}) (interface{}, bool) { } case *ast.SelectorExpr: var ok bool - obj, ok = m.TypesInfo.ObjectOf(node.Sel).(*types.Func) + obj, ok = m.TypesInfo.ObjectOf(r.Sel).(*types.Func) if !ok { return nil, false } // OPT(dh): optimize this similar to code.FuncName name = obj.(*types.Func).FullName() default: - return nil, false + panic("unreachable") } - _, ok := match(m, fn.Name, name) + _, ok = match(m, fn.Name, name) return obj, ok } diff --git a/vendor/honnef.co/go/tools/staticcheck/lint.go b/vendor/honnef.co/go/tools/staticcheck/lint.go index 0dec8f26c..35360c679 100644 --- a/vendor/honnef.co/go/tools/staticcheck/lint.go +++ b/vendor/honnef.co/go/tools/staticcheck/lint.go @@ -1384,6 +1384,13 @@ func CheckUnsafePrintf(pass *analysis.Pass) (interface{}, error) { return } + if _, ok := pass.TypesInfo.TypeOf(call.Args[arg]).(*types.Tuple); ok { + // the called function returns multiple values and got + // splatted into the call. for all we know, it is + // returning good arguments. + return + } + alt := name[:len(name)-1] report.Report(pass, call, "printf-style function with dynamic format string and no further arguments should use print-style function instead", @@ -2807,19 +2814,13 @@ func isIota(obj types.Object) bool { func CheckNonOctalFileMode(pass *analysis.Pass) (interface{}, error) { fn := func(node ast.Node) { call := node.(*ast.CallExpr) - sig, ok := pass.TypesInfo.TypeOf(call.Fun).(*types.Signature) - if !ok { - return - } - n := sig.Params().Len() - for i := 0; i < n; i++ { - typ := sig.Params().At(i).Type() - if !typeutil.IsType(typ, "os.FileMode") { + for _, arg := range call.Args { + lit, ok := arg.(*ast.BasicLit) + if !ok { continue } - - lit, ok := call.Args[i].(*ast.BasicLit) - if !ok { + if !typeutil.IsType(pass.TypesInfo.TypeOf(lit), "os.FileMode") && + !typeutil.IsType(pass.TypesInfo.TypeOf(lit), "io/fs.FileMode") { continue } if len(lit.Value) == 3 && @@ -2832,8 +2833,8 @@ func CheckNonOctalFileMode(pass *analysis.Pass) (interface{}, error) { if err != nil { continue } - report.Report(pass, call.Args[i], fmt.Sprintf("file mode '%s' evaluates to %#o; did you mean '0%s'?", lit.Value, v, lit.Value), - report.Fixes(edit.Fix("fix octal literal", edit.ReplaceWithString(pass.Fset, call.Args[i], "0"+lit.Value)))) + report.Report(pass, arg, fmt.Sprintf("file mode '%s' evaluates to %#o; did you mean '0%s'?", lit.Value, v, lit.Value), + report.Fixes(edit.Fix("fix octal literal", edit.ReplaceWithString(pass.Fset, arg, "0"+lit.Value)))) } } } @@ -3068,7 +3069,16 @@ func checkCalls(pass *analysis.Pass, rules map[string]CallCheck) (interface{}, e for idx, arg := range call.Args { for _, e := range arg.invalids { if astcall != nil { - report.Report(pass, astcall.Args[idx], e) + if idx < len(astcall.Args) { + report.Report(pass, astcall.Args[idx], e) + } else { + // this is an instance of fn1(fn2()) where fn2 + // returns multiple values. Report the error + // at the next-best position that we have, the + // first argument. An example of a check that + // triggers this is checkEncodingBinaryRules. + report.Report(pass, astcall.Args[0], e) + } } else { report.Report(pass, site, e) } diff --git a/vendor/honnef.co/go/tools/stylecheck/lint.go b/vendor/honnef.co/go/tools/stylecheck/lint.go index 8ed7ad5af..2ac5a9651 100644 --- a/vendor/honnef.co/go/tools/stylecheck/lint.go +++ b/vendor/honnef.co/go/tools/stylecheck/lint.go @@ -608,6 +608,9 @@ func CheckHTTPStatusCodes(pass *analysis.Pass) (interface{}, error) { default: return } + if arg >= len(call.Args) { + return + } lit, ok := call.Args[arg].(*ast.BasicLit) if !ok { return diff --git a/vendor/honnef.co/go/tools/unused/typemap/identical.go b/vendor/honnef.co/go/tools/unused/typemap/identical.go new file mode 100644 index 000000000..248f3e17b --- /dev/null +++ b/vendor/honnef.co/go/tools/unused/typemap/identical.go @@ -0,0 +1,149 @@ +package typemap + +import ( + "go/types" +) + +// Unlike types.Identical, receivers of Signature types are not ignored. +// Unlike types.Identical, interfaces are compared via pointer equality (except for the empty interface, which gets deduplicated). +// Unlike types.Identical, structs are compared via pointer equality. +func identical0(x, y types.Type) bool { + if x == y { + return true + } + + switch x := x.(type) { + case *types.Basic: + // Basic types are singletons except for the rune and byte + // aliases, thus we cannot solely rely on the x == y check + // above. See also comment in TypeName.IsAlias. + if y, ok := y.(*types.Basic); ok { + return x.Kind() == y.Kind() + } + + case *types.Array: + // Two array types are identical if they have identical element types + // and the same array length. + if y, ok := y.(*types.Array); ok { + // If one or both array lengths are unknown (< 0) due to some error, + // assume they are the same to avoid spurious follow-on errors. + return (x.Len() < 0 || y.Len() < 0 || x.Len() == y.Len()) && identical0(x.Elem(), y.Elem()) + } + + case *types.Slice: + // Two slice types are identical if they have identical element types. + if y, ok := y.(*types.Slice); ok { + return identical0(x.Elem(), y.Elem()) + } + + case *types.Struct: + if y, ok := y.(*types.Struct); ok { + return x == y + } + + case *types.Pointer: + // Two pointer types are identical if they have identical base types. + if y, ok := y.(*types.Pointer); ok { + return identical0(x.Elem(), y.Elem()) + } + + case *types.Tuple: + // Two tuples types are identical if they have the same number of elements + // and corresponding elements have identical types. + if y, ok := y.(*types.Tuple); ok { + if x.Len() == y.Len() { + if x != nil { + for i := 0; i < x.Len(); i++ { + v := x.At(i) + w := y.At(i) + if !identical0(v.Type(), w.Type()) { + return false + } + } + } + return true + } + } + + case *types.Signature: + // Two function types are identical if they have the same number of parameters + // and result values, corresponding parameter and result types are identical, + // and either both functions are variadic or neither is. Parameter and result + // names are not required to match. + if y, ok := y.(*types.Signature); ok { + + return x.Variadic() == y.Variadic() && + identical0(x.Params(), y.Params()) && + identical0(x.Results(), y.Results()) && + (x.Recv() != nil && y.Recv() != nil && identical0(x.Recv().Type(), y.Recv().Type()) || x.Recv() == nil && y.Recv() == nil) + } + + case *types.Interface: + // The issue with interfaces, typeutil.Map and types.Identical + // + // types.Identical, when comparing two interfaces, only looks at the set + // of all methods, not differentiating between implicit (embedded) and + // explicit methods. + // + // When we see the following two types, in source order + // + // type I1 interface { foo() } + // type I2 interface { I1 } + // + // then we will first correctly process I1 and its underlying type. When + // we get to I2, we will see that its underlying type is identical to + // that of I1 and not process it again. This, however, means that we will + // not record the fact that I2 embeds I1. If only I2 is reachable via the + // graph root, then I1 will not be considered used. + // + // We choose to be lazy and compare interfaces by their + // pointers. This will obviously miss identical interfaces, + // but this only has a runtime cost, it doesn't affect + // correctness. + if y, ok := y.(*types.Interface); ok { + if x.NumEmbeddeds() == 0 && + y.NumEmbeddeds() == 0 && + x.NumMethods() == 0 && + y.NumMethods() == 0 { + // all truly empty interfaces are the same + return true + } + return x == y + } + + case *types.Map: + // Two map types are identical if they have identical key and value types. + if y, ok := y.(*types.Map); ok { + return identical0(x.Key(), y.Key()) && identical0(x.Elem(), y.Elem()) + } + + case *types.Chan: + // Two channel types are identical if they have identical value types + // and the same direction. + if y, ok := y.(*types.Chan); ok { + return x.Dir() == y.Dir() && identical0(x.Elem(), y.Elem()) + } + + case *types.Named: + // Two named types are identical if their type names originate + // in the same type declaration. + if y, ok := y.(*types.Named); ok { + return x.Obj() == y.Obj() + } + + case nil: + + default: + panic("unreachable") + } + + return false +} + +// Identical reports whether x and y are identical types. +// Unlike types.Identical, receivers of Signature types are not ignored. +// Unlike types.Identical, interfaces are compared via pointer equality (except for the empty interface, which gets deduplicated). +// Unlike types.Identical, structs are compared via pointer equality. +func Identical(x, y types.Type) (ret bool) { + return identical0(x, y) +} diff --git a/vendor/honnef.co/go/tools/unused/typemap/map.go b/vendor/honnef.co/go/tools/unused/typemap/map.go new file mode 100644 index 000000000..d9961cab1 --- /dev/null +++ b/vendor/honnef.co/go/tools/unused/typemap/map.go @@ -0,0 +1,318 @@ +// Copyright 2014 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 typemap defines Map, a mapping from types.Type to interface{} values. +package typemap + +import ( + "bytes" + "fmt" + "go/types" + "reflect" +) + +// Map is a hash-table-based mapping from types (types.Type) to +// arbitrary interface{} values. The concrete types that implement +// the Type interface are pointers. Since they are not canonicalized, +// == cannot be used to check for equivalence, and thus we cannot +// simply use a Go map. +// +// Just as with map[K]V, a nil *Map is a valid empty map. +// +// Not thread-safe. +// +// This fork handles Signatures correctly, respecting method +// receivers. Furthermore, it doesn't deduplicate interfaces or +// structs. Interfaces aren't deduplicated as not to conflate implicit +// and explicit methods. Structs aren't deduplicated because we track +// fields of each type separately. +// +type Map struct { + hasher Hasher // shared by many Maps + table map[uint32][]entry // maps hash to bucket; entry.key==nil means unused + length int // number of map entries +} + +// entry is an entry (key/value association) in a hash bucket. +type entry struct { + key types.Type + value interface{} +} + +// SetHasher sets the hasher used by Map. +// +// All Hashers are functionally equivalent but contain internal state +// used to cache the results of hashing previously seen types. +// +// A single Hasher created by MakeHasher() may be shared among many +// Maps. This is recommended if the instances have many keys in +// common, as it will amortize the cost of hash computation. +// +// A Hasher may grow without bound as new types are seen. Even when a +// type is deleted from the map, the Hasher never shrinks, since other +// types in the map may reference the deleted type indirectly. +// +// Hashers are not thread-safe, and read-only operations such as +// Map.Lookup require updates to the hasher, so a full Mutex lock (not a +// read-lock) is require around all Map operations if a shared +// hasher is accessed from multiple threads. +// +// If SetHasher is not called, the Map will create a private hasher at +// the first call to Insert. +// +func (m *Map) SetHasher(hasher Hasher) { + m.hasher = hasher +} + +// Delete removes the entry with the given key, if any. +// It returns true if the entry was found. +// +func (m *Map) Delete(key types.Type) bool { + if m != nil && m.table != nil { + hash := m.hasher.Hash(key) + bucket := m.table[hash] + for i, e := range bucket { + if e.key != nil && Identical(key, e.key) { + // We can't compact the bucket as it + // would disturb iterators. + bucket[i] = entry{} + m.length-- + return true + } + } + } + return false +} + +// At returns the map entry for the given key. +// The result is nil if the entry is not present. +// +func (m *Map) At(key types.Type) interface{} { + if m != nil && m.table != nil { + for _, e := range m.table[m.hasher.Hash(key)] { + if e.key != nil && Identical(key, e.key) { + return e.value + } + } + } + return nil +} + +// Set sets the map entry for key to val, +// and returns the previous entry, if any. +func (m *Map) Set(key types.Type, value interface{}) (prev interface{}) { + if m.table != nil { + hash := m.hasher.Hash(key) + bucket := m.table[hash] + var hole *entry + for i, e := range bucket { + if e.key == nil { + hole = &bucket[i] + } else if Identical(key, e.key) { + prev = e.value + bucket[i].value = value + return + } + } + + if hole != nil { + *hole = entry{key, value} // overwrite deleted entry + } else { + m.table[hash] = append(bucket, entry{key, value}) + } + } else { + if m.hasher.memo == nil { + m.hasher = MakeHasher() + } + hash := m.hasher.Hash(key) + m.table = map[uint32][]entry{hash: {entry{key, value}}} + } + + m.length++ + return +} + +// Len returns the number of map entries. +func (m *Map) Len() int { + if m != nil { + return m.length + } + return 0 +} + +// Iterate calls function f on each entry in the map in unspecified order. +// +// If f should mutate the map, Iterate provides the same guarantees as +// Go maps: if f deletes a map entry that Iterate has not yet reached, +// f will not be invoked for it, but if f inserts a map entry that +// Iterate has not yet reached, whether or not f will be invoked for +// it is unspecified. +// +func (m *Map) Iterate(f func(key types.Type, value interface{})) { + if m != nil { + for _, bucket := range m.table { + for _, e := range bucket { + if e.key != nil { + f(e.key, e.value) + } + } + } + } +} + +// Keys returns a new slice containing the set of map keys. +// The order is unspecified. +func (m *Map) Keys() []types.Type { + keys := make([]types.Type, 0, m.Len()) + m.Iterate(func(key types.Type, _ interface{}) { + keys = append(keys, key) + }) + return keys +} + +func (m *Map) toString(values bool) string { + if m == nil { + return "{}" + } + var buf bytes.Buffer + fmt.Fprint(&buf, "{") + sep := "" + m.Iterate(func(key types.Type, value interface{}) { + fmt.Fprint(&buf, sep) + sep = ", " + fmt.Fprint(&buf, key) + if values { + fmt.Fprintf(&buf, ": %q", value) + } + }) + fmt.Fprint(&buf, "}") + return buf.String() +} + +// String returns a string representation of the map's entries. +// Values are printed using fmt.Sprintf("%v", v). +// Order is unspecified. +// +func (m *Map) String() string { + return m.toString(true) +} + +// KeysString returns a string representation of the map's key set. +// Order is unspecified. +// +func (m *Map) KeysString() string { + return m.toString(false) +} + +//////////////////////////////////////////////////////////////////////// +// Hasher + +// A Hasher maps each type to its hash value. +// For efficiency, a hasher uses memoization; thus its memory +// footprint grows monotonically over time. +// Hashers are not thread-safe. +// Hashers have reference semantics. +// Call MakeHasher to create a Hasher. +type Hasher struct { + memo map[types.Type]uint32 +} + +// MakeHasher returns a new Hasher instance. +func MakeHasher() Hasher { + return Hasher{make(map[types.Type]uint32)} +} + +// Hash computes a hash value for the given type t such that +// Identical(t, t') => Hash(t) == Hash(t'). +func (h Hasher) Hash(t types.Type) uint32 { + hash, ok := h.memo[t] + if !ok { + hash = h.hashFor(t) + h.memo[t] = hash + } + return hash +} + +// hashString computes the Fowler–Noll–Vo hash of s. +func hashString(s string) uint32 { + var h uint32 + for i := 0; i < len(s); i++ { + h ^= uint32(s[i]) + h *= 16777619 + } + return h +} + +// hashFor computes the hash of t. +func (h Hasher) hashFor(t types.Type) uint32 { + // See Identical for rationale. + switch t := t.(type) { + case *types.Basic: + return uint32(t.Kind()) + + case *types.Array: + return 9043 + 2*uint32(t.Len()) + 3*h.Hash(t.Elem()) + + case *types.Slice: + return 9049 + 2*h.Hash(t.Elem()) + + case *types.Struct: + var hash uint32 = 9059 + for i, n := 0, t.NumFields(); i < n; i++ { + f := t.Field(i) + if f.Anonymous() { + hash += 8861 + } + hash += hashString(t.Tag(i)) + hash += hashString(f.Name()) // (ignore f.Pkg) + hash += h.Hash(f.Type()) + } + return hash + + case *types.Pointer: + return 9067 + 2*h.Hash(t.Elem()) + + case *types.Signature: + var hash uint32 = 9091 + if t.Variadic() { + hash *= 8863 + } + return hash + 3*h.hashTuple(t.Params()) + 5*h.hashTuple(t.Results()) + + case *types.Interface: + var hash uint32 = 9103 + for i, n := 0, t.NumMethods(); i < n; i++ { + // See go/types.identicalMethods for rationale. + // Method order is not significant. + // Ignore m.Pkg(). + m := t.Method(i) + hash += 3*hashString(m.Name()) + 5*h.Hash(m.Type()) + } + return hash + + case *types.Map: + return 9109 + 2*h.Hash(t.Key()) + 3*h.Hash(t.Elem()) + + case *types.Chan: + return 9127 + 2*uint32(t.Dir()) + 3*h.Hash(t.Elem()) + + case *types.Named: + // Not safe with a copying GC; objects may move. + return uint32(reflect.ValueOf(t.Obj()).Pointer()) + + case *types.Tuple: + return h.hashTuple(t) + } + panic(t) +} + +func (h Hasher) hashTuple(tuple *types.Tuple) uint32 { + // See go/types.identicalTypes for rationale. + n := tuple.Len() + var hash uint32 = 9137 + 2*uint32(n) + for i := 0; i < n; i++ { + hash += 3 * h.Hash(tuple.At(i).Type()) + } + return hash +} diff --git a/vendor/honnef.co/go/tools/unused/unused.go b/vendor/honnef.co/go/tools/unused/unused.go index 797697719..b1312beff 100644 --- a/vendor/honnef.co/go/tools/unused/unused.go +++ b/vendor/honnef.co/go/tools/unused/unused.go @@ -17,6 +17,7 @@ import ( "honnef.co/go/tools/go/ir" "honnef.co/go/tools/go/types/typeutil" "honnef.co/go/tools/internal/passes/buildir" + "honnef.co/go/tools/unused/typemap" "golang.org/x/tools/go/analysis" ) @@ -542,9 +543,9 @@ func run(pass *analysis.Pass) (interface{}, error) { for _, v := range g.Nodes { debugNode(v) } - for _, node := range g.TypeNodes { - debugNode(node) - } + g.TypeNodes.Iterate(func(key types.Type, value interface{}) { + debugNode(value.(*node)) + }) debugf("}\n") } @@ -554,9 +555,10 @@ func run(pass *analysis.Pass) (interface{}, error) { func results(g *graph) (used, unused []types.Object) { g.color(g.Root) - for _, node := range g.TypeNodes { + g.TypeNodes.Iterate(func(_ types.Type, value interface{}) { + node := value.(*node) if node.seen { - continue + return } switch obj := node.obj.(type) { case *types.Struct: @@ -573,7 +575,7 @@ func results(g *graph) (used, unused []types.Object) { } } } - } + }) // OPT(dh): can we find meaningful initial capacities for the used and unused slices? @@ -609,9 +611,9 @@ func results(g *graph) (used, unused []types.Object) { type graph struct { Root *node - seenTypes map[types.Type]struct{} + seenTypes typemap.Map - TypeNodes map[types.Type]*node + TypeNodes typemap.Map Nodes map[interface{}]*node // context @@ -622,10 +624,8 @@ type graph struct { func newGraph() *graph { g := &graph{ - Nodes: map[interface{}]*node{}, - seenFns: map[*ir.Function]struct{}{}, - seenTypes: map[types.Type]struct{}{}, - TypeNodes: map[types.Type]*node{}, + Nodes: map[interface{}]*node{}, + seenFns: map[*ir.Function]struct{}{}, } g.Root = g.newNode(nil) return g @@ -676,11 +676,11 @@ func (g *graph) nodeMaybe(obj types.Object) (*node, bool) { func (g *graph) node(obj interface{}) (n *node, new bool) { switch obj := obj.(type) { case types.Type: - if v := g.TypeNodes[obj]; v != nil { - return v, false + if v := g.TypeNodes.At(obj); v != nil { + return v.(*node), false } n = g.newNode(obj) - g.TypeNodes[obj] = n + g.TypeNodes.Set(obj, n) return n, true case types.Object: // OPT(dh): the types.Object and default cases are identical @@ -1120,7 +1120,7 @@ func (g *graph) entry(pkg *pkg) { var ifaces []*types.Interface var notIfaces []types.Type - for t := range g.seenTypes { + g.seenTypes.Iterate(func(t types.Type, _ interface{}) { switch t := t.(type) { case *types.Interface: // OPT(dh): (8.1) we only need interfaces that have unexported methods @@ -1130,7 +1130,7 @@ func (g *graph) entry(pkg *pkg) { notIfaces = append(notIfaces, t) } } - } + }) // (8.0) handle interfaces for _, t := range notIfaces { @@ -1269,7 +1269,7 @@ func (g *graph) function(fn *ir.Function) { } func (g *graph) typ(t types.Type, parent types.Type) { - if _, ok := g.seenTypes[t]; ok { + if g.seenTypes.At(t) != nil { return } @@ -1279,7 +1279,7 @@ func (g *graph) typ(t types.Type, parent types.Type) { } } - g.seenTypes[t] = struct{}{} + g.seenTypes.Set(t, struct{}{}) if isIrrelevant(t) { return } diff --git a/vendor/modules.txt b/vendor/modules.txt index ad6852d6f..de43a1269 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -243,7 +243,7 @@ gopkg.in/ini.v1 gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 gopkg.in/yaml.v3 -# honnef.co/go/tools v0.1.1 +# honnef.co/go/tools v0.1.3 ## explicit honnef.co/go/tools/analysis/code honnef.co/go/tools/analysis/edit @@ -276,6 +276,7 @@ honnef.co/go/tools/simple honnef.co/go/tools/staticcheck honnef.co/go/tools/stylecheck honnef.co/go/tools/unused +honnef.co/go/tools/unused/typemap # k8s.io/klog/v2 v2.5.0 k8s.io/klog/v2 # github.com/miekg/dns => github.com/cilium/dns v1.1.4-0.20190417235132-8e25ec9a0ff3