Naming, labels and index conventions
These rules make names, constraint intent and numeric array indices easier to
read, point out standard-library calls that MiniZinc has deprecated, suggest
assertions for input checks and flag Boolean operators whose grouping is easy
to misread. Select the group with --rules preset:conventions.
See linting for configuration, suppressions and diagnostic output.
| Rule | Family | Severity | Default | Automatic fix |
|---|---|---|---|---|
naming |
style |
Warning | No | No |
missing-constraint-label |
style |
Warning | No | No |
array-index-start |
style |
Warning | No | No |
deprecated-call |
suspicious |
Warning | Yes | No |
prefer-assertion |
style |
Warning | No | No |
ambiguous-precedence |
suspicious |
Warning | No | No |
naming
Section titled “naming”Checks names against Zincite’s MiniZinc conventions. Values, functions,
predicates, fields and generator bindings use snake_case. Types, enums,
constructors and explicitly declared parameter sets use UpperCamelCase.
set of int: SHIFTS = 1 .. 7;array[SHIFTS] of var 0 .. 10: staffCount;Save the example as example.mzn. With the
standard library configured, run:
zincite lint --isolated --rules naming example.mznZincite reports:
[root example.mzn] example.mzn:1:13: bytes 12..18: warning [naming]: use UpperCamelCase for declared name 'SHIFTS' |1 | set of int: SHIFTS = 1 .. 7; | ^^^^^^[root example.mzn] example.mzn:2:31: bytes 59..69: warning [naming]: use snake_case for declared name 'staffCount' |2 | array[SHIFTS] of var 0 .. 10: staffCount; | ^^^^^^^^^^Here, Shifts and staff_count communicate the roles of the two declarations:
set of int: Shifts = 1 .. 7;array[Shifts] of var 0 .. 10: staff_count;Set-valued decision variables still use snake_case. Quoted identifiers and
_ are exempt; one leading underscore is allowed for intentionally unused
bindings. The rule checks declarations whose role is clear from syntax. It
does not check references or assignment names in standalone .dzn files.
Renaming is manual because other files may use the same names.
missing-constraint-label
Section titled “missing-constraint-label”Recommends a string annotation explaining why a constraint belongs in the model.
array[1 .. 7] of var 0 .. 10: staff;array[1 .. 7] of int: required;constraint forall (day in 1 .. 7) ( staff[day] >= required[day]);A label can describe the modelling requirement rather than repeat the formula:
constraint :: "Every day has enough staff to cover demand"forall (day in 1 .. 7) ( staff[day] >= required[day]);The label must be a direct string annotation in the constraint header. A string
inside the expression or a function call does not count. Equality items written
without constraint are also checked. Missing labels are readability advice;
Zincite leaves their wording to the modeller.
array-index-start
Section titled “array-index-start”Suggests starting nonempty numeric array indices at 1, following MiniZinc’s usual array convention.
array[0 .. 6] of int: required;If the numbers are only positions, array[1..7] avoids having to remember a
different offset. Changing the index set requires reviewing data and accesses
as well as the declaration.
An offset can also be meaningful. An array indexed by years, for example, may
reasonably start at 2026. Keep that representation and suppress the
rule when appropriate. Enum indices
are exempt. Unknown bounds and unconstrained int indices do not receive this
advice.
deprecated-call
Section titled “deprecated-call”Reports a call to a standard-library predicate or function that MiniZinc marks
with mzn_deprecated. The message quotes the MiniZinc version that deprecated
it and the library’s explanation, usually a link to the documentation.
include "globals.mzn";
array[1 .. 5] of var 1 .. 3: shift;constraint at_most(2, shift, 3);Save the example as example.mzn. With the
standard library configured, run:
zincite lint --isolated --rules deprecated-call example.mznZincite reports:
[root example.mzn] example.mzn:4:12: bytes 71..78: warning [deprecated-call]: 'at_most' is deprecated since MiniZinc 2.4.0: https://www.minizinc.org/doc-2.4.0/en/lib-globals.html#deprecated |4 | constraint at_most(2, shift, 3); | ^^^^^^^The integer form of at_most has been deprecated since MiniZinc 2.4.0. Its
documentation recommends a count instead:
constraint count (s in shift) (s = 3) <= 2;The rule follows the overload the call selects. The set form of at_most is
not deprecated, so a call with set arguments stays quiet. So does a call to
your own predicate with the same name. When Zincite cannot select one
overload and a deprecated candidate remains, it records an analysis limitation
instead of a finding. Replacing the call is manual.
prefer-assertion
Section titled “prefer-assertion”Reports a constraint item whose expression depends only on parameters. Such a
constraint usually checks the input data. When it fails, MiniZinc reports only
that the model is inconsistent. An assert names the failed condition instead.
int: n;array[1 .. n] of var 0 .. 9: digit;constraint n > 0;Save the example as example.mzn. With the
standard library configured, run:
zincite lint --isolated --rules prefer-assertion example.mznZincite reports:
[root example.mzn] example.mzn:3:12: bytes 55..60: warning [prefer-assertion]: this constraint depends only on parameters; consider assert(condition, "message") to explain failed input |3 | constraint n > 0; | ^^^^^Write the check as an assertion with a message:
constraint assert(n > 0, "n must be positive");A constraint item that already is an assert call stays quiet, also when
written infix, parenthesized or annotated, as does one that depends on a decision variable or
contains a let with local constraints. Constant conditions and deliberate
infeasibility checks over parameters also warn; suppress the rule for those.
When Zincite cannot determine whether the expression depends on decisions, it
records an analysis limitation instead of a finding. The rule checks top-level
constraint items only, not constraints in let expressions. Rewriting the
constraint is manual.
ambiguous-precedence
Section titled “ambiguous-precedence”Reports two unparenthesized Boolean operator patterns whose grouping is easy to misread. The MiniZinc 2.10.1 operator table defines the grouping:
/\binds tighter than\/andxor, soa \/ b /\ cmeansa \/ (b /\ c). The rule reports/\and\/orxorat one level.->and<-share one precedence level and group from the left, soa -> b -> cmeans(a -> b) -> c. The rule reports a chain of two or more of these operators.
var bool: rain;var bool: wind;var bool: stay_in;constraint rain \/ wind /\ stay_in;Save the example as example.mzn. With the
standard library configured, run:
zincite lint --isolated --rules ambiguous-precedence example.mznZincite reports:
[root example.mzn] example.mzn:4:17: bytes 67..69: warning [ambiguous-precedence]: conjunction binds tighter than '\/', so this reads as 'rain \/ (wind /\ stay_in)'; add parentheses to show the grouping |4 | constraint rain \/ wind /\ stay_in; | ^^The warning points at the operator and shows the grouping MiniZinc uses. Add parentheses to state the grouping you mean:
constraint (rain \/ wind) /\ stay_in;Parenthesized forms such as a -> (b -> c) and (a -> b) -> c stay quiet, and
so does a /\ b -> c, where conjunction binding tighter than implication
matches the usual reading. Unicode spellings such as ∨, ∧ and → count as
the same operators. Other operators, not, <-> chains and backquoted infix
calls are not checked. The rule needs no model context or standard library.
Adding parentheses is manual; the formatter never adds them.