# Trigger annotations
Verus assigns a set of triggers to every quantifier expression (`forall`, `exists`, `choose`)
in the program, including "implicit" quantifiers such as in `broadcast` lemmas.
There are many implications of triggers on proof automation that Verus developers should be
aware of. See [the relevant chapter of the guide](./quants.md), particularly the section
on [multiple triggers and matching loops](./multitriggers.md).
This page explains the procedure Verus uses to determine these triggers from Verus source code.
### Syntax
```verus-grammar
V@[root_trigger_attr_expr] ::= #![trigger V@[spec_expr] (, V@[spec_expr])*]
| #![auto]
| #![all_triggers]
V@[inner_trigger_attr_expr] ::= #[trigger] V@[spec_expr]
| #[trigger(R@[n])] V@[spec_expr]
```
V@[root_trigger_attr_expr] annotations appear at the start of the quantifier body and configure
trigger selection for the whole quantifier. V@[inner_trigger_attr_expr] annotations appear on
specific sub-expressions within the body to mark them individually as triggers.
### Semantics
Trigger annotations have no impact on the semantics of a spec expression.
Triggers only impact the proof space explored by the automated theorem prover.
## Terminology: trigger groups and trigger expressions
Every quantifier has a number of _quantifier variables_. To control how the solver instantiates
these variables, trigger groups are used.
* To every quantifier, Verus determines a collection of _trigger groups_.
* Every _trigger group_ is a collection of _trigger expressions_.
By necessity, any trigger group is only well-formed if every quantifier variable is used
by at least one trigger expression in the group.
Note that:
* The SMT solver will instantiate any quantifier whenever _any_ trigger group fires.
* However, a trigger group will only fire if _every_ expression in the group matches.
Therefore:
* Having more trigger groups makes the quantifier be instantiated _more_ often.
* A trigger group with more trigger expressions will fire _less_ often.
## Selecting trigger groups
Verus determines the collection of trigger groups as follows:
* Verus finds all applicable `#[trigger]` and `#[trigger(n)]` annotations in the body
of the quantifier.
* In the case of nested quantifiers, every `#[trigger]` or `#[trigger(n)]` annotation
is applicable to exactly one quantifier expression: the _innermost_ quantifier
which binds a variable used by the trigger expression.
* All applicable expressions marked by `#[trigger]` become a trigger group.
* All applicable expressions marked by `#[trigger(n)]` for the same `n` become a trigger group.
* Every annotation #![trigger EXPR1, ..., EXPRk] at
the root of the quantifier expression becomes a trigger group.
* If, after all of the above, no trigger groups have been identified, Verus _may_ use
heuristics to determine the trigger group(s) based on the body of the quantifier expression.
* If `#![all_triggers]` is provided, Verus uses an "aggressive" strategy, choosing all trigger
groups that can reasonably be inferred as applicable from the body.
* If `#![auto]` is provided, Verus uses a "conservative" strategy, choosing a single
trigger group that is judged as optimal by various heuristics.
* If neither `#![all_triggers]` nor `#![auto]` are provided, Verus uses the same
"conservative" strategy as it does for `#![auto]`.
* If, after all of the above, Verus is unable to find any trigger groups, it produces
an error.
## Trigger logging
By default, Verus often prints verbose information about selected triggers in cases where
Verus's heuristics are "un-confident" in the selected trigger groups.
You can silence this information on a case-by-case basis using the `#![auto]` attribute.
When `#![auto]` is applied to a quantifier, this tells Verus
that you want the automatically selected triggers
even when Verus is un-confident, in which case this logging will be silenced.
The behavior can be configured through the command line:
| Option | Behavior |
|---|---|
--triggers-mode silent | Do not show automatically chosen triggers |
--triggers-mode selective | Default. Show automatically chosen triggers only when heuristics are un-confident, and when #![auto] has not been supplied |
--triggers | Show all automatically chosen triggers for verified modules |
--triggers-mode verbose | Show all automatically chosen triggers for verified modules and imported definitions from other modules |