6 "honnef.co/go/tools/ir"
9 // Terminates reports whether fn is supposed to return, that is if it
10 // has at least one theoretic path that returns from the function.
11 // Explicit panics do not count as terminating.
12 func Terminates(fn *ir.Function) bool {
14 // assuming that a function terminates is the conservative
19 for _, block := range fn.Blocks {
20 if _, ok := block.Control().(*ir.Return); ok {
21 if len(block.Preds) == 0 {
24 for _, pred := range block.Preds {
25 switch ctrl := pred.Control().(type) {
27 // explicit panics do not count as terminating
29 // Check if we got here by receiving from a closed
30 // time.Tick channel – this cannot happen at
31 // runtime and thus doesn't constitute termination
36 ex, ok := iff.Cond.(*ir.Extract)
43 recv, ok := ex.Tuple.(*ir.Recv)
47 call, ok := recv.Chan.(*ir.Call)
51 fn, ok := call.Common().Value.(*ir.Function)
55 fn2, ok := fn.Object().(*types.Func)
59 if fn2.FullName() != "time.Tick" {
63 // we've reached the exit block