src/rules/suspicious/strict.bend checks
raw source on the hub · import 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/rules/suspicious/strict.bend as Strict
rule strict: a def calls itself inside an operand of Bool.and(..) or
Bool.or(..), or in a comma-separated stretch holding && or || (either
side of the operator), matched by that exact text
(a qualified Base.Bool.or is not seen). They are functions, not
short-circuits: both sides always run (timed: False{} && f(x) costs all of
f), so ok(h) && go(rest) walks the whole input after the answer is known,
and the pending operator keeps a frame per step (the JS lane overflowed at
~64K this way). Match on the Bool in a helper, or carry it as an argument:
go(rest, ok(h)). A self-call bound by a let above is not flagged: binding
it says both run. Nor is one in a lambda body (_u => go(rest), as
Lazy.or_else takes): a thunk does not run eagerly, unless the body itself
holds && or ||. A => ends the stretch on its left, so a body's && or
|| never reaches back past it: go(x) <> _u => a && b is not flagged.
7 imports
import Base import ../../src.bend as Src import ../../finding.bend as F import ../../syntax/lex.bend as Lex import ../../syntax/tree.bend as Tree import ../calls.bend as Calls import ../../lazy/lazy.bend as Lazy
Definitions
def logic source · line 23 · raw
@+tt:String -> Bool
is the operator && or ||?
def seg_op.ends source · line 27 · raw
@kk:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/lex.TokKind -> Bool
a comma or a =>: the end of a stretch
def seg_op.or source · line 37 · raw
@+here:Bool -> @more:Bool -> Bool
this leaf's && or ||, or one further on in the stretch
def seg_op source · line 41 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> Bool
does the chain, up to its first top-level comma or =>, hold && or ||?
def inner source · line 51 · raw
@+hot:Bool -> @+oo:String -> @+tt:String -> Bool
is the group after a name an operand: the stretch is hot, or it is the (
of Bool.and or Bool.or
def call source · line 56 · raw
@+tt:String -> @+ll:U32 -> @+cc:U32 -> @+oo:String -> @+name:String -> @+path:String -> @+hot:Bool -> @kids:List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding> -> @rest:List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding> -> List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>
a name, then a group: a finding when the name is the def, the group a (
call and the stretch hot, then what the group and the rest report
def leaf source · line 75 · raw
@kk:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/lex.TokKind -> @comma:(@_:Unit -> List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>) -> @lam:(@_:Unit -> List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>) -> @plain:(@_:Unit -> List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>) -> List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>
a leaf read by its kind: past a comma, past a =>, or past any other
token; only the branch taken runs
def walk source · line 93 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> @+name:String -> @+path:String -> @+outer:Bool -> @+hot:Bool -> List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>
the self-calls in operands: outer is whether the enclosing group is an
operand, hot whether the current comma segment is; a => starts a lambda
body, hot only by its own &&/||. A leaf is read by its kind in leaf,
once the cell after it is known
def check.go source · line 118 · raw
@ds:List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/rules/calls.Def> -> @+path:String -> @acc:List<&2, List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>> -> List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>
def check source · line 128 · raw
@ss:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/src.Src -> List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>
the rule