Laurel User Guide

4.6. Quantifier🔗

For specifications that range over many values, Laurel provides quantifiers. A forall states that its body holds for every value of the bound variables; an exists states that there is at least one value for which the body holds. Both take one or more typed binders and a body introduced with =>.

procedure quantifiers()
  opaque
{
  assert forall(x: int) => x + 0 == x;
  assert exists(x: int) => x == 42
};

The implication operator ==> is frequently used inside quantifiers to restrict the range of interest — for instance, to say something about every index of an array within bounds:

procedure inContract(n: int)
  requires n > 0
  opaque
  ensures forall(i: int) => i >= 0 ==> i < n ==> i < n + 1
{
};

Because a forall over an infinite domain (such as all integers) cannot be checked by enumeration, the solver reasons about it logically. To control how it instantiates a quantifier, you can attach a trigger — a pattern in braces that tells the solver which terms should cause the quantified fact to fire:

procedure P(x: int): int;
procedure withTrigger()
  opaque
{
  assume forall(i: int) { P(i) } => P(i) == i + 1;
  assert P(1) == 2   // the term P(1) matches the trigger, so the fact fires
};