aboutsummaryrefslogtreecommitdiff
path: root/vendor/honnef.co/go/tools/functions/functions.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/honnef.co/go/tools/functions/functions.go')
-rw-r--r--vendor/honnef.co/go/tools/functions/functions.go150
1 files changed, 0 insertions, 150 deletions
diff --git a/vendor/honnef.co/go/tools/functions/functions.go b/vendor/honnef.co/go/tools/functions/functions.go
deleted file mode 100644
index c5fe2d7..0000000
--- a/vendor/honnef.co/go/tools/functions/functions.go
+++ /dev/null
@@ -1,150 +0,0 @@
-package functions
-
-import (
- "go/types"
- "sync"
-
- "honnef.co/go/tools/callgraph"
- "honnef.co/go/tools/callgraph/static"
- "honnef.co/go/tools/ssa"
- "honnef.co/go/tools/staticcheck/vrp"
-)
-
-var stdlibDescs = map[string]Description{
- "errors.New": Description{Pure: true},
-
- "fmt.Errorf": Description{Pure: true},
- "fmt.Sprintf": Description{Pure: true},
- "fmt.Sprint": Description{Pure: true},
-
- "sort.Reverse": Description{Pure: true},
-
- "strings.Map": Description{Pure: true},
- "strings.Repeat": Description{Pure: true},
- "strings.Replace": Description{Pure: true},
- "strings.Title": Description{Pure: true},
- "strings.ToLower": Description{Pure: true},
- "strings.ToLowerSpecial": Description{Pure: true},
- "strings.ToTitle": Description{Pure: true},
- "strings.ToTitleSpecial": Description{Pure: true},
- "strings.ToUpper": Description{Pure: true},
- "strings.ToUpperSpecial": Description{Pure: true},
- "strings.Trim": Description{Pure: true},
- "strings.TrimFunc": Description{Pure: true},
- "strings.TrimLeft": Description{Pure: true},
- "strings.TrimLeftFunc": Description{Pure: true},
- "strings.TrimPrefix": Description{Pure: true},
- "strings.TrimRight": Description{Pure: true},
- "strings.TrimRightFunc": Description{Pure: true},
- "strings.TrimSpace": Description{Pure: true},
- "strings.TrimSuffix": Description{Pure: true},
-
- "(*net/http.Request).WithContext": Description{Pure: true},
-
- "math/rand.Read": Description{NilError: true},
- "(*math/rand.Rand).Read": Description{NilError: true},
-}
-
-type Description struct {
- // The function is known to be pure
- Pure bool
- // The function is known to be a stub
- Stub bool
- // The function is known to never return (panics notwithstanding)
- Infinite bool
- // Variable ranges
- Ranges vrp.Ranges
- Loops []Loop
- // Function returns an error as its last argument, but it is
- // always nil
- NilError bool
- ConcreteReturnTypes []*types.Tuple
-}
-
-type descriptionEntry struct {
- ready chan struct{}
- result Description
-}
-
-type Descriptions struct {
- CallGraph *callgraph.Graph
- mu sync.Mutex
- cache map[*ssa.Function]*descriptionEntry
-}
-
-func NewDescriptions(prog *ssa.Program) *Descriptions {
- return &Descriptions{
- CallGraph: static.CallGraph(prog),
- cache: map[*ssa.Function]*descriptionEntry{},
- }
-}
-
-func (d *Descriptions) Get(fn *ssa.Function) Description {
- d.mu.Lock()
- fd := d.cache[fn]
- if fd == nil {
- fd = &descriptionEntry{
- ready: make(chan struct{}),
- }
- d.cache[fn] = fd
- d.mu.Unlock()
-
- {
- fd.result = stdlibDescs[fn.RelString(nil)]
- fd.result.Pure = fd.result.Pure || d.IsPure(fn)
- fd.result.Stub = fd.result.Stub || d.IsStub(fn)
- fd.result.Infinite = fd.result.Infinite || !terminates(fn)
- fd.result.Ranges = vrp.BuildGraph(fn).Solve()
- fd.result.Loops = findLoops(fn)
- fd.result.NilError = fd.result.NilError || IsNilError(fn)
- fd.result.ConcreteReturnTypes = concreteReturnTypes(fn)
- }
-
- close(fd.ready)
- } else {
- d.mu.Unlock()
- <-fd.ready
- }
- return fd.result
-}
-
-func IsNilError(fn *ssa.Function) bool {
- // TODO(dh): This is very simplistic, as we only look for constant
- // nil returns. A more advanced approach would work transitively.
- // An even more advanced approach would be context-aware and
- // determine nil errors based on inputs (e.g. io.WriteString to a
- // bytes.Buffer will always return nil, but an io.WriteString to
- // an os.File might not). Similarly, an os.File opened for reading
- // won't error on Close, but other files will.
- res := fn.Signature.Results()
- if res.Len() == 0 {
- return false
- }
- last := res.At(res.Len() - 1)
- if types.TypeString(last.Type(), nil) != "error" {
- return false
- }
-
- if fn.Blocks == nil {
- return false
- }
- for _, block := range fn.Blocks {
- if len(block.Instrs) == 0 {
- continue
- }
- ins := block.Instrs[len(block.Instrs)-1]
- ret, ok := ins.(*ssa.Return)
- if !ok {
- continue
- }
- v := ret.Results[len(ret.Results)-1]
- c, ok := v.(*ssa.Const)
- if !ok {
- return false
- }
- if !c.IsNil() {
- return false
- }
- }
- return true
-}