123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210typet=|Unused_local|Unused_field|Unused_import|Unused_label|Shift_overflow|Constant_trap|Tautological_comparison|Constant_condition|Unused_result|Dead_code|Cast_always_fails|Eager_select|Precedence|Redundant_operation|Truncated_coverage|Naming_conflict|Reserved_word_rename|Generated_nameletall=[Unused_local;Unused_field;Unused_import;Unused_label;Shift_overflow;Constant_trap;Tautological_comparison;Constant_condition;Unused_result;Dead_code;Cast_always_fails;Eager_select;Precedence;Redundant_operation;Truncated_coverage;Naming_conflict;Reserved_word_rename;Generated_name;]letname=function|Unused_local->"unused-local"|Unused_field->"unused-field"|Unused_import->"unused-import"|Unused_label->"unused-label"|Shift_overflow->"shift-count-overflow"|Constant_trap->"constant-trap"|Tautological_comparison->"tautological-comparison"|Constant_condition->"constant-condition"|Unused_result->"unused-result"|Dead_code->"dead-code"|Cast_always_fails->"cast-always-fails"|Eager_select->"eager-select"|Precedence->"precedence"|Redundant_operation->"redundant-operation"|Truncated_coverage->"truncated-coverage"|Naming_conflict->"naming-conflict"|Reserved_word_rename->"reserved-word-rename"|Generated_name->"generated-name"letdescription=function|Unused_local->"A local that is declared but never read."|Unused_field->"A module field that is defined but never used."|Unused_import->"An imported function or global that is never used."|Unused_label->"A block label that is declared but never branched to."|Shift_overflow->"A constant shift count is at least the operand's bit width (Wasm masks \
it)."|Constant_trap->"An operation always traps on a constant operand (integer division by \
zero, or an out-of-range trapping conversion)."|Tautological_comparison->"A comparison whose result is constant (an unsigned comparison against \
zero, or identical operands)."|Constant_condition->"A branch, loop, or select condition that is a constant."|Unused_result->"The result of a side-effect-free expression is computed and then \
discarded."|Dead_code->"A statement is unreachable: it follows an unconditional branch, return, \
or unreachable."|Cast_always_fails->"A reference cast or test whose operand can never have the target type, \
so it always traps (or is always false)."|Eager_select->"A trapping or effectful operation in a branch of a '?:' (which compiles \
to a 'select', evaluating both branches unconditionally)."|Precedence->"Operators whose relative precedence is easy to misread are mixed \
without parentheses (a shift with arithmetic, or a comparison with a \
bitwise operator)."|Redundant_operation->"An operation with no effect on its result (an arithmetic identity, an \
absorbing operand, identical operands, a self-assignment, or a \
superfluous cast)."|Truncated_coverage->"Path-sensitive validation gave up after too many configurations."|Naming_conflict->"A Wasm name collided with another and was renamed."|Reserved_word_rename->"A Wasm name is a reserved word and was renamed."|Generated_name->"An unnamed but used parameter was given a generated name."(* Whether the warning flags code that can be removed with no change in
behaviour: an unused binding, import, or label, or an unreachable statement.
An editor renders such a diagnostic faded (LSP's [DiagnosticTag.Unnecessary]
/ VS Code's greyed-out dead code). Kept here, with the warning definitions,
so the LSP server and the VS Code extension classify from one source. *)letis_unnecessary=function|Unused_local|Unused_field|Unused_import|Unused_label|Dead_code->true|Shift_overflow|Constant_trap|Tautological_comparison|Constant_condition|Unused_result|Cast_always_fails|Eager_select|Precedence|Redundant_operation|Truncated_coverage|Naming_conflict|Reserved_word_rename|Generated_name->false(* Group name -> members. The special group "all" is handled separately by
[set] so it need not be listed here. *)letgroup_table=[("unused",[Unused_local;Unused_field;Unused_import;Unused_label]);("correctness",[Shift_overflow;Constant_trap;Tautological_comparison;Constant_condition;Unused_result;Dead_code;Cast_always_fails;Eager_select;Precedence;Unused_field;Unused_import;Unused_label;]);("redundant",[Redundant_operation]);("naming",[Naming_conflict;Reserved_word_rename;Generated_name]);]letgroups=List.mapfstgroup_tabletypelevel=Hidden|Displayed|Error(* A policy is just the level assigned to each warning; [set] returns an updated
function, so later assignments naturally override earlier ones. *)typepolicy=t->level(* The From_wasm renaming warnings are noisy round-trip notices, and the
redundant-operation lints are optimisation hints that are common in generated
code, so all of these are hidden unless explicitly enabled with [-W];
everything else is shown. *)letdefault_policy=function|Naming_conflict|Reserved_word_rename|Generated_name|Redundant_operation->Hidden|Unused_local|Unused_field|Unused_import|Unused_label|Shift_overflow|Constant_trap|Tautological_comparison|Constant_condition|Unused_result|Dead_code|Cast_always_fails|Eager_select|Precedence|Truncated_coverage->Displayedletresolve(policy:policy)w=policyw(* The set of warnings a name refers to: the special group "all", a single
warning name, or a named group. *)lettargetstarget=ifString.equaltarget"all"thenSomeallelsematchList.find_opt(funw->String.equaltarget(namew))allwith|Somew->Some[w]|None->List.assoc_opttargetgroup_tableletset(policy:policy)targetlevel=matchtargetstargetwith|Somews->Ok(funw->ifList.exists(funw'->w=w')wsthenlevelelsepolicyw)|None->Stdlib.Error(Printf.sprintf"Unknown warning or group '%s'. Known names: %s."target(String.concat", "(List.mapnameall@groups@["all"])))letlevel_of_string=function|"hidden"->SomeHidden|"warning"->SomeDisplayed|"error"->SomeError|_->Noneletparse_specs=matchString.index_opts'='with|None->Stdlib.Error(Printf.sprintf"Malformed warning spec '%s'; expected NAME=LEVEL (LEVEL is hidden, \
warning, or error)."s)|Somei->(letname=String.subs0iinletlevel=String.subs(i+1)(String.lengths-i-1)inmatchlevel_of_stringlevelwith|Somelevel->Ok(name,level)|None->Stdlib.Error(Printf.sprintf"Unknown warning level '%s'; expected hidden, warning, or error."level))