open-nomad/vendor/honnef.co/go/tools/functions/terminates.go
Seth Hoenig 435c0d9fc8 deps: Switch to Go modules for dependency management
This PR switches the Nomad repository from using govendor to Go modules
for managing dependencies. Aspects of the Nomad workflow remain pretty
much the same. The usual Makefile targets should continue to work as
they always did. The API submodule simply defers to the parent Nomad
version on the repository, keeping the semantics of API versioning that
currently exists.
2020-06-02 14:30:36 -05:00

71 lines
1.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package functions
import (
"go/types"
"honnef.co/go/tools/ir"
)
// Terminates reports whether fn is supposed to return, that is if it
// has at least one theoretic path that returns from the function.
// Explicit panics do not count as terminating.
func Terminates(fn *ir.Function) bool {
if fn.Blocks == nil {
// assuming that a function terminates is the conservative
// choice
return true
}
for _, block := range fn.Blocks {
if _, ok := block.Control().(*ir.Return); ok {
if len(block.Preds) == 0 {
return true
}
for _, pred := range block.Preds {
switch ctrl := pred.Control().(type) {
case *ir.Panic:
// explicit panics do not count as terminating
case *ir.If:
// Check if we got here by receiving from a closed
// time.Tick channel this cannot happen at
// runtime and thus doesn't constitute termination
iff := ctrl
if !ok {
return true
}
ex, ok := iff.Cond.(*ir.Extract)
if !ok {
return true
}
if ex.Index != 1 {
return true
}
recv, ok := ex.Tuple.(*ir.Recv)
if !ok {
return true
}
call, ok := recv.Chan.(*ir.Call)
if !ok {
return true
}
fn, ok := call.Common().Value.(*ir.Function)
if !ok {
return true
}
fn2, ok := fn.Object().(*types.Func)
if !ok {
return true
}
if fn2.FullName() != "time.Tick" {
return true
}
default:
// we've reached the exit block
return true
}
}
}
}
return false
}