This reference manual defines a few different syntaxes that are used pervasively. These are defined in dedicated sections in this manual.
- An "introduction pattern"
ipat
like"H"
or"[H1 H2]"
is used to destruct a hypothesis (sometimes called eliminating a hypothesis). This is directly used byiDestruct
andiIntros
, but many tactics also integrate support foripat
s to combine some other work with destructing, such asiMod
. The name "introduction pattern" comes from a similar term in Coq which is used in tactics likedestruct
andintros
. - A "selection pattern"
selpat
like"H1 H2"
or"#"
names a collection of hypotheses. Most commonly used iniFrame
. - A "specialization pattern"
spat
likeH
or[$H1 H2]
is used to specialize a wand to some hypotheses along with specifying framing. Commonly used as part of proof mode terms (described just below). - A "proof mode term"
pm_trm
likelemma with spat
or"H" $! x with spat
allows to specialize a wand (which can be either a Gallina lemma or a hypothesis) on the fly, as an argument toiDestruct
for example.
Many of the tactics below apply to more goals than described in this document since the behavior of these tactics can be tuned via instances of the type classes in the file proofmode/classes. Most notably, many of the tactics can be applied when the connective to be introduced or to be eliminated appears under a later, an update modality, or in the conclusion of a weakest precondition.
iStartProof
: start the proof mode by turning a Coq goal into a proof mode entailment. This tactic is performed implicitly by all proof mode tactics described in this file, and thus should generally not be used by hand.iStartProof PROP
: explicitly specify which BI logicPROP : bi
should be used. This is useful to drop down in a layered logic, e.g. to drop down frommonPred PROP
toPROP
.
iStopProof
: turn the proof-mode entailment into an ordinary Coq goalbig star of context ⊢ proof mode goal
.
iExact "H"
: finish the goal if the conclusion matches the hypothesisH
iAssumption
: finish the goal if the conclusion matches any hypothesis in either the proofmode or the Coq context. Only hypotheses in the Coq context that are syntactically of the shape⊢ P
are recognized by this tactic (this means that assumptions of the shapeP ⊢ Q
are not recognized).iApply pm_trm
: match the conclusion of the current goal against the conclusion ofpm_trm
and generates goals for the premises ofpm_trm
. See proof mode terms below. If the applied term has more premises than given specialization patterns, the pattern is extended with[] ... []
. As a consequence, all unused spatial hypotheses move to the last premise.
iIntros (x1 ... xn) "ipat1 ... ipatn"
: introduce universal quantifiers using Coq introduction patternsx1 ... xn
and implications/wands using proof mode introduction patternsipat1 ... ipatn
.iClear (x1 ... xn) "selpat"
: clear the hypotheses given by the selection patternselpat
and the Coq level hypotheses/variablesx1 ... xn
.iClear select (pat)%I
: clear the last hypothesis of the intuitionistic or spatial context that matches patternpat
.iRevert (x1 ... xn) "selpat"
: revert the hypotheses given by the selection patternselpat
into wands, and the Coq level hypotheses/variablesx1 ... xn
into universal quantifiers. Intuitionistic hypotheses are wrapped into the intuitionistic modality.iRevert select (pat)%I
: revert the last hypothesis of the intuitionistic or spatial context that matches patternpat
.iRename "H1" into "H2"
: rename the hypothesisH1
intoH2
.iRename select (pat)%I into "H"
: rename the last hypothesis of the intuitionistic or spatial context that matches patternpat
intoH
. This is particularly useful to give a name to an anonymous hypothesis.iSpecialize pm_trm
: instantiate universal quantifiers and eliminate implications/wands of a hypothesispm_trm
. See proof mode terms below.iSpecialize pm_trm as #
: instantiate universal quantifiers and eliminate implications/wands of a hypothesispm_trm
whose conclusion is persistent. All hypotheses can be used for proving the premises ofpm_trm
, as well as for the resulting main goal.iPoseProof pm_trm as (x1 ... xn) "ipat"
: putpm_trm
into the context and destruct it using the introduction patternipat
. This tactic is essentially the same asiDestruct
with the difference thatpm_trm
is not thrown away if possible.iAssert (P)%I with "spat" as "H"
: generate a new subgoalP
and add the hypothesisP
to the current goal asH
. The specialization patternspat
specifies which hypotheses will be consumed by provingP
.iAssert (P)%I with "spat" as "ipat"
: like the above, but immediately destruct the generated hypothesis using the introduction patternipat
. Ifipat
is "intuitionistic" (most commonly, it starts with#
or%
), then all spatial hypotheses are available in both the subgoal forP
as well as the current goal. Anipat
is considered intuitionistic if all branches start with a#
(which causesP
to be moved to the intuitionistic context) or with a%
(which causesP
to be moved to the pure Coq context).iAssert (P)%I as %cpat
: assertP
and destruct it using the Coq introduction patterncpat
. All hypotheses can be used for provingP
as well as for proving the current goal.
iSelect (pat)%I tac
: run the tactictac H
, whereH
is the name of the last hypothesis in the intuitionistic or spatial hypothesis context that matches patternpat
. There is no backtracking to select the next hypothesis in casetac H
fails.
iPureIntro
: turn a pure goal, typically of the form⌜φ⌝
, into a Coq goal. This tactic also works for goals of the shapea ≡ b
on discrete OFEs, and✓ a
on discrete cameras.iLeft
: prove a disjunctionP ∨ Q
by proving the left sideP
.iRight
: prove a disjunctionP ∨ Q
by proving the right sideQ
.iSplitL "H1 ... Hn"
: split a conjunctionP ∗ Q
into two proofs. The hypothesesH1 ... Hn
are used for the left conjunct, and the remaining ones for the right conjunct. Intuitionistic hypotheses are always available in both proofs. Also works onP ∧ Q
, although in that case you can useiSplit
and retain all the hypotheses in both goals.iSplitR "H0 ... Hn"
: symmetric version of the above, using the hypothesesH1 ... Hn
for the right conjunct. Note that the goals are still ordered left-to-right; you can useiSplitR "..."; last first
to reverse the generated goals.iSplit
: split a conjunctionP ∧ Q
into two goals. Also works for separating conjunctionP ∗ Q
provided one of the operands is persistent (and both proofs may use the entire spatial context).iExist t1, .., tn
: provide a witness for an existential quantifier∃ x, ...
.t1 ... tn
can also be underscores, which are turned into evars. (In fact they can be arbitrary terms with holes, oropen_constr
s, and all of the holes will be turned into evars.)
-
iExFalso
: change the goal to provingFalse
. -
iDestruct
is an important enough tactic to describe several special cases:iDestruct "H1" as (x1 ... xn) "H2"
: eliminate a series of existential quantifiers in hypothesisH1
using Coq introduction patternsx1 ... xn
and name the resulting hypothesisH2
. The Coq introduction patterns can also be used for pure conjunctions; for example we can destruct∃ x, ⌜v = x⌝ ∗ l ↦ x
usingiDestruct "H" as (x Heq) "H"
to immediately putHeq: v = x
in the Coq context. This variant of the tactic will always throw away the original hypothesisH1
.iDestruct pm_trm as "ipat"
: specialize the proof-mode term (see below) and destruct it using the introduction patternipat
. Ifpm_trm
starts with a hypothesis, and that hypothesis resides in the intuitionistic context, it will not be thrown away.iDestruct pm_trm as (x1 ... xn) "ipat"
: combine the above, first specializingpm_trm
, then eliminating existential quantifiers (and pure conjuncts) withx1 ... xn
, and finally destructing the resulting term using the introduction patternipat
.iDestruct pm_trm as %cpat
: destruct the pure conclusion of a termpr_trm
using the Coq introduction patterncpat
. When using this tactic, all hypotheses can be used for proving the premises ofpm_trm
, as well as for proving the resulting goal.iDestruct num as (x1 ... xn) "ipat"
/iDestruct num as %cpat
: introducenum : nat
hypotheses and destruct the last introduced hypothesis.iDestruct select (pat)%I as ...
is the same asiDestruct "H" as ...
, whereH
is the name of the last hypothesis of the intuitionistic or spatial context matching patternpat
.
In case all branches of
ipat
start with a#
(which causes the hypothesis to be moved to the intuitionistic context) or with an%
(which causes the hypothesis to be moved to the pure Coq context), then one can use all hypotheses for proving the premises ofpm_trm
, as well as for proving the resulting goal. Note that in this case the hypotheses still need to be subdivided among the spatial premises.
iFrame (t1 .. tn) "selpat"
: cancel the Coq terms (or Coq hypotheses)t1 ... tn
and Iris hypotheses given byselpat
in the goal. The constructs of the selection pattern have the following meaning:%
: repeatedly frame hypotheses from the Coq context.#
: repeatedly frame hypotheses from the intuitionistic context.∗
: frame as much of the spatial context as possible. (N.B: this is the unicode symbol∗
, not the regular asterisk*
.) Notice that framing spatial hypotheses makes them disappear, but framing Coq or intuitionistic hypotheses does not make them disappear. This tactic solves the goal if everything in the conclusion has been framed.
iFrame select (pat)%I
: cancel the last hypothesis of the intuitionistic of spatial context that matches patternpat
.iCombine "H1 H2" as "ipat"
: combineH1 : P1
andH2 : P2
intoH: P1 ∗ P2
or something simplified but equivalent, then destruct the combined hypthesis usingipat
. Some examples of simplificationsiCombine
knows about are to combineown γ x
andown γ y
intoown γ (x ⋅ y)
, and to combinel ↦{1/2} v
andl ↦{1/2} v
intol ↦ v
.iAccu
: solves a goal that is an evar by instantiating it with all hypotheses from the spatial context joined together with a separating conjunction (oremp
in case the spatial context is empty). Not commonly used, but can be extremely useful when combined with automation.
iModIntro
: introduce a modality in the goal. The type classFromModal
is used to specify which modalities this tactic should introduce, and how introducing that modality affects the hypotheses. Instances of that type class include: later, except 0, basic update and fancy update, intuitionistically, persistently, affinely, plainly, absorbingly, objectively, and subjectively.iModIntro mod
(rarely used): introduce a specific modality named bymod
, which is a term pattern (i.e., a term with holes as underscores).iModIntro mod
will find a subterm matchingmod
, and try introducing its topmost modality. For instance, if the goal is⎡|==> P⎤
, usingiModIntro ⎡|==> P⎤%I
oriModIntro ⎡_⎤%I
would introduce⎡_⎤
and produce goal|==> P
, whileiModIntro (|==> _)%I
would introduce|==>
and produce goal⎡P⎤
.iNext
: an alias ofiModIntro (▷^_ _)
(that is, introduce the later modality). This eliminates a later in the goal, and in exchange also strips one later from all the hypotheses.iNext n
: an alias ofiModIntro (▷^n _)
(that is, introduce the▷^n
modality).iAlways
: a deprecated alias ofiModIntro
(intended to introduce the□
modality).
iMod pm_trm as (x1 ... xn) "ipat"
: eliminate a modalitypm_trm
that is an instance of theElimModal
type class, and destruct the resulting hypothesis usingipat
. Instances include: later, except 0, basic update|==>
and fancy update|={E}=>
.iMod "H"
: equivalent toiMod "H" as "H"
(eliminates the modality and keeps the name of the hypothesis).iMod pm_trm
: equivalent toiMod pm_term as "?"
(the resulting hypothesis will be introduced anonymously).
iLöb as "IH"
: perform Löb induction by generating a hypothesisIH : ▷ goal
.iLöb as "IH" forall (x1 ... xn) "selpat"
: perform Löb induction, generalizing over the Coq level variablesx1 ... xn
, the hypotheses given by the selection patternselpat
, and the spatial context as usual.
iInduction x as cpat "IH" "selpat"
: perform induction on the Coq termx
. The Coq introduction patterncpat
is used to name the introduced variables. The induction hypotheses are inserted into the intuitionistic context and given fresh names prefixedIH
.iInduction x as cpat "IH" forall (x1 ... xn) "selpat"
: perform induction, generalizing over the Coq level variablesx1 ... xn
, the hypotheses given by the selection patternselpat
, and the spatial context.
iRewrite pm_trm
/iRewrite pm_trm in "H"
: rewrite using an internal equality in the proof mode goal / hypothesisH
.iRewrite -pm_trm
/iRewrite -pm_trm in "H"
: rewrite in reverse direction using an internal equality in the proof mode goal / hypothesisH
.iEval (tac)
/iEval (tac) in "selpat"
: performs a tactictac
on the proof mode goal / hypotheses given by the selection patternselpat
. Using%
as part of the selection pattern is unsupported. The tactictac
should be a reduction or rewriting tactic likesimpl
,cbv
,lazy
,rewrite
orsetoid_rewrite
. TheiEval
tactic is implemented by runningtac
on?evar ⊢ P
/P ⊢ ?evar
whereP
is the proof goal / a hypothesis given byselpat
. After runningtac
,?evar
is unified with the resultingP
, which in turn becomes the new proof mode goal / a hypothesis given byselpat
. Note that parentheses aroundtac
are needed.iSimpl
/iSimpl in "selpat"
: performssimpl
on the proof mode goal / hypotheses given by the selection patternselpat
. This is a shorthand foriEval (simpl)
.
iInv H as (x1 ... xn) "ipat"
: open an invariant in hypothesis H. The result is destructed using the Coq intro patternsx1 ... xn
(for existential quantifiers) and then the proof mode introduction patternipat
.iInv H with "selpat" as (x1 ... xn) "ipat" "Hclose"
: generate an update for closing the invariant and put it in a hypothesis namedHclose
.iInv H with "selpat" as (x1 ... xn) "ipat"
: supply a selection patternselpat
, which is used for any auxiliary assertions needed to open the invariant (e.g. for cancelable or non-atomic invariants).iInv N as (x1 ... xn) "ipat"
: identify the invariant to be opened with a namespaceN
rather than giving a specific hypothesis.iInv S with "selpat" as (x1 ... xn) "ipat" "Hclose"
: combine all the above, whereS
is either a proof-mode identifier or a namespace.
-
The tactic
done
of std++ (which solves "trivial" goals usingintros
,reflexivity
,symmetry
,eassumption
,trivial
,split
,discriminate
,contradiction
, etc.) is extended so that it also, among other things:- performs
iAssumption
, - introduces
∀
,→
, and-∗
in the proof mode, - introduces pure goals
⌜ φ ⌝
usingiPureIntro
and callsdone
onφ
, and, - solves other trivial proof mode goals, such as
emp
,x ≡ x
, big operators over the empty list/map/set/multiset.
(Note that ssreflect also has a
done
tactic. Although Iris uses ssreflect, it overrides ssreflect'sdone
tactic with std++'s.) - performs
-
The proof mode adds hints to the core
eauto
database so thateauto
automatically introduces: conjunctions and disjunctions, universal and existential quantifiers, implications and wand, plainness, persistence, later and update modalities, and pure connectives.
Selection patterns are used to select hypotheses in the tactics iRevert
,
iClear
, iFrame
, iLöb
and iInduction
. The proof mode supports the
following selection patterns:
H
: select the hypothesis namedH
.%
: select the entire pure/Coq context.#
: select the entire intuitionistic context.∗
: select the entire spatial context. (N.B: this is the unicode symbol∗
, not the regular asterisk*
.)
Introduction patterns are used to perform introductions and eliminations of multiple connectives on the fly. The proof mode supports the following introduction patterns:
H
: create a hypothesis namedH
.?
: create an anonymous hypothesis._
: clear the hypothesis.$
: frame the hypothesis in the goal.[ipat1 ipat2]
: (separating) conjunction elimination. In order to destruct conjunctionsP ∧ Q
in the spatial context, one of the following conditions should hold:- Either the proposition
P
orQ
should be persistent. - Either
ipat1
oripat2
should be_
, which results in one of the conjuncts to be thrown away.
- Either the proposition
(pat1 & pat2 & ... & patn)
: syntactic sugar for[pat1 [pat2 .. patn ..]]
to destruct nested (separating) conjunctions.[ipat1|ipat2]
: disjunction elimination.[]
: false elimination.%H
: move the hypothesis to the pure Coq context, and name itH
. Support for the%H
introduction pattern requires an implementation of the hookstring_to_ident
. Without an implementation of this hook, the%H
pattern will fail. We provide an implementation of the hook using Ltac2, which works with Coq 8.11 and later, and can be installed with opam; see iris/string-ident for details.%
: move the hypothesis to the pure Coq context (anonymously). Note that if%
is followed by an identifier, and not another token, a space is needed to disambiguate from%H
above.->
and<-
: rewrite using a pure Coq equality# ipat
: move the hypothesis into the intuitionistic context. The tactic will fail if the hypothesis is not intuitionistic. On success, the tactic will strip any number of intuitionistic and persistence modalities. If the hypothesis is already in the intuitionistic context, the tactic will still strip intuitionistic and persistence modalities (it is a no-op if the hypothesis does not contain such modalities).-# ipat
(uncommon) : move the hypothesis into the spatial context. This can move a hypothesis from the intuitionistic context to the spatial context, or can explicitly specify the spatial context when the intuitionistic context could be used (e.g., because a hypothesis was proven without using spatial hypotheses). If the hypothesis is already in the spatial context, the tactic is a no-op. If the hypothesis is not affine, an<affine>
modality is added to the hypothesis.> ipat
: eliminate a modality (if the goal permits); commonly used to strip a later from the hypotheses when it is timeless and the goal is either aWP
or an update modality|={E}=>
.
Apart from this, there are the following introduction patterns that can only appear at the top level:
{selpat}
: clear the hypotheses given by the selection patternselpat
. Items of the selection pattern can be prefixed with$
, which cause them to be framed instead of cleared.!%
: introduce a pure goal (and leave the proof mode).!>
: introduce a modality by callingiModIntro
.!#
: introduce a modality by callingiModIntro
(deprecated)./=
: performsimpl
.//
: performtry done
on all goals.//=
: syntactic sugar for/= //
*
: introduce all universal quantifiers. (N.B.: this is the asterisk*
and not the separating conjunction∗
)**
: introduce all universal quantifiers, as well as all arrows and wands.
For example, given:
∀ x, <affine> ⌜ x = 0 ⌝ ⊢
□ (P → False ∨ □ (Q ∧ ▷ R) -∗
P ∗ ▷ (R ∗ Q ∧ ⌜ x = pred 2 ⌝)).
You can write
iIntros (x Hx) "!> $ [[] | #[HQ HR]] /= !>".
which results in:
x : nat
Hx : x = 0
______________________________________(1/1)
"HQ" : Q
"HR" : R
--------------------------------------□
R ∗ Q ∧ x = 1
Since we are reasoning in a spatial logic, when eliminating a lemma or
hypothesis of type P_0 -∗ ... -∗ P_n -∗ R
, one has to specify how the
hypotheses are split between the premises. The proof mode supports the following
specialization patterns to express splitting of hypotheses:
H
: use the hypothesisH
, which should match the premise exactly. IfH
is spatial, it will be consumed.(H spat1 .. spatn)
: first recursively specialize the hypothesisH
using the specialization patternsspat1 .. spatn
, and finally use the result of the specialization ofH
, which should match the premise exactly. IfH
is spatial, it will be consumed.[H1 .. Hn]
and[H1 .. Hn //]
: generate a goal for the premise with the (spatial) hypothesesH1 ... Hn
and all intuitionistic hypotheses. The spatial hypotheses amongH1 ... Hn
will be consumed, and will not be available for subsequent goals. Hypotheses prefixed with a$
will be framed in the goal for the premise. The pattern can be terminated with a//
, which causesdone
to be called to close the goal (after framing).[-H1 ... Hn]
and[-H1 ... Hn //]
: the negated forms of the above patterns, where the goal for the premise will have all spatial premises exceptH1 .. Hn
.[> H1 ... Hn]
and[> H1 ... Hn //]
: like the above patterns, but these patterns can only be used if the goal is a modalityM
, in which case the goal for the premise will be wrapped in the modalityM
.[> -H1 ... Hn]
and[> -H1 ... Hn //]
: the negated forms of the above patterns.[# $H1 .. $Hn]
and[# $H1 .. $Hn //]
: generate a goal for a persistent premise in which all hypotheses are available. This pattern does not consume any hypotheses; all hypotheses are available in the goal for the premise as well in the subsequent goal. The hypotheses$H1 ... $Hn
will be framed in the goal for the premise. These patterns can be terminated with a//
, which causesdone
to be called to close the goal (after framing).[%]
and[% //]
: generate a Coq goal for a pure premise. This pattern does not consume any hypotheses. The pattern can be terminated with a//
which causesdone
to be called to close the goal.[$]
: solve the premise by framing. It will first repeatedly frame and consume the spatial hypotheses, and then repeatedly frame the intuitionistic hypotheses. Spatial hypothesis that are not framed are carried over to the subsequent goal.[> $]
: like the above pattern, but this pattern can only be used if the goal is a modalityM
, in which case the goal for the premise will be wrapped in the modalityM
before framing.[# $]
: solve the persistent premise by framing. It will first repeatedly frame the spatial hypotheses, and then repeatedly frame the intuitionistic hypotheses. This pattern does not consume any hypotheses.
For example, given:
H : □ P -∗ P 2 -∗ R -∗ x = 0 -∗ Q1 ∗ Q2
One can write:
iDestruct ("H" with "[#] [H1 $H2] [$] [% //]") as "[H4 H5]".
Many of the proof mode tactics (such as iDestruct
, iApply
, iRewrite
) can
take both hypotheses and lemmas, and allow one to instantiate universal
quantifiers and implications/wands of these hypotheses/lemmas on the fly.
The syntax for the arguments of these tactics, called proof mode terms, is:
(H $! t1 ... tn with "spat1 .. spatn")
Here, H
can be either a hypothesis or a Coq lemma whose conclusion is
of the shape P ⊢ Q
. In the above, t1 ... tn
are arbitrary Coq terms used
for instantiation of universal quantifiers, and spat1 .. spatn
are
specialization patterns to eliminate implications and wands.
Proof mode terms can be written down using the following shorthand syntaxes, too:
(H with "spat1 .. spatn")
(H $! t1 ... tn)
H
If you came here looking for the wp_
tactics, those are described in the
HeapLang documentation.