Tools

Lint rules

Every rule jailint checks, with its category and default level. jailint explains each rule and how to configure them.

Categories

A rule's category sets its default level. Name a category wherever a rule name works ([lint.rules], -W, // jailint: allow(...)).

CategoryDefaultWhat
correctnessdenycode that is wrong: it does not do what it says
suspiciouswarncode that is most likely wrong, or does nothing
complexitywarncode that says something in a roundabout way
stylewarncode that works but is not written the usual way
perfwarncode that could be faster
pedanticallowstricter checks with more false positives
restrictionallowchecks that forbid things a project may choose to avoid

Rules

104 rules.

RuleCategoryDefaultFinds
absurd_comparisoncorrectnessdenya comparison an unsigned value always passes or fails (u >= 0)
almost_swappedcorrectnessdenya = b; b = a;, a swap that sets both to b
approx_constantstylewarna hand-typed 3.14159 or 1.4142 where Math has the constant
assert_constantstylewarnassert(true) or #assert true, which can never fail
autocast_in_argrestrictionallowxx, the automatic cast, written as an argument of a call
autocast_usedrestrictionallowxx, the automatic cast, outside a call's arguments
bad_bit_maskcorrectnessdenya mask test that can never match ((x & 4) == 1, (x | 2) == 0)
banner_commentstylewarna comment that is only a line of -, = or * fencing off a section
bitwise_precedencesuspiciouswarna bitwise operator that binds differently than in C (1 << n - 1)
bool_comparisoncomplexitywarncomparing a bool with true or false
bool_to_int_with_ifpedanticallowifx c then 1 else 0, a bool turned into an integer with a branch
broken_doc_linkstylewarna link in a doc comment ([name]) that names no declaration
cognitive_complexitypedanticallowa procedure whose branching scores above max_complexity (default 25)
constant_conditionsuspiciouswarnan if or while whose condition the compiler shows is always true or false
defer_frees_returnedcorrectnessdenydefer free(p); followed by return p;, which hands back freed memory
defer_in_loopsuspiciouswarna defer in a loop body that cleans up something from outside the loop
detached_doc_commentpedanticallowa comment that reads as a declaration's docs but has a blank line between it and the declaration
double_freecorrectnessdenytwo @FreesArgument calls on the same variable with nothing in between
dropped_resultsuspiciouswarna call drops the bool that follows the values it keeps (n := to_integer(s);)
duplicate_conditionsuspiciouswarnan else if that repeats an earlier condition
element_count_as_bytescorrectnessdenymemcpy(d, xs.data, xs.count) with elements wider than a byte
enum_member_prefixstylewarnevery member of an enum starts with the enum's name
erasing_opsuspiciouswarnan operation that is always 0 (x * 0, x & 0)
excessive_boolsrestrictionallowa procedure with more bool parameters than max_bools (default 3)
excessive_nestingpedanticallowblocks nested deeper than max_nesting (default 6)
exit_in_modulerestrictionallowa module ends the process
field_reassign_with_defaultpedanticallowx: T; x.a = 1; x.b = 2; where a struct literal x := T.{ a = 1, b = 2 } sets the fields at the declaration
float_equalitypedanticallow== or != between two computed floats
float_loop_counterpedanticallowa while loop counted in floats (while t < 1.0 { t += 0.1; })
format_push_stringperfwarnappend(*b, tprint(...)), which formats into a new string to add it to a builder
identical_branchessuspiciouswarnan if/else or ifx whose branches are the same
identical_case_bodiespedanticallowtwo cases of a switch with the same body, which could list their values together
identical_operandssuspiciouswarnan operator with the same expression on both sides (a == a)
identity_opcomplexitywarnan operation that changes nothing (x + 0, x * 1)
if_not_elsepedanticallowan if or ifx with a negated condition and an else
impossible_comparisoncorrectnessdenycomparisons of one integer that never pass together (x > 5 && x < 3)
incomplete_enum_switchpedanticallowa switch on an enum that neither covers every member nor has a default case
index_only_loopcomplexitywarnfor i: 0..xs.count-1 where i only indexes xs
infinite_loopsuspiciouswarna while whose condition nothing in the loop changes
int_plus_onecomplexitywarnx >= y + 1, which is x > y
integer_division_in_floatsuspiciouswarnan integer division whose result is used as a float
large_stack_arraypedanticallowa local fixed array bigger than max_stack_array_bytes (default 64 KiB)
leaked_allocationpedanticallowa local holding memory from an @Allocates call that is never freed, returned or handed on
leaked_temporarysuspiciouswarnan @Allocates result that is only compared, measured, indexed or printed, so nothing can free it
loop_with_break_conditioncomplexitywarnwhile true { if !c break; ... }, a loop whose condition is its first statement
lossy_float_literalstylewarna float32 literal with more digits than a float32 keeps (31415.92653)
lossy_xxpedanticallowxx that narrows a number to a smaller type
magic_numberpedanticallowan unexplained number in arithmetic, a comparison or an assignment
manual_array_findcomplexitywarna loop that searches an array and breaks with a found flag or index, which array_find does
manual_assign_opcomplexitywarna = a + b instead of a += b
manual_clampcomplexitywarna value kept between two constant bounds by hand instead of with clamp
manual_index_countercomplexitywarna counter incremented in a for loop that always equals it_index
manual_memcpyperfwarnfor i: 0..n-1 { dst[i] = src[i]; }, an element-by-element copy memcpy does at once
min_maxcorrectnessdenymin(0, max(100, x)), a clamp that is always one bound
misrefactored_assign_opcorrectnessdenya += a + b, an update that applies the operator to a twice
missing_docrestrictionallowan exported procedure, struct or enum with no doc comment
mixed_case_hex_literalsstylewarna hex literal with both upper and lower case digits (0xDeadbeef)
modified_range_boundsuspiciouswarna variable bounding a for range assigned in the loop, which does not change it
needless_boolcomplexitywarnifx c then true else false and if c return true; else return false;
needless_continuestylewarna continue as the last thing a loop body does
neg_cmp_floatpedanticallow!(a < b) on floats, which differs from a >= b when a value is NaN
neg_multiplystylewarnx * -1, which is -x
no_effectsuspiciouswarna statement that computes a value and drops it (x == 5;)
platform_leakrestrictionallowportable code imports something that asserts an operating system it is not built for
pointer_into_resizablesuspiciouswarna pointer into a resizable array used after a @GrowsArray call may have moved the array (p := *xs[i]; array_add(*xs, v); use(p);)
print_in_modulerestrictionallowa module writes to the program's output
push_in_static_ifsuspiciouswarna scoped push directly in an #if arm, which lasts past the arm
range_past_countcorrectnessdenyfor i: 0..xs.count indexing xs[i], one past the end
redundant_aliascomplexitywarna local that only exists to be copied into another local or returned
redundant_castcomplexitywarna cast to the type the value already has
redundant_derefcomplexitywarnp.*.field where p.field means the same
remove_in_forcorrectnessdenyremoving from an array while a for walks it forward
returned_local_addresscorrectnessdenyreturn *x; with x a local, a pointer into a stack frame that is gone
reversed_rangecorrectnessdenya range whose start is above its end, which never runs
self_assignmentsuspiciouswarna value assigned to itself (x = x;)
shadowed_itsuspiciouswarna nested for hides an it the enclosing loop uses
shadowed_localpedanticallowa local variable named like a parameter or another local in an enclosing scope of the same procedure
shift_overflowsuspiciouswarna shift by at least the bit width of its operand (x << 40 with x: s32)
single_case_switchstylewarna switch with a single case, which is an if
string_literal_writecorrectnessdenya write into a string literal, which is read-only (s := "abc"; s[0] = x;)
temp_storage_escapepedanticallowa @TempAllocates result (tprint, talloc) stored in a global or through a pointer, or returned
todo_markerrestrictionallowa comment with a TODO, FIXME, XXX or HACK marker
too_many_argumentsrestrictionallowa procedure with more parameters than max_arguments (default 7)
unchecked_directiverestrictionallow#no_abc, #no_aoc or #asm with no comment saying why
unclosed_resourcesuspiciouswarna local opened by an @Opens call (file_open, append(*builder, ..)) that nothing closes
uninit_readcorrectnessdenya variable declared = --- read before anything is written to it
unknown_allowsuspiciouswarna // jailint: allow(...) comment naming a rule that does not exist
unnecessary_force_castcomplexitywarncast,force where the value already has the type or the conversion widens
unnecessary_semicolonstylewarna ; that ends nothing (x = 1;;, if c { ... };)
unpaired_locksuspiciouswarna @Locks call with a path that returns or ends without a matching @Unlocks
unreadable_literalpedanticallowa long number without _ separators (1000000, 0xdeadbeef)
unsigned_range_end_minus_onesuspiciouswarnfor 0..n-1 with an unsigned n, which wraps around when n is 0
unused_importstylewarnan #import nothing in its scope uses
unused_parameterstylewarna parameter the procedure never uses
unused_private_declarationsuspiciouswarna #scope_file declaration that nothing in its file uses
unused_resultsuspiciouswarna call to a @UseResult procedure, as a statement
unused_suppressionsuspiciouswarna name in a // jailint: allow(...) comment or @jailint_allow note that silences nothing
unused_variablestylewarna local variable that is never used
use_after_freecorrectnessdenya variable read after a @FreesArgument call freed it (free(p); use(p);)
useless_formatcomplexitywarntprint("%", s) or sprint("%", s) with a string s, which only copies it
useless_resizableperfwarna local [..] T that is only filled with a known number of array_add calls and never resized
using_pollutionpedanticallowa using of a struct whose members share names with parameters, locals or globals already in scope
wrapping_constantcorrectnessdenya constant that wraps to the type the other operand gives it ((0xffff_ffff - 40) / h)
zero_ptrstylewarncast(*T) 0, which is null