435c0d9fc8
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.
71 lines
1.5 KiB
Go
71 lines
1.5 KiB
Go
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
|
||
}
|