Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • iris/iris
  • jeehoon.kang/iris-coq
  • amintimany/iris-coq
  • dfrumin/iris-coq
  • Villetaneuse/iris
  • gares/iris
  • shiatsumat/iris
  • Blaisorblade/iris
  • jihgfee/iris-coq
  • mrhaandi/iris
  • tlsomers/iris
  • Quarkbeast/iris-coq
  • janno/iris
  • amaurremi/iris-coq
  • proux/iris
  • tchajed/iris
  • herbelin/iris-coq
  • msammler/iris-coq
  • maximedenes/iris-coq
  • bpeters/iris
  • haidang/iris
  • lepigre/iris
  • lczch/iris
  • simonspies/iris
  • gpirlea/iris
  • dkhalanskiyjb/iris
  • gmalecha/iris
  • germanD/iris
  • aa755/iris
  • jules/iris
  • abeln/iris
  • simonfv/iris
  • atrieu/iris
  • arthuraa/iris
  • simonh/iris
  • jung/iris
  • mattam82/iris
  • Armael/iris
  • adamAndMath/iris
  • gmevel/iris
  • snyke7/iris
  • johannes/iris
  • NiklasM/iris
  • simonspies/iris-parametric-index
  • svancollem/iris
  • proux1/iris
  • wmansky/iris
  • LukeXuan/iris
  • ivanbakel/iris
  • SkySkimmer/iris
  • tjhance/iris
  • yiyunliu/iris
  • Lee-Janggun/iris
  • thomas-lamiaux/iris
  • dongjae/iris
  • dnezam/iris
  • Tragicus/iris
  • clef-men/iris
  • ffengyu/iris
59 results
Show changes
Commits on Source (5864)
*.v gitlab-language=coq
# Convert to native line endings on checkout.
*.ref text
# Shell scripts need Linux line endings.
*.sh eol=lf
*.vo
*.vos
*.vok
*.vio
*.v.d
.coqdeps.d
*.glob
*.cache
*.aux
......@@ -8,5 +11,17 @@
.\#*
*~
*.bak
.coqdeps.d
.coq-native/
*.crashcoqide
.env
builddep/
_CoqProject.*
Makefile.coq
Makefile.coq.conf
.Makefile.coq.d
Makefile.package.*
.Makefile.package.*
_opam
_build
*.install
image: coq:8.5
image: ralfjung/opam-ci:opam2
buildjob:
stages:
- build
variables:
CPU_CORES: "10"
OCAML: "ocaml-variants.4.14.0+options ocaml-option-flambda"
# Avoid needlessly increasing our TCB with native_compute
COQEXTRAFLAGS: "-native-compiler no"
.only_branches: &only_branches
only:
- /^master/@iris/iris
- /^ci/@iris/iris
.only_mr: &only_mr
only:
- merge_requests
.branches_and_mr: &branches_and_mr
only:
- /^master/@iris/iris
- /^ci/@iris/iris
- merge_requests
.template: &template
<<: *only_branches
stage: build
interruptible: true
tags:
- coq
- fp
script:
- coqc -v
- 'time make -j8 TIMED=y 2>&1 | tee build-log.txt'
- 'fgrep Axiom build-log.txt && exit 1'
- 'cat build-log.txt | egrep "[a-zA-Z0-9_/-]+ \(user: [0-9]" | tee build-time.txt'
- make validate
only:
- master
artifacts:
- git clone https://gitlab.mpi-sws.org/iris/ci.git ci -b opam2
- ci/buildjob
cache:
key: "$CI_JOB_NAME"
paths:
- build-time.txt
- _opam/
except:
- triggers
- schedules
- api
## Build jobs
# The newest version runs with timing.
build-coq.8.20.1:
<<: *template
variables:
OPAM_PINS: "coq version 8.20.1"
DENY_WARNINGS: "1"
MANGLE_NAMES: "1"
OPAM_PKG: "1"
DOC_DIR: "coqdoc@center.mpi-sws.org:iris"
DOC_OPTS: "--external https://plv.mpi-sws.org/coqdoc/stdpp/ stdpp"
tags:
- fp-timing
interruptible: false
# The newest version also runs in MRs, without timing.
build-coq.8.20.1-mr:
<<: *template
<<: *only_mr
variables:
OPAM_PINS: "coq version 8.20.1"
DENY_WARNINGS: "1"
MANGLE_NAMES: "1"
# Also ensure Dune works.
build-coq.8.20.1-dune:
<<: *template
<<: *branches_and_mr
variables:
OPAM_PINS: "coq version 8.20.1 dune version 3.15.2"
MAKE_TARGET: "dune"
# The oldest version runs in MRs, without name mangling.
build-coq.8.19.2:
<<: *template
<<: *branches_and_mr
variables:
OPAM_PINS: "coq version 8.19.2"
trigger-stdpp.dev:
<<: *template
variables:
STDPP_REPO: "iris/stdpp"
OPAM_PINS: "coq version $NIGHTLY_COQ git+https://gitlab.mpi-sws.org/$STDPP_REPO#$STDPP_REV"
CI_COQCHK: "1"
except:
only:
- triggers
- schedules
- api
<!--
When reporting a bug, please always include the version of Iris you are using.
If you are using opam, you can determine your Iris version by running
opam show coq-iris -f version
-->
In this changelog, we document "large-ish" changes to Iris that affect even the
way the logic is used on paper. We also mention some significant changes in the
Coq development, but not every API-breaking change is listed. Changes marked
`[#]` still need to be ported to the Iris Documentation LaTeX file(s).
way the logic is used on paper. We also document changes in the Coq
development; every API-breaking change should be listed, but not every new
lemma.
## Iris 3.0~rc1
## Iris master
This version matches the ESOP submission.
**Changes in `algebra`:**
* Add lemma `ufrac_auth_update_surplus_cancel`.
* Rename `CsumBot`, `GSetBot`, `CoPsetBot` and `ExclBot` to `*Invalid`.
* Add `agree_includedN`, `excl_included` and `excl_includedN`.
* Make the `algebra` folder (OFEs, COFEs, CMRAs, etc) parametric in the type of
"step indices" to prepare for the support of transfinite step indexing. This
is a large overhaul that involves nearly any file in the `algebra` folder:
(by Simon Spies and Lennard Gäher)
+ Introduce the interface [iris/algebra/stepindex.v](`sidx`), which abstracts
over the type of step indices `sidx`. The interface comes with operations
`0ᵢ`/`Sᵢ` and orders `<`/`≤` (overloaded in `sidx_scope`). The interface can
be instantiated by both `nat` (for finite step indexing, see
[iris/algebra/finite_stepindex.v](`finite_stepindex.v`)) and all sorts of
ordinal numbers (e.g., ω^2 or Aczel Trees for transfinite step indexing;
these instances are not yet present in this version of Iris).
+ Make all definitions in the `algebra` folder parametric in the type of
step indexing by adding an implicit argument `{SI : sidx}` (which always
comes first). In addition:
* OFE: Change the interface to use `dist_le` instead of `dist_S`. The smart
constructor `ofe_mixin_finite` can be used for backwards compatibility in
the case of finite step indexing.
* COFE: Extend the interface with a completion operator `lbcompl` for
"bounded chains". The smart constructor `cofe_finite` can be used to
obtain the additional limit operator for free in the case of finite step
indexing.
* LimitPreserving: Require bounded limits to be preserved too. The lemma
`limit_preserving_sidx_finite` provides the simplified definition in the
case of finite step indexing.
* CMRA: Change the interface to use `cmra_validN_le` instead of
`cmra_validN_S`.
+ Provide an instance `natSI` for finite step indexing based on the natural
numbers. Importing [iris/algebra/finite_stepindex.v](`finite_stepindex.v`)
has the side-effect of globally enabling finite step indexing (i.e., all
`SI : sidx` arguments will be resolved to the instance for finite step
indexing).
+ The COFE solver and the non-`algebra` parts of Iris (particularly, `bi`,
`base_logic`, `program_logic` and `heap_lang`) are not yet parametric in the
type of step indexing. They import `finite_stepindex.v` and therefore
enforce finite step indexing.
+ Remove the `si_solver` tactic and hint database. Either use the `SIdx`
lemmas manually, or in the case of finite step-indexing, use the wrappers
in [iris/algebra/finite_stepindex.v](`finite_stepindex.v`) that can be used
in combination with `lia`.
+ Rename `conv_compl'``conv_compl_S`.
**Changes in `base_logic`:**
* Add lemmas `own_forall` and `own_and` to reason about universal quantification
(`∀ .. own`) and conjunctions (`own .. ∧ own ..`) of ghost ownership. (by
Travis Hance)
+ These rules are derived from the new primitive rule `ownM_forall` (which is
proved in the `uPred` model).
+ Various corollaries for total cmras (which include `ucmra`s) are provided.
* Add lemma `Some_included_totalI`.
* Simplify lemma `excl_includedI` to use `=` instead of `match`.
**Changes in `bi`:**
* Merge the two `BiFUpdPlainly` laws `fupd_plainly_mask_empty` and
`fupd_plainly_keep_l` into a single law, by generalizing `fupd_plainly_keep_l`
so that it subsumes both of them.
* Change `WP` notation to allow type annotations and (exhaustive) patterns for
the return value binder.
* Rename `bi.lib.fixpoint` module to `bi.lib.fixpoint_mono`.
* Add `bi.lib.fixpoint_banach` module with lemmas for proving that a `fixpoint`
(of a contractive function) is persistent/affine/etc. (with help from William
Mansky)
* Remove the `bool`-valued `stuckness_leb`; use `stuckness_le` (in `Prop`)
instead.
**Changes in `proofmode`:**
* Generalize `AsEmpValid` to allow specifying which directions of the bi-implication
hold. This allows embedded logics to enable support for `iPoseProof` and `iStartProof`
independently. (by Michael Sammler)
**Changes in `heap_lang`:**
* Add `Inhabited lock_name` to `lock` class. (by Daniel Nezamabadi)
**Infrastructure:**
* Use `gmake` (GNU Make) instead of `make` on BSD systems. (by Yiyun Liu)
The following `sed` script helps adjust your code to the renaming (on macOS,
replace `sed` by `gsed`, installed via e.g. `brew install gnu-sed`).
Note that the script is not idempotent, do not run it twice.
```
sed -i -E -f- $(find theories -name "*.v") <<EOF
# "*Bot* RA element rename
s/\b(Csum|GSet|CoPset|Excl)Bot(\b|_)/\\1Invalid\\2/g
# bi.lib.fixpoint rename: adjust imports
s/(From iris.* Require .*|Require iris.*)\bfixpoint\b/\\1fixpoint_mono/g
EOF
```
## Iris 4.3.0 (2024-10-30)
This Iris release mostly features quality-of-life improvements, such as
improvements to `iInduction`, a new `iUnfold` tactic, and improved errors
in `iInv`. Furthermore, like std++, Iris can now be built with dune.
Iris 4.3.0 supports Coq 8.19 and 8.20. Coq 8.18 is no longer supported.
This release was managed by Jesper Bengtson, Ralf Jung and Robbert Krebbers,
with contributions from Benjamin Peters, Isaac van Bakel, Jan-Oliver Kaiser,
Janggun Lee, Michael Sammler, Ralf Jung, Robbert Krebbers, Rodolphe Lepigre
Sanjit Bhat, Tej Chajed, William Mansky, and Yusuke Matsushita.
Thanks a lot to everyone involved!
**Changes in `algebra`:**
* Add lemmas `big_opS_gset_to_gmap` and `big_opS_gset_to_gmap_L`, which rewrite
between `gset_to_gmap` and big set ops of singleton maps. (by Isaac van
Bakel)
* Add lemmas `discrete_fun_update` and `discrete_fun_updateP`, which updates an
abitrary `discrete_fun` to another. For `discrete_fun_updateP`, this requires
the domain to be finite, similar to `discrete_fun_included_spec`. (by Janggun Lee)
* Add lemmas `discrete_fun_singleton_valid` and `discrete_fun_singleton_unit`, which simplify
cmra validity and unit used with `discrete_fun_singleton`. (by Janggun Lee)
* Add `Inhabited` instance for the solution of the COFE solver.
**Changes in `bi`:**
* Add instances for `match _ with _ end` (and thus `if _ then _ else` and
`'(_, _)` pair destructuring) for `Persistent`, `Affine`, `Absorbing`,
`Timeless`, and `Plain`. (by Sanjit Bhat)
**Changes in `proofmode`:**
* Remove the `*` specialization pattern. This pattern has been deprecated and a
no-op since 2017. See https://gitlab.mpi-sws.org/iris/iris/-/merge_requests/41.
* Improve the error message of `iInv` in case the goal does not support
invariant opening.
* Change `iInduction` to always generate a magic wand instead of sometimes
generating an implication for reverted hypotheses.
* Add `iUnfold` tactic.
* Improve ability to name induction hypotheses (IHs) in `iInduction`: when
performing `iInduction x as cpat` the names of the IHs in the Coq introduction
pattern `cpat` are used to name the IHs in the proof mode context. For
example, `iInduction n as [|n IH]` and `iInduction t as [|l IHl r IHr]`.
**Changes in `base_logic`:**
* Add lemma `na_own_empty` and persistence instance for `na_own p ∅` for
non-atomic invariant tokens. (by Benjamin Peters)
* Add instances `big_sepL_flip_mono'`, `big_sepM_flip_mono'`, etc., which are
wrappers of instances `big_sep*_mono'` for `flip (⊢)` instead of `(⊢)`. (by
Yusuke Matsushita)
**Changes in `program_logic`:**
* Add missing proofmode instances for error reporting and opening invariants
around total weakest preconditions. (by Janggun Lee)
**Changes in `heap_lang`:**
* Make `wp_cmpxchg_fail` work when the points-to is in the persistent context.
* Seal definition of `pointsto`, add copies of all relevant lemmas.
**Infrastructure:**
* Add support for compiling the packages with dune. (by Rodolphe Lepigre)
## Iris 4.2.0 (2024-04-12)
The highlights of this release are:
* We have new laws to "undiscard" discarded fractions, allowing one to update
from `DfracDiscarded` to `DfracOwn(q)` for some fresh `q`. This gives rise to
new laws for all constructions that use `dfrac`, such as
`ghost_map_elem_unpersist : ∀ k γ v, k ↪[γ]□ v ==∗ ∃ q, k ↪[γ]{#q} v`.
* The `gmap_view K V` camera now supports value types `V` that are arbitrary
cameras, and lifts their composition to the whole map. The previous `gmap_view`
type can be recovered as `gmap_view K (agree V)`.
* The `iFrame` tactic has become stronger for goals that contain existential
quantifiers: `iFrame` will now attempt to instantiate these. For example,
framing `P x` in goal `Q ∗ ∃ y, P y ∗ R` will now succeed with remaining
goal `Q ∗ R`.
Iris 4.2 supports Coq 8.18 and 8.19.
Coq 8.16 and 8.17 are no longer supported.
This release was managed by Ralf Jung and Robbert Krebbers, with contributions
from Ike Mulder, Jan-Oliver Kaiser, Johannes Hostert, Pierre Roux, Thomas
Somers, and Yixuan Chen. Thanks a lot to everyone involved!
**Changes in `algebra`:**
* Rename `discrete` to `discrete_0`, to make room for a new lemma `discrete`
that works for all `n` : `x ≡{n}≡ y → x ≡ y`.
* Enable `f_equiv` and `solve_proper` to exploit the fact that `≡{n}≡` is a
subrelation of `≡` and `=`.
* Rename `iso_cmra_mixin_restrict` to `iso_cmra_mixin_restrict_validity`, and
simplify its statement and that of `iso_cmra_mixin` by removing the `g_equiv`
assumption that follows from the other assumptions.
* Add `inj_cmra_mixin_restrict_validity` as a more general version of
`iso_cmra_mixin_restrict_validity`.
* Change statement of `Z_local_update` to be more intuitive. It now says
`x - y = x' - y' → (x,y) ~l~> (x',y')`, i.e., the difference between the
authoritative element and the fragment must stay the same.
* Rename `cmra_discrete_update``cmra_discrete_total_update` and
`cmra_discrete_updateP``cmra_discrete_total_updateP`. Repurpose original
names for lemmas that only require `CmraDiscrete`, not `CmraTotal`.
* Add a law for undiscarding discarded fractions, allowing one to update from
`DfracDiscarded` to `DfracOwn(q)` for some fresh `q`. This formalizes the
intuition that a discarded fraction is merely an "existentially quantified
fraction." (by Johannes Hostert)
* Add laws for un-persisting resources with a discardable fractional part,
based on the undiscarding law for discardable fractions. For example,
`gmap_view_frag k DfracDiscarded v ~~>: λ a, ∃ q, a = gmap_view_frag k (DfracOwn q) v`
will allow recovering a fractional points-to from a discarded one. (by Johannes
Hostert)
* Generalize `gmap_viewUR K A` from `A : ofe` to `A : cmra`. Previously, the
"agreement" camera was part of the definition, now the user can pick an
arbitrary camera. All lemmas that exposed agreement properties have
been generalized to expose general camera validity/composition.
For porting:
+ Replace `gmap_viewR K V` by `gmap_viewR K (agreeR V)`.
+ Definitions and proofs on top of this will need to be manually adjusted.
+ Replace `gmap_view_update` by `gmap_view_replace`.
+ Proofs using `gmap_view_both_dfrac_valid_L` should instead use
`gmap_view_both_dfrac_valid_discrete_total` followed by `to_agree_included_L`.
**Changes in `proofmode`:**
* The `iFrame` tactic has become slightly weaker for goals that contain both
evars and either `∨` or `∧`. This prevents an exponential slowdown of
`iFrame` on some goals. This change should be backwards compatible for almost
all proofs. If you define or use custom `Frame` instances, note that the
`MaybeFrame` class has become notation for `TCNoBackTrack (MaybeFrame' ...)`,
which means the proofs of your instances might need a slight refactoring.
* Adjust the `iFrame` proof search to use `QuickAffine` and `QuickAbsorbing`
instead of `Affine` and `Absorbing`. This fixes some performance issues with
large terms in non-affine logics, at the expense of a slight reduction in what
`iFrame` can do in these logics.
* The `iFrame` tactic has become stronger for goals that contain existential
quantifiers: `iFrame` will now attempt to instantiate these. For example,
framing `P x` in goal `Q ∗ ∃ y, P y ∗ R` will now succeed with remaining
goal `Q ∗ R`. `iFrame` still behaves the same when no instantiation can be
found: framing `R` in goal `Q ∗ ∃ y, P y ∗ R` still gives `Q ∗ ∃ y, P y`.
This should simplify and potentially even speed up some proofs (MR: iris/iris!1017).
Porting to this change will require manually fixing broken proofs: `iFrame`
may now make more progress than your proof script expects. Proofs that look
like `iFrame. iExists _. iFrame.` may need to be replaced with just `iFrame.`
In some cases, you may need to be explicit in what hypotheses to `iFrame`,
to prevent wrong instantiation of existential quantifiers.
To temporarily fix broken proofs, you can restore `iFrame`'s old behavior with:
```
Local Instance frame_exist_instantiate_disabled :
FrameInstantiateExistDisabled := {}.
```
`iFrame` will not instantiate existential quantifiers below connectives such as
`-∗`, `∀`, `→` and `WP`, since this is more frequently unsafe (MR: iris/iris!1035).
If you have custom recursive `Frame` instances for which you want to disable
instantiating existential quantifiers, you need to replace the `Frame ...` premise
of your instance with `(FrameInstantiateExistDisabled → Frame ...)`.
* `iFrame` no longer loops on `[∗mset ] x ∈ X, ..` when `X` is an existential variable
(MR: iris/iris!1039). (by Jan-Oliver Kaiser for BedRock Systems)
**Changes in `base_logic`:**
* Rename `mapsto` to `pointsto` to align with standard separation logic
terminology.
* Add laws for un-persisting assertions with a discardable fractional permission,
for example `l ↦□ v ==∗ ∃ q, l ↦{#q} v`, using the new laws from `algebra`
(see above). These laws allow one to update a persistent (discarded) assertion,
like a points-to, back into a fractionally owned one, where the fraction is
existentially quantified. They are useful when e.g. constructing invariants
that allow exchanging fractional assertions. See !960 for more details. (by
Johannes Hostert)
* Add `token` library, providing a simple ghost token as a logic-level wrapper
over the RA `excl unit`.
* Add lemma `lc_fupd_add_laterN`. (by Thomas Somers)
**Changes in `program_logic`:**
* Rename `head_step` to `base_step` to avoid potential confusion with the
standard term "head reduction", and also rename all associated definitions and
lemmas. In particular: `head_stuck``base_stuck`, `head_reducible`
`base_reducible`, `head_irreducible``base_irreducible`, `head_redex`
`base_redex`, `head_atomc``base_atomic`. The sed script will rename all
definitions and lemmas that come with Iris, but if you had additional
definitions or lemmas with `head` in their name, you will have to rename them
by hand if you want to remain consistent.
**Changes in `heap_lang`:**
* Replace `wp_lb_init` with a more general `steps_lb_0` lemma for creating a
`steps_lb` without depending on WP. (by Thomas Somers)
* Add generic lemma `twp_wp_step_lc` to derive WP with later credits from TWP.
* Add Texan triples with later credits for stateful operations: `wp_alloc_lc`,
`wp_alloc_lc`, `wp_free_lc`, `wp_load_lc`, `wp_store_lc`, `wp_xchg_lc`,
`wp_cmpxchg_fail_lc`, `wp_cmpxchg_suc_lc`, and `wp_faa_lc`.
The following `sed` script helps adjust your code to the renaming (on macOS,
replace `sed` by `gsed`, installed via e.g. `brew install gnu-sed`).
Note that the script is not idempotent, do not run it twice.
```
sed -i -E -f- $(find theories -name "*.v") <<EOF
# discrete camera updates
s/\bcmra_discrete_update\b/cmra_discrete_total_update/g
s/\bcmra_discrete_updateP\b/cmra_discrete_total_updateP/g
# maps-to → points-to
s/(\b|_)mapsto(\b|_)/\1pointsto\2/g
# Head reduction
s/(\b|_)head_(step|stuck|ctx|prim_|(ir)?reducible)/\1\base_\2/g
EOF
```
## Iris 4.1.0 (2023-10-11)
This Iris release mostly features quality-of-life improvements, such as smarter
handling of `->`/`<-` patterns by `iDestruct`, support for an arbitrary number of
Coq intro patterns in the Iris proofmode tactics (`iIntros`, `iDestruct`, etc.),
and support for immediately introducing the postcondition of a WP specification
via `wp_apply lemma as "Hpost"`.
The biggest changes and new features are:
* Logically atomic triples now support private (non-atomic) postconditions, and
the notation was changed to not clash with Autosubst any more. Existing users
of logically atomic specifications have to update their notation, see the full
CHANGELOG for more details.
* The meaning of `P -∗ Q` as a Coq proposition has changed from `P ⊢ Q` to
`⊢ P -∗ Q`. If you are only using the Iris proofmode, this will not make a
difference, but when writing proof scripts or tactics that `rewrite` or
`apply` Iris lemmas, the exact position of the `⊢ P -∗ Q` matters and this
will now always be visible in lemma statements.
* `iCombine` is starting to gain support for a `gives` clause, which yields
persistent facts gained from combining the resources. So far, this remains
mostly experimental. We support `↦` and the connectives of ghost theories in
`base_logic/lib`, but support for `own` and custom cameras is minimal and will
be improved in future releases.
* Some initial refactoring prepares Iris for eventually supporting transfinite step-indexing.
* New resources algebras have been added: `Z`, `max_Z`, `mono_Z`, and `mra` (the
monotone resource algebra of https://iris-project.org/pdfs/2021-CPP-monotone-final.pdf)
Iris 4.1 supports Coq 8.16-8.18. Coq 8.13-8.15 are no longer supported.
This release was managed by Ralf Jung, Robbert Krebbers, and Johannes Hostert,
with contributions from Amin Timany, Arthur Azevedo de Amorim, Armaël Guéneau,
Benjamin Peters, Dan Frumin, Dorian Lesbre, Ike Mulder, Isaac van Bakel, Jaemin
Choi, Janine Lohse, Jan-Oliver Kaiser, Jonas Kastberg Hinrichsen, Lennard Gäher,
Mathias Adam Møller, Michael Sammler, Paolo Giarrusso, Pierre Roux, Rodolphe
Lepigre, Simcha van Collem, Simon Friis Vindum, Simon Spies, Tej Chajed, Yixuan
Chen, and Yusuke Matsushita. Thanks a lot to everyone involved!
**Changes in `prelude`:**
* Re-export `stdpp.options` from `iris.prelude.options`. This enables 'light'
name mangling, which prefixes auto-generated names with `__`. This only
affects developments that explicitly opt-in to following the Iris
configuration by importing `iris.prelude.options`.
**Changes in `algebra`:**
* Add (basic) support for `gset` and `gset_disj` cameras to `set_solver`.
* Rename `sig_{equiv,dist}_alt` into `sig_{equiv,dist}_def` and state these
lemmas using `=` instead of `<->`.
* Add custom entry `dfrac` that can be used for `{dq}` / `□` / `{# q}`
annotation of connectives with a discardable fraction.
* Add an RA on the `Z` type of integers, using addition for `⋅`.
* Prepare Iris to generalize the type of step-indices. This is a large series of
changes; more changes will follow later. More documentation will follow as
part of
[this merge request](https://gitlab.mpi-sws.org/iris/iris/-/merge_requests/888).
- Change the definition of `dist_later` to an equivalent definition that is
future-proof with respect to general step-indices.
- Change the definition of the properties of an `ofe` to be slightly more
general and future proof (i.e., change `dist_S` into `dist_lt`).
- Adapt `f_contractive` to work with the new definition of `dist_later`.
For backwards compatibility for existing developments, the tactic
`f_contractive_fin` is provided. It uses the old definition of `dist_later`,
now called `dist_later_fin`.
- If you need to deal with a `dist_later`/`dist_later_fin` in a manual proof,
use the tactic `dist_later_intro`/`dist_later_fin_intro` to introduce it.
(by Michael Sammler, Lennard Gäher, and Simon Spies)
* Add `max_Z` and `mono_Z` cameras.
* Add `dfrac_valid`.
* Rename `Some_included_2` to `Some_included_mono`.
* Consistently use `Some x ≼ Some y` to express the reflexive closure of
`x ≼ y`. This changes the statements of some lemmas: `singleton_included`,
`local_update_valid0`, `local_update_valid`. Also add various new
`Some_included` lemmas to help deal with these assertions.
* Add hints for `a ≼ a ⋅ _` / `a ≼ _ ⋅ a` / `ε ≼ _` / `_ ≼ CsumBot` /
`_ ≼ ExclBot` with cost 0, which means they are used by `done` to finish
proofs. (by Ike Mulder)
* Rename `singleton_mono` to `singleton_included_mono`.
* Use `Strategy expand` for CMRA/UCMRA coercions and most projections to improve
performance of type-checking some large CMRA/OFE types. (by Ike Mulder)
* Add monotone resource algebra, `algebra/mra.v`, to enable reasoning about
monotonicity with respect to an arbitrary preorder relation: the extension order
of `mra R` is designed to embed the preorder relation `R`. (by Amin Timany)
* Rename instances `union_with_proper``union_with_ne`,
`map_fmap_proper``map_fmap_ne`, `map_zip_with_proper``map_zip_with_ne`.
* Rename `dist_option_Forall2``option_dist_Forall2`. Add similar lemma
`list_dist_Forall2`.
* Add instances `option_fmap_dist_inj` and `list_fmap_dist_inj`.
* Rename `list_dist_cons_inv_r``cons_dist_eq` and remove
`list_dist_cons_inv_l` to be consistent with `cons_equiv_eq` in std++.
(If you needed `list_dist_cons_inv_l`, you can apply `symmetry` and
then use `cons_dist_eq`.)
Add similar lemmas `nil_dist_eq`, `app_dist_eq`, `list_singleton_dist_eq`,
`dist_Permutation`.
**Changes in `bi`:**
* Use `binder` in notations for big ops. This means one can write things such
as `[∗ map] '(k,_) ↦ '(_,y) ∈ m, ⌜ k = y ⌝`.
* Add constructions `bi_tc`/`bi_nsteps` to create the transitive/`n`-step
closure of a PROP-level binary relation. (by Simcha van Collem)
* Make the `unseal` tactic of `monPred` more consistent with `uPred`:
+ Rename `MonPred.unseal``monPred.unseal`
+ No longer unfold derived BI connectives `<affine>`, `<absorb>` and `◇`.
* Make `monPred.unseal` tactic more robust by using types to unfold the right
BI projections.
* Add `unseal` tactic for `siProp`.
* Add compatibility lemmas for `big_sepL <-> big_sepL2`, `big_sepM <-> big_sepM2`
with list/maps of pairs; and `big_sepM <-> big_sepL` via `list_to_map` and
`map_to_list`. (by Dorian Lesbre)
* Make `persistently_True` a bi-entailment; this changes the default `rewrite`
direction.
* Make `BiLaterContractive` a class instead of a notation.
* Make projections of `Bupd`/`Fupd`/`InternalEq`/`Plainly` operational type
classes `Typeclasses Opaque`.
* Make BI relations (`bi_rtc`, `bi_tc`, `bi_nsteps`) typeclasses opaque (they
were accidentally transparent).
* Make the `P -∗ Q` notation in stdpp_scope (i.e., outside of bi_scope) a
shorthand for `⊢ P -∗ Q` rather than `P ⊢ Q`. This means that any BI notation
used in stdpp_scope will be sugar for adding a leading `⊢` (`bi_emp_valid`).
It also means that `apply` becomes sensitive to the difference between `P ⊢ Q`
and `P -∗ Q`, and `rewrite` will only work with lemmas that are explicitly
written using `⊢`.
When a proof breaks, there are generally 3 options:
- Try to find the `-∗` that should be turned into a `⊢` so that things work
like before.
- Adjust the proof to use proof mode tactics rather than Coq tactics (in
particular, replace `apply` by `iApply`).
- Add some `apply bi.entails_wand`/`apply bi.wand_entails` to 'convert'
between the old and new way of interpreting `P -∗ Q`.
* Add `auto` hint to introduce the BI version of `↔`.
* Change `big_sepM2_alt` to use `dom m1 = dom2 m2` instead of
`∀ k, is_Some (m1 !! k) ↔ is_Some (m2 !! k)`. The old lemma is still
available as `big_sepM2_alt_lookup`.
* Overhaul `Fractional`/`AsFractional`:
- Remove `AsFractional → Fractional` instance.
- No longer use `AsFractional P Φ q` backwards, from `Φ` and `q` to `P` -- just
use `Φ q` instead.
- Remove multiplication instances (that also go from `AsFractional` to
`Fractional`, making it very hard to reason about search termination).
- Rewrite `frame_fractional` lemma using the new `FrameFractionalQp` typeclass
for `Qp` reasoning.
- Change statements of `fractional_split`, `fractional_half`, and
`fractional_merge` to avoid using `AsFractional` backwards, and only keep
the bi-directional versions (remove `fractional_split_1`,
`fractional_split_2`, `fractional_half_1`, `fractional_half_2`).
`iDestruct`/`iCombine`/`iSplitL`/`iSplitR` should be used instead.
* Add missing transitivity, symmetry and reflexivity lemmas about the `↔`, `→`,
`-∗` and `∗-∗` connectives. (by Ike Mulder)
* Add `∗-∗` as notation in `stdpp_scope` similar to `-∗`. This means `P ∗-∗ Q`
can be directly used as lemma statement, and is syntactic sugar for `⊢ P ∗-∗ Q`.
* Add `≼` connective (`internal_included`) on the BI level. (by Ike Mulder)
* Move laws of persistence modality out of `BiMixin` into `BiPersistentlyMixin`.
* Provide smart constructor `bi_persistently_mixin_discrete` for
`BiPersistentlyMixin`: Given a discrete BI that enjoys the existential
property, a trivial definition of the persistence modality can be given.
* Fix `greatest_fixpoint_ne'` accidentally being about the least fixpoint.
* Add `Plain` instance for `|==> P` when `P` is plain.
* Rename `bupd_plain``bupd_elim`.
* Change notation for atomic updates and atomic accessors to use `<{ ... }>`
instead of `<< ... >>`. This avoids a conflict with Autosubst.
**Changes in `proofmode`:**
* The proof mode introduction patterns "<-" and "->" are considered
intuitionistic. This means that tactics such as `iDestruct ... as "->"` will
not dispose of hypotheses to perform the rewrite.
* Remove tactic `iSolveTC` in favor of `tc_solve` in std++.
* The result of `iCombine` is no longer computed with the `FromSep` typeclass,
but with a new `CombineSepAs` typeclass. If you provide custom `FromSep`
instances and use the `iCombine` tactic, you will need to define additional
`CombineSepAs` instances. This is done in preparation for making `iCombine`
combine propositions in ways that are not appropriate for how `FromSep` is used.
Note that `FromSep` is still used for determining the new goals when applying
the `iSplitL` and `iSplitR` tactics.
* The `iCombine` tactic now accepts an (optional) 'gives' clause, with which one
can learn persistent facts from the combination of two hypotheses. One can
register such 'gives' clauses by providing instances of the new
`CombineSepGives` typeclass. The 'gives' clause is still experimental;
in future versions of Iris it will combine `own` connectives based on the
validity rules for cameras.
* Make sure that `iStartProof` fails with a proper error message on goals with
`let`. These `let`s should either be `simpl`ed or introduced into the Coq
context using `intros x`, `iIntros (x)`, or `iIntros "%x"`.
This can break some proofs that did `iIntros "?"` on a goal of the shape
`let ... in P ⊢ Q`.
* Make `iApply`/`iPoseProof`/`iDestruct` more reliable for lemmas whose
statement involves `let`.
* Remove `string_to_ident`; use `string_to_ident_cps` instead which is in CPS
form and hence does not require awful hacks.
* The `iFrame` tactic now removes some conjunctions and disjunctions with `False`,
since additional `MakeOr` and `MakeAnd` instances were provided. If you use these
classes, their results may have become more concise.
* Support n-ary versions of `iIntros`, `iRevert`, `iExists`, `iDestruct`, `iMod`,
`iFrame`, `iRevertIntros`, `iPoseProof`, `iInduction`, `iLöb`, `iInv`, and
`iAssert`. (by Jan-Oliver Kaiser and Rodolphe Lepigre)
* Add tactics `ltac1_list_iter` and `ltac1_list_rev_iter` to iterate over
lists of `ident`s/`simple intropatterns`/`constr`/etc using Ltac1. See
[proofmode/base.v](iris/proofmode/base.v) for documentation on how
to use these tactics to convert your own fixed arity tactics to an n-ary
variant.
* Improve the `IntoPure` instance for internal equality. Whenever possible,
`a ≡ b` will now be simplified to `a = b` upon introduction into the pure
context. This will break but simplify some existing proofs:
`iIntros (H%leibniz_equiv)` should be replaced by `iIntros (H)`. (by Ike Mulder)
**Changes in `base_logic`:**
* Add `mono_Z` library for monotone non-negative integers.
(This has exactly the same lemmas as `mono_nat`. It is useful in cases
where one wants to avoid `nat` entirely and use `Z` throughout.)
* Add `IsExcept0` instance for invariants, allowing you to remove laters of
timeless hypotheses when proving an invariant (without an update).
* Make `uPred.unseal` tactic more robust by using types to unfold the right
BI projections.
* Turn `internal_eq_entails` into a bi-implication.
* Add lemmas to relate internal/external non-expansiveness and contractiveness.
* Refactor soundness lemmas: `bupd_plain_soundness``bupd_soundness`,
`soundness``laterN_soundness` + `pure_soundness`; removed
`consistency_modal`.
* Strengthen `cmra_valid_elim` to `✓ a ⊢ ⌜ ✓{0} a ⌝`; make `discrete_valid` a
derived law.
* Remove `frac_validI`. Instead, move to the pure context (with `%` in the proof
mode or `uPred.discrete_valid` in manual proofs) and use `frac_valid`.
**Changes in `program_logic`:**
* Change the notation for logically atomic triples: we add support for specifying private (non-atomic) postconditions,
and we avoid a notation conflict with Autosubst. The new notation looks as follows:
`<<{ ∀∀ x, atomic_pre x }>> code @ ∅ <<{ ∃∃ y, atomic_post x y | z, RET v, non_atomic_post x y z }>>`.
To keep the notation without private postcondition consistent, the way the return value is specified changes slightly
even when there is no private postcondition:
`<<{ ∀∀ x, atomic_pre x }>> code @ ∅ <<{ ∃∃ y, atomic_post x y | RET v }>>`.
**Changes in `heap_lang`:**
* Move operations and lemmas about locations into a module `Loc`.
* Extend `wp_apply` and `wp_smart_apply` to support immediately introducing the
postcondition into the context via `as (x1 ... xn) "ipat1 ... ipatn"`.
* Add comparison `≤` and `<` for locations. (by Arthur Azevedo de Amorim)
* Make the generic `lock` interface a typeclass and make sure the lock code
does not depend on `Σ`. Code that is generic about lock implementations, or
that instantiates that specification, needs adjustment. See
[iris_heap_lang/lib/lock.v](iris_heap_lang/lib/lock.v) for documentation on
how to work with this specification.
* Adjust the generic `atomic_heap` interface to follow the same pattern as
`lock`.
* Add a generic `rwlock` interface and a spinning implementation.
(by Isaac van Bakel)
**LaTeX changes:**
- Rename `\Alloc` to `\AllocN` and `\Ref` to `\Alloc` for better consistency
with the Coq names and to avoid clash with hyperref package.
The following `sed` script helps adjust your code to the renaming (on macOS,
replace `sed` by `gsed`, installed via e.g. `brew install gnu-sed`).
Note that the script is not idempotent, do not run it twice.
```
sed -i -E -f- $(find theories -name "*.v") <<EOF
# iSolveTC
s/iSolveTC\b/tc_solve/g
# _alt -> _def
s/\bsig_equiv_alt\b/sig_equiv_def/g
s/\bsig_dist_alt\b/sig_dist_def/g
# Loc
s/\bloc_add(_assoc|_0|_inj|)\b/Loc.add\1/g
s/\bfresh_locs(_fresh|)\b/Loc.fresh\1/g
# unseal
s/\bMonPred\.unseal\b/monPred\.unseal/g
# big op
s/\bbig_sepM2_alt\b/big_sepM2_alt_lookup/g
s/\bbupd_plain\b/bupd_elim/g
# Logical atomicity (will break Autosubst notation!)
s/<<</<<\{/g
s/>>>/\}>>/g
# option and list
s/\bdist_option_Forall2\b/option_dist_Forall2/g
s/\blist_dist_cons_inv_r\b/cons_dist_eq/g
EOF
```
The following sed script helps adjust LaTeX documents to these changes:
Note that the script is not idempotent, do not run it twice.
```
sed -i -E -f- *.tex <<EOF
# Alloc & Ref
s/\\Alloc\b/\\AllocN/g
s/\\Ref\b/\\Alloc/g
EOF
```
## Iris 4.0.0 (2022-08-18)
The highlight of Iris 4.0 is the *later credits* mechanism, which provides a new
way to eliminate later modalities.
This new mechanism complements the existing techniques of taking program steps,
exploiting timelessness, and various modality commuting rules. At each program
step, one obtains a credit `£ 1`, which is an ownable Iris resource. These
credits don't have to be used at the present step, but can be saved up, and used
to eliminate laters at any point in the verification using the fancy update
modality. Later credits are particularly useful in proofs where there is not a
one-to-one correspondence between program steps and later eliminations, for
example, logical atomicity proofs. As a consequence, we have been able to
simplify the definition of logical atomicity by removing the 'laterable'
mechanism.
The later credit mechanism is described in detail in the
[ICFP'22 paper](https://plv.mpi-sws.org/later-credits/) and there is a
[small tutorial](https://gitlab.mpi-sws.org/iris/iris/-/blob/iris-4.0.0/tests/later_credits_paper.v)
in the Iris repository. The
[examples](https://gitlab.mpi-sws.org/iris/examples/) repository contains some
logically atomic case studies that make use of later credits: the counter with a
backup (Section 4 of the later credits paper), as well as the elimination stack,
conditional increment, and RDCSS.
Iris 4.0 supports Coq 8.13 - 8.16.
This release was managed by Ralf Jung, Robbert Krebbers, and Lennard Gäher, with
contributions from Glen Mével, Gregory Malecha, Ike Mulder, Irene Yoon,
Jan-Oliver Kaiser, Jonas Kastberg Hinrichsen, Lennard Gäher, Michael Sammler,
Niklas Mück, Paolo G. Giarrusso, Ralf Jung, Robbert Krebbers, Simon Spies,
and Tej Chajed. Thanks a lot to everyone involved!
**General changes:**
- Rename "unsealing" lemmas from `_eq` to `_unseal`. This particularly
affects `envs_entails_eq`, which is commonly used in the definition of
custom proof mode tactics. All other unsealing lemmas should be internal, so
in principle you should not rely on them.
- Rename `coq-iris-staging` package to `coq-iris-unstable`, and also change the
import path from `iris.staging` to `iris.unstable`.
**Changes in `algebra`:**
* Add some missing algebra functors: `dfrac_agreeRF`, `excl_authURF`, `excl_authRF`,
`frac_authURF`, `frac_authRF`, `ufrac_authURF`, `ufrac_authRF`, `max_prefix_listURF`,
`max_prefix_listRF`, `mono_listURF`, and `mono_listRF`.
* Make validy lemmas for `excl_auth` more consistent with `auth`.
- Rename `excl_auth_frag_validN_op_1_l` into `excl_auth_frag_op_validN` and
`excl_auth_frag_valid_op_1_l` into `excl_auth_frag_op_valid` (similar to
`auth_auth_op_valid`), and make them bi-implications.
- Add `excl_auth_auth_op_validN` and `excl_auth_auth_op_valid`.
* Make validy lemmas for `(u)frac_auth` more consistent with `auth`.
- Remove unidirectional lemmas with `1` fraction `frac_auth_frag_validN_op_1_l`
and `frac_auth_frag_valid_op_1_l`
- Add `frac_auth_frag_op_validN` and `frac_auth_frag_op_valid`, which are
bi-implications with arbitrary fractions.
- Add `ufrac_auth_frag_op_validN` and `ufrac_auth_frag_op_valid`.
* Remove `mono_list_lb_is_op` instance for `IsOp' (◯ML l) (◯ML l) (◯ML l)`; we
don't usually have such instances for duplicable resources and it was added by
accident.
* Rename `pos_op_plus` into `pos_op_add`.
**Changes in `bi`:**
* Generalize `big_op` lemmas that were previously assuming `Absorbing`ness of
some assertion: they now take any of (`TCOr`) an `Affine` instance or an
`Absorbing` instance. This breaks uses where an `Absorbing` instance was
provided without relying on TC search (e.g. in `by apply ...`; a possible fix
is `by apply: ...`). (by Glen Mével, Bedrock Systems)
* Change statement of `affinely_True_emp` to also remove the affinely modality.
* Rename `absorbingly_True_emp` to `absorbingly_emp_True` and make statement
consistent with `affinely_True_emp`: `<absorb> emp ⊣⊢ True`.
* Change the notation for atomic updates and atomic accessors (`AU`, `AACC`) to
swap the quantifiers: the first quantifier is logically an existential, the
second a universal, so let's use the appropriate notation. Also use double
quantifiers (`∀∀`, `∃∃`) to make it clear that these are not normal
quantifiers (the latter change was also applied to logically atomic triples).
* Add some lemmas to show properties of functions defined via monotonoe fixpoints:
`least_fixpoint_affine`, `least_fixpoint_absorbing`,
`least_fixpoint_persistent_affine`, `least_fixpoint_persistent_absorbing`,
`greatest_fixpoint_absorbing`.
* Rename `laterN_plus` into `laterN_add`.
* Remove `make_laterable` from atomic updates. This relies on Iris now having
support for later credits (see below).
* Add `Fractional` and `AsFractional` instances for `embed` such that the
embedding of something fractional is also fractional. (by Simon Friis Vindum).
**Changes in `proofmode`:**
* Change `iAssumption` to no longer instantiate evar premises with `False`. This
used to occur when the conclusion contains variables that are not in scope of
the evar, thus blocking the default behavior of instantiating the premise with
the conclusion. The old behavior can be emulated with`iExFalso. iExact "H".`
* In `iInduction`, support induction schemes that involve `Forall` and
`Forall2` (for example, for trees with finite branching).
* Change `iRevert` of a pure hypothesis to generate a magic wand instead of an
implication.
* Change `of_envs` such that when the persistent context is empty, the
persistence modality no longer appears at all. This is a step towards using
the proofmode in logics without a persistence modality.
The lemma `of_envs_alt` shows equivalence with the old version.
* Adjust `IntoWand` instances for non-affine BIs: in many cases where
`iSpecialize`/`iApply` of an implication previously failed, it will now
instead add an `<affine>` modality to the newly generated goal. In some rare
cases it might stop working or add an `<affine>` modality where previously
none was added.
**Changes in `base_logic`:**
* Make the `inG` instances for `libG` fields local, so they are only used inside
the library that defines the `libG`.
* Add infrastructure for supporting later credits, by adding a resource `£ n`
describing ownership of `n` credits that can be eliminated at fancy updates.
+ To retain backwards compatibility with the interaction laws of fancy updates
with the plainly modality (`BiFUpdPlainly`), which are incompatible with
later credits, the logic has a new parameter of type `has_lc`, which is
either `HasLc` or `HasNoLc`. The parameter is an index of the `invGS_gen`
typeclass; the old `invGS` is an alias for `invGS_gen HasLc` so that
developments default to having later credits available. Libraries that want
to be generic over whether credits are available or not, and proofs that
need `BiFUpdPlainly`, need to be changed to use `invGS_gen` rather than
`invGS`.
+ The core soundness lemma `step_fupdN_soundness_gen` similarly takes a `has_lc`
parameter to control how the logic is supposed to be instantiated. The lemma
always generates credits, but they cannot be used in any meaningful way unless
`HasLc` is picked.
* Add discardable fractions `dfrac` to `saved_anything_own`, `saved_prop_own`,
and `saved_pred_own`, so they can be updated. The previous persistent versions
can be recovered with the fraction `DfracDiscarded`. Allocation lemmas now take
a `dq` parameter to define the initial fraction.
* Remove an unused fraction argument to `dfrac_valid_discarded`.
**Changes in `program_logic`:**
* The definition of the weakest precondition has been changed to generate later credits
(see `base_logic`) for each step:
+ The member `num_laters_per_step` of the `irisGS` class now also determines the number
of later credits that are generated: `S (num_laters_per_step ns)` if `ns` steps
have been taken.
+ The weakest precondition offers credits after a `prim_step` has been proven.
+ All lifting lemmas have been altered to provide credits.
`wp_lift_step_fupdN` provides `S (num_laters_per_step ns)` credits, while all other
lemmas always provide one credit.
* In line with the support for later credits (see `base_logic`), `irisGS_gen`
now also has a `has_lc` parameter and the adequacy statements have been
changed to account for that:
+ The lemma `twp_total` (total adequacy) provides `irisGS_gen HasNoLc`. Clients
of the adequacy proof will need to make sure to be either generic over the
choice of `has_lc` or explicitly opt-out of later credits.
+ The adequacy lemmas for the partial WP, in particular `wp_adequacy`,
`wp_strong_adequacy` and `wp_invariance`, are now available in two flavors:
the old names generate `irisGS` (a short-hand for `irisGS_gen HasLc`); new
lemmas with a `_gen` suffix leave the choice of `has_lc` to the user.
+ The parameter for the stuckness bit `s` in `wp_strong_adequacy{_lc, _no_lc}` has
moved up and is now universally quantified in the lemma instead of being existentially
quantified at the Iris-level. For clients that already previously quantified over `s`
at the Coq level, the only required change should be to remove the instantiation
of the existential quantifier.
**Changes in `iris_heap_lang`:**
* Change the `num_laters_per_step` of `heap_lang` to `λ n, n`, signifying that
each step of the weakest precondition strips `n` laters, where `n` is the
number of steps taken so far. This number is tied to ghost state in the state
interpretation, which is exposed, updated, and used with new lemmas
`wp_lb_init`, `wp_lb_update`, and `wp_step_fupdN_lb`. (by Jonas Kastberg Hinrichsen)
* Make pattern argument of `wp_pure` tactic optional (defaults to wildcard
pattern, matching all redexes).
* In line with the support for later credits (see `base_logic`), the tactic
`wp_pure` now takes an optional parameter `credit:"H"` which generates a
hypothesis `H` for a single later credit `£ 1` that can be eliminated using
`lc_fupd_elim_later`.
The typeclass `heapGS_gen` now takes an additional `has_lc` parameter, and
`heapGS` is a short-hand for `heapGS_gen HasLc`. The adequacy statements for
HeapLang have been changed accordingly:
+ `heap_adequacy` provides `heapGS`, thus enabling the use of later credits.
This precludes usage of the laws in `BiFUpdPlainly` in the HeapLang instance of Iris.
+ `heap_total` provides `heapGS_gen HasNoLc`.
The following `sed` script helps adjust your code to the renaming (on macOS,
replace `sed` by `gsed`, installed via e.g. `brew install gnu-sed`).
Note that the script is not idempotent, do not run it twice.
```
sed -i -E -f- $(find theories -name "*.v") <<EOF
# excl_auth
s/\bexcl_auth_frag_validN_op_1_l\b/excl_auth_frag_op_validN/g
s/\bexcl_auth_frag_valid_op_1_l\b/excl_auth_frag_op_valid/g
# staging → unstable
s/\biris\.staging\b/iris.unstable/g
# plus → add
s/\blaterN_plus\b/laterN_add/g
s/\bpos_op_plus\b/pos_op_add/g
EOF
```
## Iris 3.6.0 (2022-01-22)
The highlights and most notable changes of this release are:
* Coq 8.15 is now supported, while Coq 8.13 and Coq 8.14 remain supported.
Coq 8.12 is no longer supported.
* Support for discardable fractions (`dfrac`) has been added to `gmap_view`
authoritative elements, and to the `mono_nat` library. See below for other
`dfrac`-related changes.
* A new `mono_list` algebra provides monotonically growing lists with an
exclusive authoritative element and persistent prefix witnesses. See
`iris/algebra/lib/mono_list.v` for details. An experimental logic-level
library wrapping the algebra is available at
`iris_staging/base_logic/mono_list.v`; if you use it, please give feedback on
the tracking issue
[iris/iris#439](https://gitlab.mpi-sws.org/iris/iris/-/issues/439).
This release was managed by Ralf Jung, Robbert Krebbers, and Tej Chajed, with
contributions from Dan Frumin, Jonas Kastberg Hinrichsen, Lennard Gäher,
Matthieu Sozeau, Michael Sammler, Paolo G. Giarrusso, Ralf Jung, Robbert
Krebbers, Simon Friis Vindum, Tej Chajed, and Vincent Siles. Thanks a lot to
everyone involved!
**Changes in `algebra`**
* Define non-expansive instance for `dom`. This, in particular, makes it
possible to `iRewrite` below `dom` (even if the `dom` appears in `⌜ _ ⌝`).
* Generalize the authoritative elements of `gmap_view` to be parameterized by a
[discardable fraction](iris/algebra/dfrac.v) (`dfrac`) instead of a fraction
(`frac`). Lemmas affected by this have been renamed such that the "frac" in
their name has been changed into "dfrac". (by Simon Friis Vindum)
* Change `ufrac_auth` notation to not use curly braces, since these fractions do
not behave like regular fractions (and cannot be made `dfrac`).
Old: `●U{q} a`, `◯U{q} b`; new: `●U_q a`, `◯U_q b`.
* Equip `frac_agree` with support for `dfrac` and rename it to `dfrac_agree`.
The old `to_frac_agree` and its lemmas still exist, except that the
`frac_agree_op_valid` lemmas are made bi-directional.
* Rename typeclass instance `Later_inj` -> `Next_inj`.
* Remove `view_auth_frac_op`, `auth_auth_frac_op`, `gmap_view_auth_frac_op`; the
corresponding `dfrac` lemmas can be used instead (together with `dfrac_op_own`
if needed).
* Equip `mono_nat` algebra with support for `dfrac`, make API more consistent,
and add notation for algebra elements. See `iris/algebra/lib/mono_nat.v` for
details. This affects some existing terms and lemmas:
- `mono_nat_auth` now takes a `dfrac`, but the recommendation is to port to the notation.
- `mono_nat_lb_op`: direction of equality is swapped.
- `mono_nat_auth_frac_op`, `mono_nat_auth_frac_op_valid`,
`mono_nat_auth_frac_valid`, `mono_nat_both_frac_valid`: use `dfrac` variant
instead.
* Add `mono_list` algebra for monotonically growing lists with an exclusive
authoritative element and persistent prefix witnesses. See
`iris/algebra/lib/mono_list.v` for details.
**Changes in `bi`:**
* Rename `least_fixpoint_ind` into `least_fixpoint_iter`,
rename `greatest_fixpoint_coind` into `greatest_fixpoint_coiter`,
rename `least_fixpoint_strong_ind` into `least_fixpoint_ind`,
add lemmas `least_fixpoint_{ind_wf, ne', strong_mono}`, and
add lemmas `greatest_fixpoint_{coind, paco, ne', strong_mono}`.
* Move `persistently_forall_2` (`∀ <pers> ⊢ <pers> ∀`) out of the BI interface
into a new typeclass, `BiPersistentlyForall`. The BI interface instead just
demands the equivalent property for conjunction (`(<pers> P) ∧ (<pers> Q) ⊢
<pers> (P ∧ Q)`). This enables the IPM to support logics where the
persistently modality is defined with an existential quantifier. This also
necessitates removing `persistently_impl_plainly` from `BiPlainly` into a new
typeclass `BiPersistentlyImplPlainly`.
Proofs that are generic in `PROP` might have to add those new classes as
assumptions to remain compatible, and code that instantiates the BI interface
needs to provide instances for the new classes.
* Make `frame_fractional` not an instance any more; instead fractional
propositions that want to support framing are expected to register an
appropriate instance themselves. HeapLang and gen_heap `↦` still support
framing, but the other fractional propositions in Iris do not.
* Strengthen the `Persistent`/`Affine`/`Timeless` results for big ops. Add a `'`
to the name of the weaker results, which remain to be used as instances.
**Changes in `heap_lang`:**
* The `is_closed_expr` predicate is formulated in terms of a
set of binders (as opposed to a list of binders).
The following `sed` script helps adjust your code to the renaming (on macOS,
replace `sed` by `gsed`, installed via e.g. `brew install gnu-sed`).
Note that the script is not idempotent, do not run it twice.
```
sed -i -E -f- $(find theories -name "*.v") <<EOF
# least/greatest fixpoint renames
s/\bleast_fixpoint_ind\b/least_fixpoint_iter/g
s/\bgreatest_fixpoint_coind\b/greatest_fixpoint_coiter/g
s/\bleast_fixpoint_strong_ind\b/least_fixpoint_ind/g
# gmap_view renames from frac to dfrac
s/\bgmap_view_(auth|both)_frac_(op_invN|op_inv|op_inv_L|valid|op_validN|op_valid|op_valid_L)\b/gmap_view_\1_dfrac_\2/g
s/\bgmap_view_persist\b/gmap_view_frag_persist/g
# frac_agree with dfrac
s/\bfrac_agreeR\b/dfrac_agreeR/g
EOF
```
## Iris 3.5.0 (2021-11-05)
The highlights and most notable changes of this release are:
* Coq 8.14 is now supported, while Coq 8.12 and Coq 8.13 remain supported.
* The proof mode now has native support for pure names `%H` in intro patterns,
without installing
[iris/string-ident](https://gitlab.mpi-sws.org/iris/string-ident). If you had
the plugin installed, to migrate simply uninstall the plugin and stop
importing it.
* The proof mode now supports destructing existentials with the `"[%x ...]"`
pattern.
* `iMod` and `iModIntro` now report an error message for mask mismatches.
* Performance improvements for the proof mode in `iFrame` in non-affine
logics, `iPoseProof`, and `iDestruct` (by Paolo G. Giarrusso, Bedrock Systems,
and Armaël Guéneau).
* The new `ghost_map` logic-level library supports a ghost `gmap K V` with an
authoritative view and per-element points-to facts written `k ↪[γ] w`.
* Weakest preconditions now support a flexible number of laters per
physical step of the operational semantics. See merge request
[!585](https://gitlab.mpi-sws.org/iris/iris/-/merge_requests/595) (by
Jacques-Henri Jourdan and Yusuke Matsushita).
* HeapLang now has an atomic `Xchg` (exchange) operation (by Simon Hudon,
Google).
This release was managed by Ralf Jung, Robbert Krebbers, and Tej Chajed, with
contributions from Amin Timany, Armaël Guéneau, Dan Frumin, Dmitry Khalanskiy,
Hoang-Hai Dang, Jacques-Henri Jourdan, Lennard Gäher, Michael Sammler, Paolo G.
Giarrusso, Ralf Jung, Robbert Krebbers, Simon Friis Vindum, Simon Hudon, Tej
Chajed, and Yusuke Matsushita. Thanks a lot to everyone involved!
**Changes in `algebra`:**
* Generalize the authoritative elements of the `view`, `auth` and `gset_bij`
cameras to be parameterized by a [discardable fraction](iris/algebra/dfrac.v)
(`dfrac`) instead of a fraction (`frac`). Normal fractions are now denoted
`●{#q} a` and `●V{#q} a`. Lemmas affected by this have been renamed such that
the "frac" in their name has been changed into "dfrac". (by Simon Friis Vindum)
* Generalize `namespace_map` to `reservation_map` which enhances `gmap positive
A` with a notion of 'tokens' that enable allocating a particular name in the
map. See [algebra.reservation_map](iris/algebra/reservation_map.v) for further
information.
* Add `dyn_reservation_map` which further extends `reservation_map` with the
ability to dynamically allocate an infinite set of tokens. This is useful to
perform synchronized allocation of the same name in two maps/APIs without
dedicated support from one of the involved maps/APIs. See
[algebra.dyn_reservation_map](iris/algebra/dyn_reservation_map.v) for further
information.
* Demote the Camera structure on `list` to `iris_staging` since its composition
is not very well-behaved.
* Extend `gmap_view` with lemmas for "big" operations on maps.
* Typeclasses instances triggering a canonical structure search such as `Equiv`,
`Dist`, `Op`, `Valid`, `ValidN`, `Unit`, `PCore` now use an `Hint Extern`
based on `refine` instead of `apply`, in order to use Coq's newer unification
algorithm.
* Set `Hint Mode` for the classes `OfeDiscrete`, `Dist`, `Unit`, `CmraMorphism`,
`rFunctorContractive`, `urFunctorContractive`.
* Set `Hint Mode` for the stdpp class `Equiv`. This might require few spurious
type annotations until
[Coq bug #14441](https://github.com/coq/coq/issues/14441) is fixed.
* Add `max_prefix_list` RA on lists whose composition is only defined when one
operand is a prefix of the other. The result is the longer list.
* Add `NonExpansive` instances for `curry` and friends.
**Changes in `bi`:**
* Add new lemmas `big_sepM2_delete_l` and `big_sepM2_delete_r`.
* Rename `big_sepM2_lookup_1``big_sepM2_lookup_l` and
`big_sepM2_lookup_2``big_sepM2_lookup_r`.
* Add lemmas for swapping nested big-ops: `big_sep{L,M,S,MS}_sep{L,M,S,MS}`.
* Rename `big_sep{L,L2,M,M2,S}_intuitionistically_forall`
`big_sep{L,L2,M,M2,S}_intro`, and `big_orL_lookup``big_orL_intro`.
* Rename `bupd_forall` to `bupd_plain_forall`, and add
`{bupd,fupd}_{and,or,forall,exist}`.
* Decouple `Wp` and `Twp` typeclasses from the `program_logic.language`
interface. The typeclasses are now parameterized over an expression and a
value type, instead of a language. This requires extra type annotations or
explicit coercions in a few cases, in particular `WP v {{ Φ }}` must now be
written `WP (of_val v) {{ Φ }}`.
* Improve `make_laterable`:
- Adjust definition such that `Laterable P` iff `P ⊢ make_laterable P`.
As a consequence, `make_laterable_elim` got weaker: elimination now requires
an except-0 modality (`make_laterable P -∗ ◇ P`).
- Add `iModIntro` support for `make_laterable`.
* Improvements to `BiMonoPred`:
- Use `□`/`-∗` instead of `<pers>`/`→`.
- Strengthen to ensure that functions for recursive calls are non-expansive.
* Add `big_andM` (big conjunction on finite maps) with lemmas similar to `big_andL`.
* Add transitive embedding that constructs an embedding of `PROP1` into `PROP3`
by combining the embeddings of `PROP1` into `PROP2` and `PROP2` into `PROP3`.
This construct is *not* declared as an instance to avoid TC search divergence.
(by Hai Dang, BedRock Systems)
* Improve notation printing around magic wands, view shifts, `WP`, Texan
triples, and logically atomic triples.
* Slight change to the `AACC` notation for atomic accessors (which is usually
only printed, not parsed): added a `,` before `ABORT`, for consistency with `COMM`.
* Add the lemmas `big_sepM_impl_strong` and `big_sepM_impl_dom_subseteq` that
generalize the existing `big_sepM_impl` lemma. (by Simon Friis Vindum)
* Add new instance `fractional_big_sepL2`. (by Paolo G. Giarrusso, BedRock Systems)
**Changes in `proofmode`:**
* Add support for pure names `%H` in intro patterns. This is now natively
supported whereas the previous experimental support required installing
https://gitlab.mpi-sws.org/iris/string-ident. (by Tej Chajed)
* Add support for destructing existentials with the intro pattern `[%x ...]`.
(by Tej Chajed)
* `iMod`/`iModIntro` show proper error messages when they fail due to mask
mismatches. To support this, the proofmode typeclass `FromModal` now takes an
additional pure precondition.
* Fix performance of `iFrame` in logics without `BiAffine`.
To adjust your code if you use such logics and define `Frame` instances,
ensure these instances to have priority at least 2: they should have either at
least 2 (non-dependent) premises, or an explicit priority.
References: docs for `frame_here_absorbing` in
[iris/proofmode/frame_instances.v](iris/proofmode/frame_instances.v) and
https://coq.inria.fr/refman/addendum/type-classes.html#coq:cmd.Instance. (by
Paolo G. Giarrusso, BedRock Systems)
* Rename the main entry point module for the proofmode from
`iris.proofmode.tactics` to `iris.proofmode.proofmode`. Under normal
circumstances, this should be the only proofmode file you need to import.
* Improve performance of the `iIntoEmpValid` tactic used by `iPoseProof`,
especially in the case of large goals and lemmas with many forall quantifiers.
(by Armaël Guéneau)
* Improve performance of the `iDestruct` tactic, by using user-provided names
more eagerly in order to avoid later calls to `iRename`.
(by Armaël Guéneau)
**Changes in `bi`:**
* Add lemmas characterizing big-ops over pure predicates (`big_sep*_pure*`).
* Move `BiAffine`, `BiPositive`, `BiLöb`, and `BiPureForall` from
`bi.derived_connectives` to `bi.extensions`.
* Strengthen `persistent_fractional` to support propositions that are persistent
and either affine or absorbing. (by Paolo G. Giarrusso, BedRock Systems)
**Changes in `base_logic`:**
* Add `ghost_map`, a logic-level library for a `gmap K V` with an authoritative
view and per-element points-to facts written `k ↪[γ] w`.
* Generalize the soundness lemma of the base logic `step_fupdN_soundness`.
It applies even if invariants stay open across an arbitrary number of laters.
(by Jacques-Henri Jourdan)
* Rename those `*G` typeclasses that must be global singletons to `*GS`, and
their corresponding `preG` class to `GpreS`. Affects `invG`, `irisG`,
`gen_heapG`, `inv_heapG`, `proph_mapG`, `ownPG`, `heapG`.
**Changes in `program_logic`:**
* Change definition of weakest precondition to use a variable number of laters
(i.e., logical steps) for each physical step of the operational semantics,
depending on the number of physical steps executed since the beginning of the
execution of the program. See merge request [!595](https://gitlab.mpi-sws.org/iris/iris/-/merge_requests/595).
This implies several API-breaking changes, which can be easily fixed in client
formalizations in a backward compatible manner as follows:
- Ignore the new parameter `ns` in the state interpretation, which
corresponds to a step counter.
- Use the constant function "0" for the new field `num_laters_per_step` of
`irisG`.
- Use `fupd_intro _ _` for the new field `state_interp_mono` of `irisG`.
- Some proofs using lifting lemmas and adequacy theorems need to be adapted
to ignore the new step counter.
(by Jacques-Henri Jourdan)
* Remove `wp_frame_wand_l`; add `wp_frame_wand` as more symmetric replacement.
* Swap the polarity of the mask in logically atomic triples, so that it matches
regular `WP` masks.
* Rename `iris_invG` to `iris_invGS`.
**Changes in `heap_lang`:**
* Rename `Build_loc` constructor for `loc` type to `Loc`.
* Add atomic `Xchg` ("exchange"/"swap") operation. (by Simon Hudon, Google LLC)
The following `sed` script helps adjust your code to the renaming (on macOS,
replace `sed` by `gsed`, installed via e.g. `brew install gnu-sed`).
Note that the script is not idempotent, do not run it twice.
```
sed -i -E -f- $(find theories -name "*.v") <<EOF
# auth and view renames from frac to dfrac
s/\b(auth|view)_(auth|both|update)_frac_(is_op|op_invN|op_inv|inv_L|validN|op_validN|valid|op_valid|valid_2|valid_discrete|includedN|included|alloc|validI|validI_2|validI_1|validI|)\b/\1_\2_dfrac_\3/g
s/\bgset_bij_auth_frac_(\w*)\b/gset_bij_auth_dfrac_\1/g
s/\bgset_bij_auth_empty_frac_valid\b/gset_bij_auth_empty_dfrac_valid/g
s/\bbij_both_frac_valid\b/bij_both_dfrac_valid/g
# big_sepM renames
s/\bbig_sepM2_lookup_1\b/big_sepM2_lookup_l/g
s/\bbig_sepM2_lookup_2\b/big_sepM2_lookup_r/g
# big_*_intro
s/\bbig_sep(L|L2|M|M2|S)_intuitionistically_forall\b/big_sep\1_intro/g
s/\bbig_orL_lookup\b/big_orL_intro/g
s/\bbupd_forall\b/bupd_plain_forall/g
# "global singleton" rename
s/\b(inv|iris|(gen|inv)_heap|(Gen|Inv)Heap|proph_map|ProphMap|[oO]wnP|[hH]eap)G\b/\1GS/g
s/\b([iI]nv|iris|(gen|inv)_heap|(Gen|Inv)Heap|proph_map|ProphMap|[oO]wnP|[hH]eap)PreG\b/\1GpreS/g
# iris.proofmode.tactics → iris.proofmode.proofmode
s/\bproofmode\.tactics\b/proofmode.proofmode/
s/(From +iris\.proofmode +Require +(Import|Export).*)\btactics\b/\1proofmode/
# iris_invG → iris_invGS
s/\biris_invG\b/iris_invGS/g
EOF
```
## Iris 3.4.0 (released 2021-02-16)
The highlights and most notable changes of this release are as follows:
* Coq 8.13 is now supported; the old Coq 8.9 and Coq 8.10 are not supported any
more.
* The new `view` RA construction generalizes `auth` to user-defined abstraction
relations. (thanks to Gregory Malecha for the inspiration)
* The new `dfrac` RA extends `frac` (fractions `0 < q ≤ 1`) with support for
"discarding" some part of the fraction in exchange for a persistent witness
that discarding has happened. This can be used to easily generalize fractional
permissions with support for persistently owning "any part" of the resource.
(by Simon Friis Vindum)
* The new `gmap_view` RA provides convenient lemmas for ghost ownership
of heap-like structures with an "authoritative" view. Thanks to `dfrac`, it
supports both exclusive (mutable) and persistent (immutable) ownership of
individual map elements.
* With this release we are beginning to provide logic-level abstractions for
ghost state, which have the advantage that the user does not have to directly
interact with RAs to use them.
- `ghost_var` provides a logic-level abstraction of ghost variables: a mutable
"variable" with fractional ownership.
- `mono_nat` provides a "monotone counter" with a persistent witnesses
representing a lower bound of the current counter value. (by Tej Chajed)
- `gset_bij` provides a monotonically growing partial bijection; this is
useful in particular when building binary logical relations for languages
with a heap.
* HeapLang provides a persistent read-only points-to assertion `l ↦□ v`.
(by Simon Friis Vindum)
* We split Iris into multiple opam packages: `coq-iris` no longer contains
HeapLang, which is now in a separate package `coq-iris-heap-lang`. The two
packages `coq-iris-deprecated` (for old modules that we eventually plan to
remove entirely) and `coq-iris-staging` (for new modules that are not yet
ready for prime time) exist only as development versions, so they are not part
of this release.
* The proofmode now does a better job at picking reasonable names when moving
variables into the Coq context without a name being explicitly given by the
user. However, the exact variable names remain unspecified. (by Tej Chajed)
Further details are given in the changelog below.
This release of Iris was managed by Ralf Jung and Robbert Krebbers, with
contributions by Arthur Azevedo de Amorim, Dan Frumin, Enrico Tassi, Hai Dang,
Michael Sammler, Paolo G. Giarrusso, Rodolphe Lepigre, Simon Friis Vindum, Tej
Chajed, and Yusuke Matsushita. Thanks a lot to everyone involved!
**Changes in `algebra`:**
* Add constructions to define a camera through restriction of the validity predicate
(`iso_cmra_mixin_restrict`) and through an isomorphism (`iso_cmra_mixin`).
* Add a `frac_agree` library which encapsulates `frac * agree A` for some OFE
`A`, and provides some useful lemmas.
* Add the view camera `view`, which generalizes the authoritative camera
`auth` by being parameterized by a relation that relates the authoritative
element with the fragments.
* Add the camera of discardable fractions `dfrac`. This is a generalization of
the normal fractional camera.
See [algebra.dfrac](iris/algebra/dfrac.v) for further information.
* Add `gmap_view`, a camera providing a "view of a `gmap`". The authoritative
element is any `gmap`; the fragment provides fractional ownership of a single
key, including support for persistent read-only ownership through `dfrac`.
See [algebra.lib.gmap_view](iris/algebra/lib/gmap_view.v) for further information.
* Add `mono_nat`, a wrapper for `auth max_nat`. The result is an authoritative
`nat` where a fragment is a lower bound whose ownership is persistent.
See [algebra.lib.mono_nat](iris/algebra/lib/mono_nat.v) for further information.
* Add the `gset_bij` resource algebra for monotone partial bijections.
See [algebra.lib.gset_bij](iris/algebra/lib/gset_bij.v) for further information.
* Rename `agree_op_inv'``to_agree_op_inv`,
`agree_op_invL'``to_agree_op_inv_L`, and add `to_agree_op_invN`.
* Rename `auth_auth_frac_op_invL``auth_auth_frac_op_inv_L`,
`excl_auth_agreeL``excl_auth_agree_L`,
`frac_auth_agreeL``frac_auth_agree_L`, and
`ufrac_auth_agreeL``ufrac_auth_agree_L`.
* Fix direction of `auth_auth_validN` to make it consistent with similar lemmas,
e.g., `auth_auth_valid`. The direction is now `✓{n} (● a) ↔ ✓{n} a`.
* Rename `auth_both_valid` to `auth_both_valid_discrete` and
`auth_both_frac_valid` to `auth_both_frac_valid_discrete`. The old name is
used for new, stronger lemmas that do not assume discreteness.
* Redefine the authoritative camera in terms of the view camera. As part of this
change, we have removed lemmas that leaked implementation details. Hence, the
only way to construct elements of `auth` is via the elements `●{q} a` and
`◯ b`. The constructor `Auth`, and the projections `auth_auth_proj` and
`auth_frag_proj` no longer exist. Lemmas that referred to these constructors
have been removed, in particular: `auth_equivI`, `auth_validI`,
`auth_included`, `auth_valid_discrete`, and `auth_both_op`. For validity, use
`auth_auth_valid*`, `auth_frag_valid*`, or `auth_both_valid*` instead.
* Rename `auth_update_core_id` into `auth_update_frac_alloc`.
* Rename `cmra_monotone_valid` into `cmra_morphism_valid` (this rename was
forgotten in !56).
* Move the `*_validI` and `*_equivI` lemmas to a new module, `base_logic.algebra`.
That module is exported by `base_logic.base_logic` so it should usually be
available everywhere without further changes.
* The authoritative fragment `✓ (◯ b : auth A)` is no longer definitionally
equal to `✓ b`.
* Change `*_valid` lemma statements involving fractions to use `Qp` addition and
inequality instead of RA composition and validity (also in `base_logic` and
the higher layers).
* Move `algebra.base` module to `prelude.prelude`.
* Strengthen `cmra_op_discrete` to assume only `✓{0} (x1 ⋅ x2)` instead of `✓
(x1 ⋅ x2)`.
* Rename the types `ofeT``ofe`, `cmraT``cmra`, `ucmraT``ucmra`, and the
constructors `OfeT``Ofe`, `CmraT``Cmra`, and `UcmraT``Ucmra` since the `T`
suffix is not needed. This change makes these names consistent with `bi`,
which also does not have a `T` suffix.
* Rename typeclass instances of CMRA operational typeclasses (`Op`, `Core`,
`PCore`, `Valid`, `ValidN`, `Unit`) to have a `_instance` suffix, so that
their original names are available to use as lemma names.
* Rename `frac_valid'``frac_valid`, `frac_op'``frac_op`,
`ufrac_op'``ufrac_op`, `coPset_op_union``coPset_op`, `coPset_core_self`
`coPset_core`, `gset_op_union``gset_op`, `gset_core_self``gset_core`,
`gmultiset_op_disj_union``gmultiset_op`, `gmultiset_core_empty`
`gmultiset_core`, `nat_op_plus``nat_op`, `max_nat_op_max`
`max_nat_op`. Those names were previously blocked by typeclass instances.
**Changes in `bi`:**
* Add big op lemmas `big_op{L,L2,M,M2,S}_intuitionistically_forall` and
`big_sepL2_forall`, `big_sepMS_forall`, `big_sepMS_impl`, and `big_sepMS_dup`.
* Add lemmas to big-ops that provide ownership of a single element and permit
changing the quantified-over predicate when re-assembling the big-op:
`big_sepL_lookup_acc_impl`, `big_sepL2_lookup_acc_impl`,
`big_sepM_lookup_acc_impl`, `big_sepM2_lookup_acc_impl`,
`big_sepS_elem_of_acc_impl`, `big_sepMS_elem_of_acc_impl`.
* Add lemmas `big_sepM_filter'` and `big_sepM_filter` matching the corresponding
`big_sepS` lemmas.
* Add lemmas for big-ops of magic wands: `big_sepL_wand`, `big_sepL2_wand`,
`big_sepM_wand`, `big_sepM2_wand`, `big_sepS_wand`, `big_sepMS_wand`.
* Add notation `¬ P` for `P → False` to `bi_scope`.
* Add `fupd_mask_intro` which can be conveniently `iApply`ed to goals of the
form `|={E1,E2}=>` to get rid of the `fupd` in the goal if `E2 ⊆ E1`. The
lemma `fupd_mask_weaken Enew` can be `iApply`ed to shrink the first mask to
`Enew` without getting rid of the modality; the same effect can also be
obtained slightly more conveniently by using `iMod` with `fupd_mask_subseteq
Enew`. To make the new names work, rename some existing lemmas:
`fupd_intro_mask``fupd_mask_intro_subseteq`,
`fupd_intro_mask'``fupd_mask_subseteq` (implicit arguments also changed
here), `fupd_mask_weaken``fupd_mask_intro_discard`. Remove `fupd_mask_same`
since it was unused and obscure. In the `BiFUpd` axiomatization, rename
`bi_fupd_mixin_fupd_intro_mask` to `bi_fupd_mixin_fupd_mask_subseteq` and
weaken the lemma to be specifically about `emp` (the stronger version can be
derived).
* Remove `bi.tactics` with tactics that predate the proofmode (and that have not
been working properly for quite some time).
* Strengthen `persistent_sep_dup` to support propositions that are persistent
and either affine or absorbing.
* Fix the statement of the lemma `fupd_plainly_laterN`; the old lemma was a
duplicate of `fupd_plain_laterN`.
* Strengthen `big_sepL2_app_inv` by weakening a premise (it is sufficient for
one of the two pairs of lists to have equal length).
* Rename `equiv_entails``equiv_entails_1_1`,
`equiv_entails_sym``equiv_entails_1_2`, and `equiv_spec``equiv_entails`.
* Remove the laws `pure_forall_2 : (∀ a, ⌜ φ a ⌝) ⊢ ⌜ ∀ a, φ a ⌝` from the BI
interface and factor it into a type class `BiPureForall`.
**Changes in `proofmode`:**
* The proofmode now preserves user-supplied names for existentials when using
`iDestruct ... as (?) "..."`. This is backwards-incompatible if you were
relying on the previous automatic names (which were always "H", possibly
freshened). It also requires some changes if you were implementing `IntoExist`
yourself, since the typeclass now forwards names. If your instance transforms
one `IntoExist` into another, you can generally just forward the name from the
premise.
* The proofmode also preserves user-supplied names in `iIntros`, for example
with `iIntros (?)` and `iIntros "%"`, as described for destructing
existentials above. As part of this change, it now uses a base name of `H` for
pure facts rather than the previous default of `a`. This also requires some
changes if you were implementing `FromForall`, in order to forward names.
* Make `iFrame` "less" smart w.r.t. clean up of modalities. It now consistently
removes the modalities `<affine>`, `<absorbing>`, `<persistent>` and `□` only
if the result after framing is `True` or `emp`. In particular, it no longer
removes `<affine>` if the result after framing is affine, and it no longer
removes `□` if the result after framing is intuitionistic.
* Allow framing below an `<affine>` modality if the hypothesis that is framed is
affine. (Previously, framing below `<affine>` was only possible if the
hypothesis that is framed resides in the intuitionistic context.)
* Add Coq side-condition `φ` to class `ElimAcc` (similar to what we already had
for `ElimInv` and `ElimModal`).
* Add a tactic `iSelect pat tac` (similar to `select` in std++) which runs the
tactic `tac H` with the name `H` of the last hypothesis of the intuitionistic
or spatial context matching `pat`. The tactic `iSelect` is used to implement:
+ `iRename select (pat)%I into name` which renames the matching hypothesis,
+ `iDestruct select (pat)%I as ...` which destructs the matching hypothesis,
+ `iClear select (pat)%I` which clears the matching hypothesis,
+ `iRevert select (pat)%I` which reverts the matching hypothesis,
+ `iFrame select (pat)%I` which cancels the matching hypothesis.
**Changes in `base_logic`:**
* Add a `ghost_var` library that provides (fractional) ownership of a ghost
variable of arbitrary `Type`.
* Define a ghost state library on top of the `mono_nat` resource algebra.
See [base_logic.lib.mono_nat](iris/base_logic/lib/mono_nat.v) for further
information.
* Define a ghost state library on top of the `gset_bij` resource algebra.
See [base_logic.lib.gset_bij](iris/base_logic/lib/gset_bij.v) for further
information.
* Extend the `gen_heap` library with read-only points-to assertions using
[discardable fractions](iris/algebra/dfrac.v).
+ The `mapsto` connective now takes a `dfrac` rather than a `frac` (i.e.,
positive rational number `Qp`).
+ The notation `l ↦{ dq } v` is generalized to discardable fractions
`dq : dfrac`.
+ The new notation `l ↦{# q} v` is used for a concrete fraction `q : frac`
(e.g., to enable writing `l ↦{# 1/2} v`).
+ The new notation `l ↦□ v` is used for the discarded fraction. This
persistent proposition provides read-only access to `l`.
+ The lemma `mapsto_persist : l ↦{dq} v ==∗ l ↦□ v` is used for making the
location `l` read-only.
+ See the [changes to HeapLang](https://gitlab.mpi-sws.org/iris/iris/-/merge_requests/554)
for an indication on how to adapt your language.
+ See the [changes to iris-examples](https://gitlab.mpi-sws.org/iris/examples/-/commit/a8425b708ec51d918d5cf6eb3ab6fde88f4e2c2a)
for an indication on how to adapt your development. In particular, instead
of `∃ q, l ↦{q} v` you likely want to use `l ↦□ v`, which has the advantage
of being persistent (rather than just duplicable).
* Change type of some ghost state lemmas (mostly about allocation) to use `∗`
instead of `∧` (consistent with our usual style). This affects the following
lemmas: `own_alloc_strong_dep`, `own_alloc_cofinite_dep`, `own_alloc_strong`,
`own_alloc_cofinite`, `own_updateP`, `saved_anything_alloc_strong`,
`saved_anything_alloc_cofinite`, `saved_prop_alloc_strong`,
`saved_prop_alloc_cofinite`, `saved_pred_alloc_strong`,
`saved_pred_alloc_cofinite`, `auth_alloc_strong`, `auth_alloc_cofinite`,
`auth_alloc`.
* Change `uPred_mono` to only require inclusion at the smaller step-index.
* Put `iProp`/`iPreProp`-isomorphism into the `own` construction. This affects
clients that define higher-order ghost state constructions. Concretely, when
defining an `inG`, the functor no longer needs to be applied to `iPreProp`,
but should be applied to `iProp`. This avoids clients from having to push
through the `iProp`/`iPreProp`-isomorphism themselves, which is now handled
once and for all by the `own` construction.
* Rename `gen_heap_ctx` to `gen_heap_interp`, since it is meant to be used in
the state interpretation of WP and since `_ctx` is elsewhere used as a suffix
indicating "this is a persistent assumption that clients should always have in
their context". Likewise, rename `proph_map_ctx` to `proph_map_interp`.
* Move `uPred.prod_validI`, `uPred.option_validI`, and
`uPred.discrete_fun_validI` to the new `base_logic.algebra` module. That
module is exported by `base_logic.base_logic` so these names are now usually
available everywhere, and no longer inside the `uPred` module.
* Remove the `gen_heap` notations `l ↦ -` and `l ↦{q} -`. They were barely used
and looked very confusing in context: `l ↦ - ∗ P` looks like a magic wand.
* Change `gen_inv_heap` notation `l ↦□ I` to `l ↦_I □`, so that `↦□` can be used
by `gen_heap`.
* Strengthen `mapsto_valid_2` conclusion from `✓ (q1 + q2)%Qp` to
`⌜✓ (q1 + q2)%Qp ∧ v1 = v2⌝`.
* Change `gen_heap_init` to also return ownership of the points-to facts for the
initial heap.
* Rename `mapsto_mapsto_ne` to `mapsto_frac_ne`, and add a simpler
`mapsto_ne` that does not require reasoning about fractions.
* Deprecate the `auth` and `sts` modules. These were logic-level wrappers around
the underlying RAs; as far as we know, they are unused since they were not
flexible enough for practical use.
* Deprecate the `viewshift` module, which defined a binary view-shift connective
with an implicit persistence modality. It was unused and too easily confused
with `={_}=∗`, the binary view-shift (fancy update) *without* a persistence
modality.
**Changes in `program_logic`:**
* `wp_strong_adequacy` now applies to an initial state with multiple
threads instead of only a single thread. The derived adequacy lemmas
are unchanged.
* `pure_exec_fill` is no longer registered as an instance for `PureExec`, to
avoid TC search attempting to apply this instance all the time.
* Merge `wp_value_inv`/`wp_value_inv'` into `wp_value_fupd`/`wp_value_fupd'` by
making the lemmas bidirectional.
* Generalize HeapLang's `mapsto` (`↦`), `array` (`↦∗`), and atomic heap
connectives to discardable fractions. See the CHANGELOG entry in the category
`base_logic` for more information.
* Opening an invariant or eliminating a mask-changing update modality around a
non-atomic weakest precondition creates a side-condition `Atomic ...`.
Before, this would fail with the unspecific error "iMod: cannot eliminate
modality (|={E1,E2}=> ...) in (WP ...)".
* In `Ectx_step` and `step_atomic`, mark the parameters that are determined by
the goal as implicit.
* Deprecate the `hoare` module to prevent accidental usage; the recommended way
to write Hoare-style specifications is to use Texan triples.
**Changes in `heap_lang`:**
* `wp_pures` now turns goals of the form `WP v {{ Φ }}` into `Φ v`.
* Fix `wp_bind` in case of a NOP (i.e., when the given expression pattern is
already at the top level).
* The `wp_` tactics now preserve the possibility of doing a fancy update when
the expression reduces to a value.
* Move `IntoVal`, `AsVal`, `Atomic`, `AsRecV`, and `PureExec` instances to their
own file [heap_lang.class_instances](iris_heap_lang/class_instances.v).
* Move `inv_head_step` tactic and `head_step` auto hints (now part of new hint
database `head_step`) to [heap_lang.tactics](iris_heap_lang/tactics.v).
* The tactic `wp_apply` no longer performs `wp_pures` before applying the given
lemma. The new tactic `wp_smart_apply` repeatedly performs single `wp_pure`
steps until the lemma matches the goal.
The following `sed` script helps adjust your code to the renaming (on macOS,
replace `sed` by `gsed`, installed via e.g. `brew install gnu-sed`).
Note that the script is not idempotent, do not run it twice.
```
sed -i -E -f- $(find theories -name "*.v") <<EOF
# agree and L suffix renames
s/\bagree_op_inv'/to_agree_op_inv/g
s/\bagree_op_invL'/to_agree_op_inv_L/g
s/\bauth_auth_frac_op_invL\b/auth_auth_frac_op_inv_L/g
s/\b(excl|frac|ufrac)_auth_agreeL/\1_auth_agree_L/g
# auth_both_valid
s/\bauth_both_valid\b/auth_both_valid_discrete/g
s/\bauth_both_frac_valid\b/auth_both_frac_valid_discrete/g
# gen_heap_ctx and proph_map_ctx
s/\bgen_heap_ctx\b/gen_heap_interp/g
s/\bproph_map_ctx\b/proph_map_interp/g
# other gen_heap changes
s/\bmapsto_mapsto_ne\b/mapsto_frac_ne/g
# remove Ts in algebra
s/\bofeT\b/ofe/g
s/\bOfeT\b/Ofe/g
s/\bcmraT\b/cmra/g
s/\bCmraT\b/Cmra/g
s/\bucmraT\b/ucmra/g
s/\bUcmraT\b/Ucmra/g
# _op/valid/core lemmas
s/\b(u?frac_(op|valid))'/\1/g
s/\b((coPset|gset)_op)_union\b/\1/g
s/\b((coPset|gset)_core)_self\b/\1/g
s/\b(gmultiset_op)_disj_union\b/\1/g
s/\b(gmultiset_core)_empty\b/\1/g
s/\b(nat_op)_plus\b/\1/g
s/\b(max_nat_op)_max\b/\1/g
# equiv_spec
s/\bequiv_entails\b/equiv_entails_1_1/g
s/\bequiv_entails_sym\b/equiv_entails_1_2/g
s/\bequiv_spec\b/equiv_entails/g
EOF
```
## Iris 3.3.0 (released 2020-07-15)
This release does not have any outstanding highlights, but contains a large
number of improvements all over the board. For instance:
* `heap_lang` now supports deallocation as well as better reasoning about
"invariant locations" (locations that perpetually satisfy some Coq-level
invariant).
* Invariants (`inv N P`) are more flexible, now also supporting splitting
and merging of invariants with respect to separating conjunction.
* Performance of the proofmode for BIs constructed on top of other BIs (e.g.,
`monPred`) was greatly improved, leading to up to 70% speedup in individual
files. As part of this refactoring, the proofmode can now also be instantiated
with entirely "logical" notion of BIs that do not have a (non-trivial) metric
structure, and still support reasoning about ▷.
* The proof mode now provides experimental support for naming pure facts in
intro patterns. See
[iris/string-ident](https://gitlab.mpi-sws.org/iris/string-ident) for details.
* Iris now provides official ASCII notation. We still recommend using the
Unicode notation for better consistency and interoperability with other Iris
libraries, but provide ASCII notation for when Unicode is not an option.
* We removed several coercions, fixing "ambiguous coercion path" warnings and
solving some readability issues.
* Coq 8.10, 8.11, and 8.12 are newly supported by this release, and Coq 8.7 and
8.8 are no longer supported.
Further details are given in the changelog below. We always first list the
potentially breaking changes, then (some of) the additions.
This release of Iris received contributions by Abel Nieto, Amin Timany, Dan
Frumin, Derek Dreyer, Dmitry Khalanskiy, Gregory Malecha, Jacques-Henri Jourdan,
Jonas Kastberg, Jules Jacobs, Matthieu Sozeau, Maxime Dénès, Michael Sammler,
Paolo G. Giarrusso, Ralf Jung, Robbert Krebbers, Simon Friis Vindum, Simon
Spies, and Tej Chajed. Thanks a lot to everyone involved!
**Changes in `heap_lang`:**
* Remove global `Open Scope Z_scope` from `heap_lang.lang`, and leave it up to
reverse dependencies if they want to `Open Scope Z_scope` or not.
* Fix all binary operators performing pointer arithmetic (instead of just the
dedicated `OffsetOp` operator doing that).
* Rename `heap_lang.lifting` to `heap_lang.primitive_laws`. There now also
exists `heap_lang.derived_laws`.
* Make lemma names for `fill` more consistent
- Use the `_inv` suffix for the the backwards directions:
`reducible_fill``reducible_fill_inv`,
`reducible_no_obs_fill``reducible_no_obs_fill_inv`,
`not_stuck_fill``not_stuck_fill_inv`.
- Use the non-`_inv` names (that freed up) for the forwards directions:
`reducible_fill`, `reducible_no_obs_fill`, `irreducible_fill_inv`.
* Remove namespace `N` from `is_lock`.
* Add support for deallocation of locations via the `Free` operation.
* Add a fraction to the heap_lang `array` assertion.
* Add `lib.array` module for deallocating, copying and cloning arrays.
* Add TWP (total weakest-pre) lemmas for arrays.
* Add a library for "invariant locations": heap locations that will not be
deallocated (i.e., they are GC-managed) and satisfy some pure, Coq-level
invariant. See `iris.base_logic.lib.gen_inv_heap` for details.
* Add the ghost state for "invariant locations" to `heapG`. This affects the
statement of `heap_adequacy`, which is now responsible for initializing the
"invariant locations" invariant.
* Add lemma `mapsto_mapsto_ne : ¬ ✓(q1 + q2)%Qp → l1 ↦{q1} v1 -∗ l2 ↦{q2} v2 -∗ ⌜l1 ≠ l2⌝`.
* Add lemma `is_lock_iff` and show that `is_lock` is contractive.
**Changes in `program_logic`:**
* In the axiomatization of ectx languages, replace the axiom of positivity of
context composition with an axiom that says if `fill K e` takes a head step,
then either `K` is the empty evaluation context or `e` is a value.
**Changes in the logic (`base_logic`, `bi`):**
* Rename some accessor-style lemmas to consistently use the suffix `_acc`
instead of `_open`:
`inv_open``inv_acc`, `inv_open_strong``inv_acc_strong`,
`inv_open_timeless``inv_acc_timeless`, `na_inv_open``na_inv_acc`,
`cinv_open``cinv_acc`, `cinv_open_strong``cinv_acc_strong`,
`auth_open``auth_acc`, `sts_open``sts_acc`.
To make this work, also rename `inv_acc``inv_alter`.
(Most developments should be unaffected as the typical way to invoke these
lemmas is through `iInv`, and that does not change.)
* Change `inv_iff`, `cinv_iff` and `na_inv_iff` to make order of arguments
consistent and more convenient for `iApply`. They are now of the form
`inv N P -∗ ▷ □ (P ↔ Q) -∗ inv N Q` and (similar for `na_inv_iff` and
`cinv_iff`), following e.g., `inv_alter` and `wp_wand`.
* Rename `inv_sep_1``inv_split_1`, `inv_sep_2``inv_split_2`, and
`inv_sep``inv_split` to be consistent with the naming convention in boxes.
* Update the strong variant of the accessor lemma for cancellable invariants to
match that of regular invariants, where you can pick the mask at a later time.
(The other part that makes it strong is that you get back the token for the
invariant immediately, not just when the invariant is closed again.)
* Rename `iProp`/`iPreProp` to `iPropO`/`iPrePropO` since they are `ofeT`s.
Introduce `iProp` for the `Type` carrier of `iPropO`.
* Flatten the BI hierarchy by merging the `bi` and `sbi` canonical structures.
This gives significant performance benefits on developments that construct BIs
from BIs (e.g., use `monPred`). For, example it gives a performance gain of 37%
overall on lambdarust-weak, with improvements for individual files up to 72%,
see Iris issue #303. The concrete changes are as follows:
+ The `sbi` canonical structure has been removed.
+ The `bi` canonical structure contains the later modality. It does not
require the later modality to be contractive or to satisfy the Löb rule, so
we provide a smart constructor `bi_later_mixin_id` to get the later axioms
"for free" if later is defined to be the identity function.
+ There is a separate class `BiLöb`, and a "free" instance of that class if
the later modality is contractive. A `BiLöb` instance is required for the
`iLöb` tactic, and for timeless instances of implication and wand.
+ There is a separate type class `BiInternalEq` for BIs with a notion of
internal equality (internal equality was part of `sbi`). An instance of this
class is needed for the `iRewrite` tactic, and the various lemmas about
internal equality.
+ The class `SbiEmbed` has been removed and been replaced by classes
`BiEmbedLater` and `BiEmbedInternalEq`.
+ The class `BiPlainly` has been generalized to BIs without internal equality.
As a consequence, there is a separate class `BiPropExt` for BIs with
propositional extensionality (i.e., `■ (P ∗-∗ Q) ⊢ P ≡ Q`).
+ The class `BiEmbedPlainly` is a bi-entailment (i.e., `⎡■ P⎤ ⊣⊢ ■ ⎡P⎤`
instead of `■ ⎡P⎤ ⊢ ⎡■ P⎤`) as it has been generalized to BIs without a
internal equality. In the past, the left-to-right direction was obtained for
"free" using the rules of internal equality.
* Remove coercion from `iProp` (and other MoSeL propositions) to `Prop`.
Instead, use the new unary notation `⊢ P`, or `⊢@{PROP} P` if the proposition
type cannot be inferred. This also means that `%I` should not be necessary any
more when stating lemmas, as `P` above is automatically parsed in scope `%I`.
* Some improvements to the `bi/lib/core` construction:
+ Rename `coreP_wand` into `coreP_entails` since it does not involve wands.
+ Generalize `coreP_entails` to non-affine BIs, and prove more convenient
version `coreP_entails'` for `coreP P` with `P` affine.
+ Add instance `coreP_affine P : Affine P → Affine (coreP P)` and
lemma `coreP_wand P Q : <affine> ■ (P -∗ Q) -∗ coreP P -∗ coreP Q`.
* Remove notation for 3-mask step-taking updates, and made 2-mask notation less
confusing by distinguishing it better from mask-changing updates.
Old: `|={Eo,Ei}▷=> P`. New: `|={Eo}[Ei]▷=> P`.
Here, `Eo` is the "outer mask" (used at the beginning and end) and `Ei` the
"inner mask" (used around the ▷ in the middle).
As part of this, the lemmas about the 3-mask variant were changed to be about
the 2-mask variant instead, and `step_fupd_mask_mono` now also has a more
consistent argument order for its masks.
* Add a counterexample showing that sufficiently powerful cancellable invariants
with a linear token subvert the linearity guarantee (see
`bi.lib.counterexmples` for details).
* Redefine invariants as "semantic invariants" so that they support
splitting and other forms of weakening.
* Add lemmas `inv_combine` and `inv_combine_dup_l` for combining invariants.
* Add the type `siProp` of "plain" step-indexed propositions, together with
basic proofmode support.
* New ASCII versions of Iris notations. These are marked parsing only and
can be made available using `Require Import iris.bi.ascii`. The new
notations are (notations marked [†] are disambiguated using notation scopes):
- entailment: `|-` for `⊢` and `-|-` for `⊣⊢`
- logic[†]: `->` for `→`, `/\\` for `∧`, `\\/` for `∨`, and `<->` for `↔`
- quantifiers[†]: `forall` for `∀` and `exists` for `∃`
- separation logic: `**` for `∗`, `-*` for `-∗`, and `*-*` for `∗-∗`
- step indexing: `|>` for `▷`
- modalities: `<#>` for `□` and `<except_0>` for `◇`
- most derived notations can be computed from previous notations using the
substitutions above, e.g. replace `∗` with `*` and `▷` with `|>`. Examples
include the following:
- `|={E1,E2}=* P` for `|={E1,E2}=∗`
- `P ={E}=* Q` for `P ={E}=∗ Q`
- `P ={E1,E2}=* Q` for `P ={E1,E2}=∗ Q`
- `|={E1}[E2]|>=> Q` for `|={E1}[E2]▷=> Q`
The full list can be found in [theories/bi/ascii.v](theories/bi/ascii.v),
where the ASCII notations are defined in terms of the unicode notations.
* Add affine, absorbing, persistent and timeless instances for telescopes.
* Add a construction `bi_rtc` to create reflexive transitive closures of
PROP-level binary relations.
* Slightly strengthen the lemmas `big_sepL_nil'`, `big_sepL2_nil'`,
`big_sepM_nil'` `big_sepM2_empty'`, `big_sepS_empty'`, and `big_sepMS_empty'`.
They now only require that the argument `P` is affine instead of the whole BI
being affine.
* Add `big_sepL_insert_acc`, a variant of `big_sepL_lookup_acc` which allows
updating the value.
* Add many missing `Proper`/non-expansiveness lemmas for big-ops.
* Add `big_*_insert_delete` lemmas to split a `<[i:=x]> m` map into `i` and the rest.
* Seal the definitions of `big_opS`, `big_opMS`, `big_opM` and `big_sepM2`
to prevent undesired simplification.
* Fix `big_sepM2_fmap*` only working for `nat` keys.
**Changes in `proofmode`:**
* Make use of `notypeclasses refine` in the implementation of `iPoseProof` and
`iAssumption`, see <https://gitlab.mpi-sws.org/iris/iris/merge_requests/329>.
This has two consequences:
1. Coq's "new" unification algorithm (the one in `refine`, not the "old" one
in `apply`) is used more often by the proof mode tactics.
2. Due to the use of `notypeclasses refine`, TC constraints are solved less
eagerly, see <https://github.com/coq/coq/issues/6583>.
In order to port your development, it is often needed to instantiate evars
explicitly (since TC search is performed less eagerly), and in few cases it is
needed to unfold definitions explicitly (due to new unification algorithm
behaving differently).
* Strengthen the tactics `iDestruct`, `iPoseProof`, and `iAssert`:
- They succeed in certain cases where they used to fail.
- They keep certain hypotheses in the intuitionistic context, where they were
moved to the spatial context before.
The latter can lead to stronger proof mode contexts, and therefore to
backwards incompatibility. This can usually be fixed by manually clearing some
hypotheses. A more detailed description of the changes can be found in
<https://gitlab.mpi-sws.org/iris/iris/merge_requests/341>.
* Remove the long-deprecated `cofeT` alias (for `ofeT`) and `dec_agree` RA (use
`agree` instead).
* Add `auto` hint for `∗-∗`.
* Add new tactic `iStopProof` to turn the proof mode entailment into an ordinary
Coq goal `big star of context ⊢ proof mode goal`.
* Add new introduction pattern `-# pat` that moves a hypothesis from the
intuitionistic context to the spatial context.
* The tactic `iAssumption` also recognizes assumptions `⊢ P` in the Coq context.
* Better support for telescopes in the proof mode, i.e., all tactics should
recognize and distribute telescopes now.
* The proof mode now supports names for pure facts in intro patterns. Support
requires implementing `string_to_ident`. Without this tactic such patterns
will fail. We provide one implementation using Ltac2 which works with Coq 8.11
and can be installed with opam; see
[iris/string-ident](https://gitlab.mpi-sws.org/iris/string-ident) for details.
**Changes in `algebra`:**
* Remove `Core` type class for defining the total core; it is now always
defined in terms of the partial core. The only user of this type class was the
STS RA.
* The functions `{o,r,ur}Functor_diag` are no longer coercions, and renamed into
`{o,r,ur}Functor_apply` to better match their intent. This fixes "ambiguous
coercion path" warnings.
* Rename `{o,r,ur}Functor_{ne,id,compose,contractive}` into
`{o,r,ur}Functor_map_{ne,id,compose,contractive}`.
* Move derived camera constructions (`frac_auth` and `ufrac_auth`) to the folder
`algebra/lib`.
* Rename `mnat` to `max_nat` and "box" it by creating a separate type for it.
* Move the RAs for `nat` and `positive` and the `mnat` RA into a separate
module. They must now be imported from `From iris.algebra Require Import
numbers`.
* Make names of `f_op`/`f_core` rewrite lemmas more consistent by always making
`_core`/`_op` the suffix:
`op_singleton``singleton_op`, `core_singleton``singleton_core`,
`discrete_fun_op_singleton``discrete_fun_singleton_op`,
`discrete_fun_core_singleton``discrete_fun_singleton_core`,
`list_core_singletonM``list_singleton_core`,
`list_op_singletonM``list_singleton_op`,
`sts_op_auth_frag``sts_auth_frag_op`,
`sts_op_auth_frag_up``sts_auth_frag_up_op`,
`sts_op_frag``sts_frag_op`,
`list_op_length``list_length_op`,
`list_core_singletonM``list_singletonM_core`,
`list_op_singletonM``list_singletonM_op`.
* All list "map singleton" lemmas consistently use `singletonM` in their name:
`list_singleton_valid``list_singletonM_valid`,
`list_singleton_core_id``list_singletonM_core_id`,
`list_singleton_snoc``list_singletonM_snoc`,
`list_singleton_updateP``list_singletonM_updateP`,
`list_singleton_updateP'``list_singletonM_updateP'`,
`list_singleton_update``list_singletonM_update`,
`list_alloc_singleton_local_update``list_alloc_singletonM_local_update`.
* Remove `auth_both_op` and rename `auth_both_frac_op` into `auth_both_op`.
* Add lemma `singleton_included : {[ i := x ]} ≼ ({[ i := y ]} ↔ x ≡ y ∨ x ≼ y`,
and rename existing asymmetric lemmas (with a singleton on just the LHS):
`singleton_includedN``singleton_includedN_l`,
`singleton_included``singleton_included_l`,
`singleton_included_exclusive``singleton_included_exclusive_l`.
* Add notion `ofe_iso A B` that states that OFEs `A` and `B` are
isomorphic. This is used in the COFE solver.
* Add `{o,r,ur}Functor_oFunctor_compose` for composition of functors.
* Add `pair_op_1` and `pair_op_2` to split a pair where one component is the unit.
* Add derived camera construction `excl_auth A` for `auth (option (excl A))`.
* Make lemma `Excl_included` a bi-implication.
* Make `auth_update_core_id` work with any fraction of the authoritative
element.
* Add `min_nat`, an RA for natural numbers with `min` as the operation.
* Add many missing `Proper`/non-expansiveness lemmas for maps and lists.
* Add `list_singletonM_included` and `list_lookup_singletonM_{lt,gt}` lemmas
about singletons in the list RA.
* Add `list_core_id'`, a stronger version of `list_core_id` which only talks
about elements that are actually in the list.
The following `sed` script helps adjust your code to the renaming (on macOS,
replace `sed` by `gsed`, installed via e.g. `brew install gnu-sed`).
Note that the script is not idempotent, do not run it twice.
```
sed -i -E '
# functor renames
s/\b(o|r|ur)Functor_(ne|id|compose|contractive)\b/\1Functor_map_\2/g
# singleton_included renames
s/\bsingleton_includedN\b/singleton_includedN_l/g
s/\bsingleton_included\b/singleton_included_l/g
s/\bsingleton_included_exclusive\b/singleton_included_exclusive_l/g
# f_op/f_core renames
s/\b(op|core)_singleton\b/singleton_\1/g
s/\bdiscrete_fun_(op|core)_singleton\b/discrete_fun_singleton_\1/g
s/\bsts_op_(auth_frag|auth_frag_up|frag)\b/sts_\1_op/g
s/\blist_(op|core)_singletonM\b/list_singletonM_\1/g
s/\blist_op_length\b/list_length_op/g
# list "singleton map" renames
s/\blist_singleton_valid\b/list_singletonM_valid/g
s/\blist_singleton_core_id\b/list_singletonM_core_id/g
s/\blist_singleton_snoc\b/list_singletonM_snoc/g
s/\blist_singleton_updateP\b/list_singletonM_updateP/g
s/\blist_singleton_update\b/list_singletonM_update/g
s/\blist_alloc_singleton_local_update\b/list_alloc_singletonM_local_update/g
# inv renames
s/\binv_sep(|_1|_2)\b/inv_split\1/g
s/\binv_acc\b/inv_alter/g
s/\binv_open(|_strong|_timeless)\b/inv_acc\1/g
s/\bcinv_open(|_strong)\b/cinv_acc\1/g
s/\b(na_inv|auth|sts)_open\b/\1_acc/g
# miscellaneous
s/\bauth_both_frac_op\b/auth_both_op/g
s/\bmnat\b/max_nat/g
s/\bcoreP_wand\b/coreP_entails/g
' $(find theories -name "*.v")
```
## Iris 3.2.0 (released 2019-08-29)
The highlight of this release is the completely re-engineered interactive proof
mode. Not only did many tactics become more powerful; the entire proof mode can
now be used not just for Iris but also for other separation logics satisfying
the proof mode interface (e.g., [Iron] and [GPFSL]). Also see the
[accompanying paper][MoSeL].
[Iron]: https://iris-project.org/iron/
[GPFSL]: https://gitlab.mpi-sws.org/iris/gpfsl/
[MoSeL]: https://iris-project.org/mosel/
Beyond that, the Iris program logic gained the ability to reason about
potentially stuck programs, and a significantly strengthened adequacy theorem
that unifies the three previously separately presented theorems. There are now
also Hoare triples for total program correctness (but with very limited support
for invariants) and logical atomicity.
And finally, our example language HeapLang was made more realistic
(Compare-and-set got replaced by compare-exchange and limited to only compare
values that can actually be compared atomically) and more powerful, with added
support for arrays and prophecy variables.
Further details are given in the changelog below.
This release of Iris received contributions by Aleš Bizjak, Amin Timany, Dan
Frumin, Glen Mével, Hai Dang, Hugo Herbelin, Jacques-Henri Jourdan, Jan Menz,
Jan-Oliver Kaiser, Jonas Kastberg Hinrichsen, Joseph Tassarotti, Mackie Loeffel,
Marianna Rapoport, Maxime Dénès, Michael Sammler, Paolo G. Giarrusso,
Pierre-Marie Pédrot, Ralf Jung, Robbert Krebbers, Rodolphe Lepigre, and Tej
Chajed. Thanks a lot to everyone involved!
**Changes in the theory of Iris itself:**
* Change in the definition of WP, so that there is a fancy update between
the quantification over the next states and the later modality. This makes it
possible to prove more powerful lifting lemmas: The new versions feature an
"update that takes a step".
* Add weakest preconditions for total program correctness.
* "(Potentially) stuck" weakest preconditions and the "plainly modality" are no
longer considered experimental.
* Add the notion of an "observation" to the language interface, so that
every reduction step can optionally be marked with an event, and an execution
trace has a matching list of events. Change WP so that it is told the entire
future trace of observations from the beginning.
* The Löb rule is now a derived rule; it follows from later-intro, later
being contractive and the fact that we can take fixpoints of contractive
functions.
* Add atomic updates and logically atomic triples, including tactic support.
See `heap_lang/lib/increment.v` for an example.
* Extend the state interpretation with a natural number that keeps track of
the number of forked-off threads, and have a global fixed proposition that
describes the postcondition of each forked-off thread (instead of it being
`True`).
* A stronger adequacy statement for weakest preconditions that involves
the final state, the post-condition of forked-off threads, and also applies if
the main-thread has not terminated.
* The user-chosen functor used to instantiate the Iris logic now goes from
COFEs to Cameras (it was OFEs to Cameras).
**Changes in heap_lang:**
* CAS (compare-and-set) got replaced by CmpXchg (compare-exchange). The
difference is that CmpXchg returns a pair consisting of the old value and a
boolean indicating whether the comparison was successful and hence the
exchange happened. CAS can be obtained by simply projecting to the second
component, but also providing the old value more closely models the primitive
typically provided in systems languages (C, C++, Rust).
The comparison by this operation also got weakened to be efficiently
implementable: CmpXchg may only be used to compare "unboxed" values that can
be represented in a single machine word. It is sufficient if one of the two
compared values is unboxed.
* For consistency, the restrictions CmpXchg imposes on comparison also apply to
the `=` binary operator. This also fixes the long-standing problem that that
operator allowed compared closures with each other.
* Implement prophecy variables using the new support for "observations". The
erasure theorem (showing that prophecy variables do not alter program
behavior) can be found [in the iris/examples repository][prophecy-erasure].
* heap_lang now uses right-to-left evaluation order. This makes it
significantly easier to write specifications of curried functions.
* heap_lang values are now injected in heap_lang expressions via a specific
constructor of the expr inductive type. This simplifies much the tactical
infrastructure around the language. In particular, this allow us to get rid
the reflection mechanism that was needed for proving closedness, atomicity and
"valueness" of a term. The price to pay is the addition of new
"administrative" reductions in the operational semantics of the language.
* heap_lang now has support for allocating, accessing and reasoning about arrays
(continuously allocated regions of memory).
* One can now assign "meta" data to heap_lang locations.
[prophecy-erasure]: https://gitlab.mpi-sws.org/iris/examples/blob/3f33781fe6e19cfdb25259c8194d34403f1134d5/theories/logatom/proph_erasure.v
**Changes in Coq:**
* An all-new generalized proof mode that abstracts away from Iris! Major new
features:
- The proof mode can now be used with logics derived from Iris (like iGPS),
with non-step-indexed logics and even with non-affine (i.e., linear) logics.
- `iModIntro` is more flexible and more powerful, it now also subsumes
`iNext` and `iAlways`.
- General infrastructure for deriving a logic for monotone predicates over
an existing logic (see the paper for more details).
Developments instantiating the proof mode typeclasses may need significant
changes. For developments just using the proof mode tactics, porting should
not be too much effort. Notable things to port are:
- All the BI laws moved from the `uPred` module to the `bi` module. For
example, `uPred.later_equivI` became `bi.later_equivI`.
- Big-ops are automatically imported, imports of `iris.base_logic.big_op` have
to be removed.
- The ⊢ notation can sometimes infer different (but convertible) terms when
searching for the BI to use, which (due to Coq limitations) can lead to
failing rewrites, in particular when rewriting at function types.
* The `iInv` tactic can now be used without the second argument (the name for
the closing update). It will then instead add the obligation to close the
invariant to the goal.
* The new `iEval` tactic can be used to execute a simplification or rewriting
tactic on some specific part(s) of the proofmode goal.
* Added support for defining derived connectives involving n-ary binders using
telescopes.
* The proof mode now more consistently "prettifies" the goal after each tactic.
Prettification also simplifies some BI connectives, like conditional
modalities and telescope quantifiers.
* Improved pretty-printing of Iris connectives (in particular WP and fancy
updates) when Coq has to line-wrap the output. This goes hand-in-hand with an
improved test suite that also tests pretty-printing.
* Added a `gmultiset` RA.
* Rename `timelessP``timeless` (projection of the `Timeless` class)
* The CMRA axiom `cmra_extend` is now stated in `Type`, using `sigT` instead of
in `Prop` using `exists`. This makes it possible to define the function space
CMRA even for an infinite domain.
* Rename proof mode type classes for laters:
- `IntoLaterN``MaybeIntoLaterN` (this one _may_ strip a later)
- `IntoLaterN'``IntoLaterN` (this one _should_ strip a later)
- `IntoLaterNEnv``MaybeIntoLaterNEnv`
- `IntoLaterNEnvs``MaybeIntoLaterNEnvs`
* Rename:
- `frag_auth_op``frac_auth_frag_op`
- `cmra_opM_assoc``cmra_op_opM_assoc`
- `cmra_opM_assoc_L``cmra_op_opM_assoc_L`
- `cmra_opM_assoc'``cmra_opM_opM_assoc`
* `namespaces` has been moved to std++.
* Changed `IntoVal` to be directly usable for rewriting `e` into `of_val v`, and
changed `AsVal` to be usable for rewriting via the `[v <-]` destruct pattern.
* `wp_fork` is now written in curried form.
* `PureExec`/`wp_pure` now supports taking multiple steps at once.
* A new tactic, `wp_pures`, executes as many pure steps as possible, excluding
steps that would require unlocking subterms. Every impure wp_ tactic executes
this tactic before doing anything else.
* Add `big_sepM_insert_acc`.
* Add big separating conjunctions that operate on pairs of lists (`big_sepL2`)
and on pairs of maps (`big_sepM2`). In the former case the lists are required
to have the same length, and in the latter case the maps are required to
have the same domains.
* The `_strong` lemmas (e.g. `own_alloc_strong`) work for all infinite
sets, instead of just for cofinite sets. The versions with cofinite
sets have been renamed to use the `_cofinite` suffix.
* Remove locked value lambdas. The value scope notations `rec: f x := e` and
`(λ: x, e)` no longer add a `locked`. Instead, we made the `wp_` tactics
smarter to no longer unfold lambdas/recs that occur behind definitions.
* Export the fact that `iPreProp` is a COFE.
* The CMRA `auth` now can have fractional authoritative parts. So now `auth` has
3 types of elements: the fractional authoritative `●{q} a`, the full
authoritative `● a ≡ ●{1} a`, and the non-authoritative `◯ a`. Updates are
only possible with the full authoritative element `● a`, while fractional
authoritative elements have agreement: `✓ (●{p} a ⋅ ●{q} b) ⇒ a ≡ b`. As a
consequence, `auth` is no longer a COFE and does not preserve Leibniz
equality.
* Add a COFE construction (and functor) on dependent pairs `sigTO`, dual to
`discrete_funO`.
* Rename in `auth`:
- Use `auth_auth_proj`/`auth_frag_proj` for the projections of `auth`:
`authoritative``auth_auth_proj` and `auth_own``auth_frag_proj`.
- Use `auth_auth` and `auth_frag` for the injections into authoritative
elements and non-authoritative elements respectively.
- Lemmas for the projections and injections are renamed accordingly.
For examples:
+ `authoritative_validN``auth_auth_proj_validN`
+ `auth_own_validN``auth_frag_proj_validN`
+ `auth_auth_valid` was not renamed because it was already used for the
authoritative injection.
- `auth_both_valid``auth_both_valid_2`
- `auth_valid_discrete_2``auth_both_valid`
* Add the camera `ufrac` for unbounded fractions (i.e. without fractions that
can be `> 1`) and the camera `ufrac_auth` for a variant of the authoritative
fractional camera (`frac_auth`) with unbounded fractions.
* Changed `frac_auth` notation from `●!`/`◯!` to `●F`/`◯F`. sed script:
`s/◯!/◯F/g; s/●!/●F/g;`.
* Lemma `prop_ext` works in both directions; its default direction is the
opposite of what it used to be.
* Make direction of `f_op` rewrite lemmas more consistent: Flip `pair_op`,
`Cinl_op`, `Cinr_op`, `cmra_morphism_op`, `cmra_morphism_pcore`,
`cmra_morphism_core`.
* Rename lemmas `fupd_big_sep{L,M,S,MS}` into `big_sep{L,M,S,MS}_fupd` to be
consistent with other such big op lemmas. Also add such lemmas for `bupd`.
* Rename `C` suffixes into `O` since we no longer use COFEs but OFEs. Also
rename `ofe_fun` into `discrete_fun` and the corresponding notation `-c>` into
`-d>`. The renaming can be automatically done using the following script
(on macOS, replace `sed` by `gsed`, installed via e.g. `brew install gnu-sed`):
```
sed -i '
s/\bCofeMor/OfeMor/g;
s/\-c>/\-d>/g;
s/\bcFunctor/oFunctor/g;
s/\bCFunctor/OFunctor/g;
s/\b\%CF/\%OF/g;
s/\bconstCF/constOF/g;
s/\bidCF/idOF/g
s/\bdiscreteC/discreteO/g;
s/\bleibnizC/leibnizO/g;
s/\bunitC/unitO/g;
s/\bprodC/prodO/g;
s/\bsumC/sumO/g;
s/\bboolC/boolO/g;
s/\bnatC/natO/g;
s/\bpositiveC/positiveO/g;
s/\bNC/NO/g;
s/\bZC/ZO/g;
s/\boptionC/optionO/g;
s/\blaterC/laterO/g;
s/\bofe\_fun/discrete\_fun/g;
s/\bdiscrete\_funC/discrete\_funO/g;
s/\bofe\_morC/ofe\_morO/g;
s/\bsigC/sigO/g;
s/\buPredC/uPredO/g;
s/\bcsumC/csumO/g;
s/\bagreeC/agreeO/g;
s/\bauthC/authO/g;
s/\bnamespace_mapC/namespace\_mapO/g;
s/\bcmra\_ofeC/cmra\_ofeO/g;
s/\bucmra\_ofeC/ucmra\_ofeO/g;
s/\bexclC/exclO/g;
s/\bgmapC/gmapO/g;
s/\blistC/listO/g;
s/\bvecC/vecO/g;
s/\bgsetC/gsetO/g;
s/\bgset\_disjC/gset\_disjO/g;
s/\bcoPsetC/coPsetO/g;
s/\bgmultisetC/gmultisetO/g;
s/\bufracC/ufracO/g
s/\bfracC/fracO/g;
s/\bvalidityC/validityO/g;
s/\bbi\_ofeC/bi\_ofeO/g;
s/\bsbi\_ofeC/sbi\_ofeO/g;
s/\bmonPredC/monPredO/g;
s/\bstateC/stateO/g;
s/\bvalC/valO/g;
s/\bexprC/exprO/g;
s/\blocC/locO/g;
s/\bdec\_agreeC/dec\_agreeO/g;
s/\bgnameC/gnameO/g;
s/\bcoPset\_disjC/coPset\_disjO/g;
' $(find theories -name "*.v")
```
## Iris 3.1.0 (released 2017-12-19)
**Changes in and extensions of the theory:**
* Define `uPred` as a quotient on monotone predicates `M -> SProp`.
* Get rid of some primitive laws; they can be derived:
`True ⊢ □ True` and `□ (P ∧ Q) ⊢ □ (P ∗ Q)`
* Camera morphisms have to be homomorphisms, not just monotone functions.
* Add a proof that `f` has a fixed point if `f^k` is contractive.
* Constructions for least and greatest fixed points over monotone predicates
(defined in the logic of Iris using impredicative quantification).
* Add a proof of the inverse of `wp_bind`.
* [Experimental feature] Add new modality: ■ ("plainly").
* [Experimental feature] Support verifying code that might get stuck by
distinguishing "non-stuck" vs. "(potentially) stuck" weakest
preconditions. (See [Swasey et al., OOPSLA '17] for examples.) The non-stuck
`WP e @ E {{ Φ }}` ensures that, as `e` runs, it does not get stuck. The stuck
`WP e @ E ?{{ Φ }}` ensures that, as usual, all invariants are preserved while
`e` runs, but it permits execution to get stuck. The former implies the
latter. The full judgment is `WP e @ s; E {{ Φ }}`, where non-stuck WP uses
*stuckness bit* `s = NotStuck` while stuck WP uses `s = MaybeStuck`.
**Changes in Coq:**
* Move the `prelude` folder to its own project:
[coq-std++](https://gitlab.mpi-sws.org/robbertkrebbers/coq-stdpp)
* Some extensions/improvements of heap_lang:
- Improve handling of pure (non-state-dependent) reductions.
- Add fetch-and-add (`FAA`) operation.
- Add syntax for all Coq's binary operations on `Z`.
* Generalize `saved_prop` to let the user choose the location of the type-level
later. Rename the general form to `saved_anything`. Provide `saved_prop` and
`saved_pred` as special cases.
* Improved big operators:
+ They are no longer tied to cameras, but work on any monoid
+ The version of big operations over lists was redefined so that it enjoys
more definitional equalities.
* Rename some things and change notation:
- The unit of a camera: `empty` -> `unit`, `∅` -> `ε`
- Disjointness: `⊥` -> `##`
- A proof mode type class `IntoOp` -> `IsOp`
- OFEs with all elements being discrete: `Discrete` -> `OfeDiscrete`
- OFE elements whose equality is discrete: `Timeless` -> `Discrete`
- Timeless propositions: `TimelessP` -> `Timeless`
- Camera elements such that `core x = x`: `Persistent` -> `CoreId`
- Persistent propositions: `PersistentP` -> `Persistent`
- The persistent modality: `always` -> `persistently`
- Adequacy for non-stuck weakestpre: `adequate_safe` -> `adequate_not_stuck`
- Consistently SnakeCase identifiers:
+ `CMRAMixin` -> `CmraMixin`
+ `CMRAT` -> `CmraT`
+ `CMRATotal` -> `CmraTotal`
+ `CMRAMorphism` -> `CmraMorphism`
+ `CMRADiscrete` -> `CmraDiscrete`
+ `UCMRAMixin` -> `UcmraMixin`
+ `UCMRAT` -> `UcmraT`
+ `DRAMixin` -> `DraMixin`
+ `DRAT` -> `DraT`
+ `STS` -> `Sts`
- Many lemmas also changed their name. `always_*` became `persistently_*`,
and furthermore: (the following list is not complete)
+ `impl_wand` -> `impl_wand_1` (it only involves one direction of the
equivalent)
+ `always_impl_wand` -> `impl_wand`
+ `always_and_sep_l` -> `and_sep_l`
+ `always_and_sep_r` -> `and_sep_r`
+ `always_sep_dup` -> `sep_dup`
+ `wand_impl_always` -> `impl_wand_persistently` (additionally,
the direction of this equivalence got swapped for consistency's sake)
+ `always_wand_impl` -> `persistently_impl_wand` (additionally, the
direction of this equivalence got swapped for consistency's sake)
The following `sed` snippet should get you most of the way (on macOS you will
have to replace `sed` by `gsed`, installed via e.g. `brew install gnu-sed`):
```
sed -i 's/\bPersistentP\b/Persistent/g; s/\bTimelessP\b/Timeless/g; s/\bCMRADiscrete\b/CmraDiscrete/g; s/\bCMRAT\b/CmraT/g; s/\bCMRAMixin\b/CmraMixin/g; s/\bUCMRAT\b/UcmraT/g; s/\bUCMRAMixin\b/UcmraMixin/g; s/\bSTS\b/Sts/g' $(find -name "*.v")
```
* `PersistentL` and `TimelessL` (persistence and timelessness of lists of
propositions) are replaces by `TCForall` from std++.
* Fix a bunch of consistency issues in the proof mode, and make it overall more
usable. In particular:
- All proof mode tactics start the proof mode if necessary; `iStartProof` is
no longer needed and should only be used for building custom proof mode
tactics.
- Change in the grammar of specialization patterns: `>[...]` -> `[> ...]`
- Various new specification patterns for `done` and framing.
- There is common machinery for symbolic execution of pure reductions. This
is provided by the type classes `PureExec` and `IntoVal`.
- There is a new connective `tc_opaque`, which can be used to make definitions
opaque for type classes, and thus opaque for most tactics of the proof
mode.
- Define Many missing type class instances for distributing connectives.
- Implement the tactics `iIntros (?)` and `iIntros "!#"` (i.e. `iAlways`)
using type classes. This makes them more generic, e.g., `iIntros (?)` also
works when the universal quantifier is below a modality, and `iAlways` also
works for the plainness modality. A breaking change, however, is that these
tactics now no longer work when the universal quantifier or modality is
behind a type class opaque definition. Furthermore, this can change the
name of anonymous identifiers introduced with the "%" pattern.
* Make `ofe_fun` dependently typed, subsuming `iprod`. The latter got removed.
* Define the generic `fill` operation of the `ectxi_language` construct in terms
of a left fold instead of a right fold. This gives rise to more definitional
equalities.
* The language hierarchy (`language`, `ectx_language`, `ectxi_language`) is now
fully formalized using canonical structures instead of using a mixture of
type classes and canonical structures. Also, it now uses explicit mixins. The
file `program_logic/ectxi_language` contains some documentation on how to
setup Iris for your language.
* Restore the original, stronger notion of atomicity alongside the weaker
notion. These are `Atomic a e` where the stuckness bit `s` indicates whether
expression `e` is weakly (`a = WeaklyAtomic`) or strongly
(`a = StronglyAtomic`) atomic.
* Various improvements to `solve_ndisj`.
* Use `Hint Mode` to prevent Coq from making arbitrary guesses in the presence
of evars, which often led to divergence. There are a few places where type
annotations are now needed.
* The rules `internal_eq_rewrite` and `internal_eq_rewrite_contractive` are now
stated in the logic, i.e., they are `iApply`-friendly.
## Iris 3.0.0 (released 2017-01-11)
* There now is a deprecation process. The modules `*.deprecated` contain
deprecated notations and definitions that are provided for backwards
compatibility and will be removed in a future version of Iris.
* View shifts are radically simplified to just internalize frame-preserving
updates. Weakestpre is defined inside the logic, and invariants and view
shifts with masks are also coded up inside Iris. Adequacy of weakestpre
is proven in the logic.
* With invariants and the physical state being handled in the logic, there
is no longer any reason to demand the CMRA unit to be discrete.
shifts with masks are also coded up inside Iris. Adequacy of weakestpre is
proven in the logic. The old ownership of the entire physical state is
replaced by a user-selected predicate over physical state that is maintained
by weakestpre.
* Use OFEs instead of COFEs everywhere. COFEs are only used for solving the
recursive domain equation. As a consequence, CMRAs no longer need a proof of
completeness. (The old `cofeT` is provided by `algebra.deprecated`.)
* Implement a new agreement construction. Unlike the old one, this one
preserves discreteness. dec_agree is thus no longer needed and has been moved
to algebra.deprecated.
* Renaming and moving things around: uPred and the rest of the base logic are in
`base_logic`, while `program_logic` is for everything involving the general
Iris notion of a language.
* Renaming in prelude.list: Rename `prefix_of` -> `prefix` and `suffix_of` ->
`suffix` in lemma names, but keep notation ``l1 `prefix_of` l2`` and ``l1
`suffix_of` l2``. `` l1 `sublist` l2`` becomes ``l1 `sublist_of` l2``. Rename
`contains` -> `submseteq` and change `` l1 `contains` l2`` to ``l1 ⊆+ l2``.
* Slightly weaker notion of atomicity: an expression is atomic if it reduces in
one step to something that does not reduce further.
* Changed notation for embedding Coq assertions into Iris. The new notation is
⌜φ⌝. Also removed `=` and `⊥` from the Iris scope. (The old notations are
provided in `base_logic.deprecated`.)
* Up-closure of namespaces is now a notation (↑) instead of a coercion.
* With invariants and the physical state being handled in the logic, there is no
longer any reason to demand the CMRA unit to be discrete.
* The language can now fork off multiple threads at once.
* Local Updates (for the authoritative monoid) are now a 4-way relation
with syntax-directed lemmas proving them.
* Local Updates (for the authoritative monoid) are now a 4-way relation with
syntax-directed lemmas proving them.
## Iris 2.0
......@@ -30,7 +2173,7 @@ This version matches the ESOP submission.
## Iris 2.0-rc2
This version matches the final ICFP paper.
This version matches the final ICFP 2016 paper.
* [algebra] Make the core of an RA or CMRA a partial function.
* [program_logic/lifting] Lifting lemmas no longer round-trip through a
......@@ -40,4 +2183,4 @@ This version matches the final ICFP paper.
## Iris 2.0-rc1
This is the Coq development and Iris Documentation as submitted to ICFP.
This is the Coq development and Iris Documentation as submitted to ICFP 2016.
# Contributing to the Iris Coq Development
Here you can find some how-tos for various thing sthat might come up when doing
Iris development. This is for contributing to Iris itself; see
[the README](README.md#further-resources) for resources helpful for all Iris
users.
To work on Iris itself, you need to install its build-dependencies. Again we
recommend you do that with opam (2.0.0 or newer). This requires the following
two repositories:
opam repo add coq-released https://coq.inria.fr/opam/released
opam repo add iris-dev https://gitlab.mpi-sws.org/iris/opam.git
Once you got opam set up, run `make builddep` to install the right versions
of the dependencies.
Run `make -jN` to build the full development, where `N` is the number of your
CPU cores.
To update Iris, do `git pull`. After an update, the development may fail to
compile because of outdated dependencies. To fix that, please run `opam update`
followed by `make builddep`.
## How to submit a merge request
To contribute code, you need an MPI-SWS GitLab account as described on the
[chat page](https://iris-project.org/chat.html). Then you can fork the
[Iris git repository][iris], make your changes in your fork, and create a merge
request. If forking fails with an error, please send your MPI-SWS GitLab
username to [Ralf Jung][jung] to unlock forks for your account.
Please do *not* use the master branch of your fork, that might confuse CI. Use
a feature branch instead.
[jung]: https://gitlab.mpi-sws.org/jung
[iris]: https://gitlab.mpi-sws.org/iris/iris
We prefer small and self-contained merge requests that add a single feature
over merge requests that add arbitrary collections of lemmas. Small merge
requests are easier to review, and will typically be merged more quickly
(because it avoids blocking the whole merge request on a single
discussion).
Please follow the coding style laid out in our [style
guide](docs/style_guide.md).
## How to update the std++ dependency
* Do the change in std++, push it.
* Wait for CI to publish a new std++ version on the opam archive, then run
`opam update iris-dev`.
* In Iris, change the `opam` file to depend on the new version.
(In case you do not use opam yourself, you can see recently published versions
[in this repository](https://gitlab.mpi-sws.org/iris/opam/commits/master).)
* Run `make builddep` (in Iris) to install the new version of std++.
You may have to do `make clean` as Coq will likely complain about .vo file
mismatches.
## How to write/update test cases
The files in `tests/` are test cases. Each of the `.v` files comes with a
matching `.ref` file containing the expected output of `coqc`. Adding `Show.`
in selected places in the proofs makes `coqc` print the current goal state.
This is used to make sure the proof mode prints goals and reduces terms the way
we expect it to. You can run `make MAKE_REF=1` to re-generate all the `.ref` files;
this is useful after adding or removing `Show.` from a test. If you do this,
make sure to check the diff for any unexpected changes in the output!
Some test cases have per-Coq-version `.ref` files (e.g., `atomic.8.8.ref` is a
Coq-8.8-specific `.ref` file). If you change one of these, remember to update
*all* the `.ref` files.
If you want to compile without tests run `make NO_TEST=1`.
## How to build/install only one package
Iris is split into multiple packages that can be installed separately via opam.
You can invoke the Makefile of a particular package by doing `./make-package
$PACKAGE $MAKE_ARGS`, where `$MAKE_ARGS` are passed to `make` (so you can use
the usual `-jN`, `install`, ...). This should only rarely be necessary. For
example, if you are not using opam and you want to install only the `iris`
package (without HeapLang, to avoid waiting on that part of the build), you can
do `./make-package iris install`. (If you are using opam, you can achieve the
same by pinning `coq-iris` to your Iris checkout.)
Note that `./make-package` will never run the test suite, so please always do a
regular `make -jN` before submitting an MR.
## How to test effects on reverse dependencies
The `iris-bot` script makes it easy to test the effect of a branch on reverse
dependencies. It can start tests ensuring they all still build, and it can do
comparative timing runs.
If you have suitable permissions, you can trigger these builds yourself.
But first, you need to do some setup: you need to create a GitLab access token
and set the `GITLAB_TOKEN` environment variable to it. Go to
<https://gitlab.mpi-sws.org/-/profile/personal_access_tokens>, pick a suitable
name (such as "iris-bot"), select the "api" scope, and then click "Create
personal access token". Copy the value it shows and store it in some suitable
place; you will not be able to retrieve this value from GitLab in the future!
For example, you could create a `.env` file in your Iris clone containing:
```
export GITLAB_TOKEN=<your token here>
```
Then you can easily get the token back into the environment via `. .env`.
Once that setup is done, you can now use `iris-bot`. Set at least one of
`IRIS_REV` or `STDPP_REV` to control which branches of these projects to build
against (they default to the default git branch). `IRIS_REPO` and `STDPP_REPO`
can be used to control the repository in which the branch is situated. Setting
`IRIS` to "user:branch" will use the given branch on that user's fork of Iris,
and similar for `STDPP`.
Supported commands:
- `./iris-bot build [$filter]`: Builds all reverse dependencies against the
given branches. The optional `filter` argument only builds projects whose
names contains that string.
- `./iris-bot time $project`: Measure the impact of this branch on the build
time of the given reverse dependency. Only Iris branches are supported for
now.
Examples:
- `IRIS_REV=myname/mybranch ./iris-bot build` builds *all* reverse dependencies
against `myname/mybranch` from the main Iris repository.
- `IRIS=user:branch ./iris-bot build examples` builds the [examples] against
the `branch` in `user`'s fork of Iris.
- `IRIS_REV=myname/mybranch ./iris-bot time examples` measures the timing impact
of `myname/mybranch` from the main Iris repository on the [examples].
[examples]: https://gitlab.mpi-sws.org/iris/examples
The source code (i.e., everything except for files in the docs/ folder) in this
development is licensed under the terms of the BSD license, while the
documentation (i.e., everything inside the docs/ folder) is licensed under the
terms of the CC-BY 4.0 license. Fur further details, see LICENSE-CODE and
LICENSE-DOCS, respectively.
The source code (i.e., everything except for files in the docs/ and tex/
folders) in this development is licensed under the terms of the BSD license,
while the documentation (i.e., everything inside the docs/ and tex/ folders) is
licensed under the terms of the CC-BY 4.0 license. Fur further details, see
LICENSE-CODE and LICENSE-DOCS, respectively.
All files in this development, excluding those in docs/, are distributed
under the terms of the BSD license, included below.
All files in this development, excluding those in docs/ and tex/, are
distributed under the terms of the 3-clause BSD license
(https://opensource.org/licenses/BSD-3-Clause), included below.
------------------------------------------------------------------------------
Copyright: Iris developers and contributors
BSD LICENCE
------------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
......@@ -12,17 +13,17 @@ modification, are permitted provided that the following conditions are met:
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
* Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
All files in the docs/ folder of this development are distributed
All files in the docs/ and tex/ folders of this development are distributed
under the terms of the CC-BY 4.0 license <https://creativecommons.org/licenses/by/4.0/>.
For your convenience, a plain-text version of the license is included below.
......
# Makefile originally taken from coq-club
%: Makefile.coq phony
+make -f Makefile.coq $@
# Default target
all: Makefile.coq
+make -f Makefile.coq all
+@$(MAKE) -f Makefile.coq all
.PHONY: all
clean: Makefile.coq
+make -f Makefile.coq clean
rm -f Makefile.coq
Makefile.coq: _CoqProject Makefile
coq_makefile -f _CoqProject | sed 's/$$(COQCHK) $$(COQCHKFLAGS) $$(COQLIBS)/$$(COQCHK) $$(COQCHKFLAGS) $$(subst -Q,-R,$$(COQLIBS))/' > Makefile.coq
# Build with dune.
# This exists only for CI; you should just call `dune build` directly instead.
dune:
@dune build --display=short
.PHONY: dune
_CoqProject: ;
Makefile: ;
# Permit local customization
-include Makefile.local
# Forward most targets to Coq makefile (with some trick to make this phony)
%: Makefile.coq phony
@#echo "Forwarding $@"
+@$(MAKE) -f Makefile.coq $@
phony: ;
.PHONY: phony
.PHONY: all clean phony
clean: Makefile.coq
+@$(MAKE) -f Makefile.coq clean
@# Make sure not to enter the `_opam` folder.
find [a-z]*/ \( -name "*.d" -o -name "*.vo" -o -name "*.vo[sk]" -o -name "*.aux" -o -name "*.cache" -o -name "*.glob" -o -name "*.vio" \) -print -delete || true
rm -f Makefile.coq .lia.cache builddep/*
.PHONY: clean
# Create Coq Makefile.
Makefile.coq: _CoqProject Makefile
"$(COQBIN)coq_makefile" -f _CoqProject -o Makefile.coq $(EXTRA_COQFILES)
# Install build-dependencies
OPAMFILES=$(wildcard *.opam)
BUILDDEPFILES=$(addsuffix -builddep.opam, $(addprefix builddep/,$(basename $(OPAMFILES))))
builddep/%-builddep.opam: %.opam Makefile
@echo "# Creating builddep package for $<."
@mkdir -p builddep
@sed <$< -E 's/^(build|install|remove):.*/\1: []/; s/"(.*)"(.*= *version.*)$$/"\1-builddep"\2/;' >$@
builddep-opamfiles: $(BUILDDEPFILES)
.PHONY: builddep-opamfiles
builddep: builddep-opamfiles
@# We want opam to not just install the build-deps now, but to also keep satisfying these
@# constraints. Otherwise, `opam upgrade` may well update some packages to versions
@# that are incompatible with our build requirements.
@# To achieve this, we create a fake opam package that has our build-dependencies as
@# dependencies, but does not actually install anything itself.
@echo "# Installing builddep packages."
@opam install $(OPAMFLAGS) $(BUILDDEPFILES)
.PHONY: builddep
# Backwards compatibility target
build-dep: builddep
.PHONY: build-dep
# Some files that do *not* need to be forwarded to Makefile.coq.
# ("::" lets Makefile.local overwrite this.)
Makefile Makefile.local _CoqProject $(OPAMFILES):: ;
# use NO_TEST=1 to skip the tests
NO_TEST:=
# use MAKE_REF=1 to generate new reference files
MAKE_REF:=
# Only test reference output on known versions of Coq, to avoid blocking
# Coq CI when they change the printing a little.
# Need to make this a lazy variable (`=` instead of `:=`) since COQ_VERSION is only set later.
COQ_REF=$(shell echo "$(COQ_VERSION)" | grep -E "^8\.(20)\." -q && echo 1)
# Run tests interleaved with main build. They have to be in the same target for this.
real-all: style $(if $(NO_TEST),,test)
style: $(VFILES) coq-lint.sh
# Make sure everything imports the options, and some general linting.
$(SHOW)"COQLINT"
$(HIDE)for FILE in $(VFILES); do \
if ! grep -F -q 'From iris.prelude Require Import options.' "$$FILE"; then echo "ERROR: $$FILE does not import 'options'."; echo; exit 1; fi ; \
./coq-lint.sh "$$FILE" || exit 1; \
done
# Make sure main Iris does not import other Iris packages.
$(HIDE)if grep -E 'iris\.(heap_lang|deprecated|unstable)' --include "*.v" -R iris; then echo "ERROR: Iris may not import modules from other Iris packages (see above for violations)."; echo; exit 1; fi
.PHONY: style
# the test suite
TESTFILES:=$(shell find tests -name "*.v")
NORMALIZER:=test-normalizer.sed
test: $(TESTFILES:.v=.vo)
.PHONY: test
COQ_TEST=$(COQTOP) $(COQDEBUG) -batch -test-mode
tests/.coqdeps.d: $(TESTFILES)
$(SHOW)'COQDEP TESTFILES'
$(HIDE)$(COQDEP) -dyndep var $(COQMF_COQLIBS_NOML) $^ $(redir_if_ok)
-include tests/.coqdeps.d
# Main test script (comments out-of-line because macOS otherwise barfs?!?)
# - Determine reference file (`REF`).
# - Print user-visible status line.
# - unset env vars that change Coq's output
# - Dump Coq output into a temporary file.
# - Run `sed -i` on that file in a way that works on macOS.
# - Either compare the result with the reference file, or move it over the reference file.
# - Cleanup, and mark as done for make.
$(TESTFILES:.v=.vo): %.vo: %.v $(if $(MAKE_REF),,%.ref) $(NORMALIZER)
$(HIDE)REF=$*".ref" && \
echo "COQTEST$(if $(COQ_REF),$(if $(MAKE_REF), [make ref],), [ref ignored]) $< (ref: $$REF)" && \
TMPFILE="$$(mktemp)" && \
unset OCAMLRUNPARAM && \
$(TIMER) $(COQ_TEST) $(COQFLAGS) $(COQLIBS) -load-vernac-source $< > "$$TMPFILE" && \
sed -E -f $(NORMALIZER) "$$TMPFILE" > "$$TMPFILE".new && \
mv "$$TMPFILE".new "$$TMPFILE" && \
$(if $(COQ_REF),\
$(if $(MAKE_REF),mv "$$TMPFILE" "$$REF",diff --strip-trailing-cr -u "$$REF" "$$TMPFILE"), \
true \
) && \
rm -f "$$TMPFILE" && \
touch $@
Tactic overview
===============
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](proofmode/classes.v). Most notable, many
of the tactics can be applied when the to be introduced or to be eliminated
connective appears under a later, an update modality, or in the conclusion of a
weakest precondition.
Applying hypotheses and lemmas
------------------------------
- `iExact "H"` : finish the goal if the conclusion matches the hypothesis `H`
- `iAssumption` : finish the goal if the conclusion matches any hypothesis
- `iApply pm_trm` : match the conclusion of the current goal against the
conclusion of `pm_trm` and generates goals for the premises of `pm_trm`. See
proof mode terms below.
Context management
------------------
- `iIntros (x1 ... xn) "ipat1 ... ipatn"` : introduce universal quantifiers
using Coq introduction patterns `x1 ... xn` and implications/wands using proof
mode introduction patterns `ipat1 ... ipatn`.
- `iClear (x1 ... xn) "selpat"` : clear the hypotheses given by the selection
pattern `selpat` and the Coq level hypotheses/variables `x1 ... xn`.
- `iRevert (x1 ... xn) "selpat"` : revert the hypotheses given by the selection
pattern `selpat` into wands, and the Coq level hypotheses/variables
`x1 ... xn` into universal quantifiers. Persistent hypotheses are wrapped into
the always modality.
- `iRename "H1" into "H2"` : rename the hypothesis `H1` into `H2`.
- `iSpecialize pm_trm` : instantiate universal quantifiers and eliminate
implications/wands of a hypothesis `pm_trm`. See proof mode terms below.
- `iSpecialize pm_trm as #` : instantiate universal quantifiers and eliminate
implications/wands of a hypothesis whose conclusion is persistent. In this
case, all hypotheses can be used for proving the premises, as well as for
the resulting goal.
- `iPoseProof pm_trm as "H"` : put `pm_trm` into the context as a new hypothesis
`H`.
- `iAssert P with "spat" as "ipat"` : create a new goal with conclusion `P` and
put `P` in the context of the original goal. The specialization pattern
`spat` specifies which hypotheses will be consumed by proving `P`. The
introduction pattern `ipat` specifies how to eliminate `P`.
- `iAssert P with "spat" as %cpat` : assert `P` and eliminate it using the Coq
introduction pattern `cpat`.
Introduction of logical connectives
-----------------------------------
- `iPureIntro` : turn a pure goal into a Coq goal. This tactic works for goals
of the shape `■ φ`, `a ≡ b` on discrete COFEs, and `✓ a` on discrete CMRAs.
- `iLeft` : left introduction of disjunction.
- `iRight` : right introduction of disjunction.
- `iSplit` : introduction of a conjunction, or separating conjunction provided
one of the operands is persistent.
- `iSplitL "H1 ... Hn"` : introduction of a separating conjunction. The
hypotheses `H1 ... Hn` are used for the left conjunct, and the remaining ones
for the right conjunct. Persistent hypotheses are ignored, since these do not
need to be split.
- `iSplitR "H0 ... Hn"` : symmetric version of the above.
- `iExist t1, .., tn` : introduction of an existential quantifier.
Elimination of logical connectives
----------------------------------
- `iExFalso` : Ex falso sequitur quod libet.
- `iDestruct pm_trm as (x1 ... xn) "ipat"` : elimination of existential
quantifiers using Coq introduction patterns `x1 ... xn` and elimination of
object level connectives using the proof mode introduction pattern `ipat`.
In case all branches of `ipat` start with an `#` (moving the hypothesis to the
persistent context) or `%` (moving the hypothesis to the pure Coq context),
one can use all hypotheses for proving the premises of `pm_trm`, as well as
for proving the resulting goal.
- `iDestruct pm_trm as %cpat` : elimination of a pure hypothesis using the Coq
introduction pattern `cpat`. When using this tactic, all hypotheses can be
used for proving the premises of `pm_trm`, as well as for proving the
resulting goal.
Separating logic specific tactics
---------------------------------
- `iFrame (t1 .. tn) "selpat"` : cancel the Coq terms (or Coq hypotheses)
`t1 ... tn` and Iris hypotheses given by `selpat` 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 persistent context.
+ `★` : frame as much of the spatial context as possible.
Notice that framing spatial hypotheses makes them disappear, but framing Coq
or persistent hypotheses does not make them disappear.
This tactic finishes the goal in case everything in the conclusion has been
framed.
- `iCombine "H1" "H2" as "H"` : turns `H1 : P1` and `H2 : P2` into
`H : P1 ★ P2`.
Modalities
----------
- `iModIntro` : introduction of a modality that is an instance of the
`IntoModal` type class. Instances include: later, except 0, basic update and
fancy update.
- `iMod pm_trm as (x1 ... xn) "ipat"` : eliminate a modality `pm_trm` that is
an instance of the `ElimModal` type class. Instances include: later, except 0,
basic update and fancy update.
The later modality
------------------
- `iNext` : introduce a later by stripping laters from all hypotheses.
- `iLöb as "IH" forall (x1 ... xn)` : perform Löb induction by generating a
hypothesis `IH : ▷ goal`. The tactic generalizes over the Coq level variables
`x1 ... xn`, the hypotheses given by the selection pattern `selpat`, and the
spatial context.
Induction
---------
- `iInduction x as cpat "IH" forall (x1 ... xn) "selpat"` : perform induction on
the Coq term `x`. The Coq introduction pattern is used to name the introduced
variables. The induction hypotheses are inserted into the persistent context
and given fresh names prefixed `IH`. The tactic generalizes over the Coq level
variables `x1 ... xn`, the hypotheses given by the selection pattern `selpat`,
and the spatial context.
Rewriting
---------
- `iRewrite pm_trm` : rewrite an equality in the conclusion.
- `iRewrite pm_trm in "H"` : rewrite an equality in the hypothesis `H`.
Iris
----
- `iInv N as (x1 ... xn) "ipat" "Hclose"` : open the invariant `N`, the update
for closing the invariant is put in a hypothesis named `Hclose`.
Miscellaneous
-------------
- The tactic `done` is extended so that it also performs `iAssumption` and
introduces pure connectives.
- The proof mode adds hints to the core `eauto` database so that `eauto`
automatically introduces: conjunctions and disjunctions, universal and
existential quantifiers, implications and wand, always, later and update
modalities, and pure connectives.
Selection patterns
==================
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 named `H`.
- `%` : select the entire pure/Coq context.
- `#` : select the entire persistent context.
- `★` : select the entire spatial context.
Introduction patterns
=====================
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 named `H`.
- `?` : create an anonymous hypothesis.
- `_` : remove the hypothesis.
- `$` : frame the hypothesis in the goal.
- `[ipat ipat]` : (separating) conjunction elimination.
- `[ipat|ipat]` : disjunction elimination.
- `[]` : false elimination.
- `%` : move the hypothesis to the pure Coq context (anonymously).
- `# ipat` : move the hypothesis to the persistent context.
- `> ipat` : eliminate a modality (if the goal permits).
Apart from this, there are the following introduction patterns that can only
appear at the top level:
- `{H1 ... Hn}` : clear `H1 ... Hn`.
- `{$H1 ... $Hn}` : frame `H1 ... Hn` (this pattern can be mixed with the
previous pattern, e.g., `{$H1 H2 $H3}`).
- `!%` : introduce a pure goal (and leave the proof mode).
- `!#` : introduce an always modality (given that the spatial context is empty).
- `!>` : introduce a modality.
- `/=` : perform `simpl`.
- `*` : introduce all universal quantifiers.
- `**` : introduce all universal quantifiers, as well as all arrows and wands.
For example, given:
∀ x, x = 0 ⊢ □ (P → False ∨ □ (Q ∧ ▷ R) -★ P ★ ▷ (R ★ Q ∧ x = pred 2)).
You can write
iIntros (x) "% !# $ [[] | #[HQ HR]] /= !>".
which results in:
x : nat
H : x = 0
______________________________________(1/1)
"HQ" : Q
"HR" : R
--------------------------------------□
R ★ Q ∧ x = 1
Specialization patterns
=======================
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
_specification patterns_ to express splitting of hypotheses:
- `H` : use the hypothesis `H` (it should match the premise exactly). If `H` is
spatial, it will be consumed.
- `[H1 ... Hn]` : generate a goal with the (spatial) hypotheses `H1 ... Hn` and
all persistent hypotheses. The spatial hypotheses among `H1 ... Hn` will be
consumed. Hypotheses may be prefixed with a `$`, which results in them being
framed in the generated goal.
- `[-H1 ... Hn]` : negated form of the above pattern. This pattern does not
accept hypotheses prefixed with a `$`.
- `>[H1 ... Hn]` : same as the above pattern, but can only be used if the goal
is a modality, in which case the modality will be kept in the generated goal
for the premise will be wrapped into the modality.
- `[#]` : This pattern can be used when eliminating `P -★ Q` with `P`
persistent. Using this pattern, all hypotheses are available in the goal for
`P`, as well the remaining goal.
- `[%]` : This pattern can be used when eliminating `P -★ Q` when `P` is pure.
It will generate a Coq goal for `P` and does not consume any hypotheses.
- `*` : instantiate all top-level universal quantifiers with meta variables.
For example, given:
H : □ P -★ P 2 -★ x = 0 -★ Q1 ∗ Q2
You can write:
iDestruct ("H" with "[#] [H1 H2] [%]") as "[H4 H5]".
Proof mode terms
================
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 both a hypothesis, as well as 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 short hands too:
(H with "spat1 .. spatn")
(H $! t1 ... tn)
H
# IRIS COQ DEVELOPMENT
# Iris Coq Development [[coqdoc]](https://plv.mpi-sws.org/coqdoc/iris/)
This is the Coq development of the [Iris Project](http://plv.mpi-sws.org/iris/).
This is the Coq development of the [Iris Project](http://iris-project.org),
which includes [MoSeL](http://iris-project.org/mosel/), a general proof mode
for carrying out separation logic proofs in Coq.
## Prerequisites
For using the Coq library, check out the
[API documentation](https://plv.mpi-sws.org/coqdoc/iris/).
For understanding the theory of Iris, a LaTeX version of the core logic
definitions and some derived forms is available in
[tex/iris.tex](tex/iris.tex). A compiled PDF version of this document is
[available online](http://plv.mpi-sws.org/iris/appendix-3.4.pdf).
## Side-effects
Importing Iris has some side effects as the library sets some global options.
* First of all, Iris imports std++, so the
[std++ side-effects](https://gitlab.mpi-sws.org/iris/stdpp/#side-effects)
apply.
* On top of that, Iris imports ssreflect, which replaces the default `rewrite`
tactic with the ssreflect version. However, `done` is overwritten to keep
using the std++ version of the tactic. We also set `SsrOldRewriteGoalsOrder`
and re-open `general_if_scope` to un-do some effects of ssreflect.
## Building Iris
### Prerequisites
This version is known to compile with:
- Coq 8.5pl2
- Ssreflect 1.6
For development, better make sure you have a version of Ssreflect that includes
commit be724937 (no such version has been released so far, you will have to
fetch the development branch yourself). Iris compiles fine even without this
patch, but proof bullets will only be in 'strict' (enforcing) mode with the
fixed version of Ssreflect.
## Building Instructions
Run the following command to build the full development:
make
The development can then be installed as the Coq user contribution `iris` by
running:
make install
## Structure
* The folder [prelude](prelude) contains an extended "Standard Library" by
Robbert Krebbers <http://robbertkrebbers.nl/thesis.html>.
* The folder [algebra](algebra) contains the COFE and CMRA constructions as well
as the solver for recursive domain equations.
* The folder [base_logic](base_logic) defines the Iris base logic and the
primitive connectives. It also contains derived constructions that are
entirely independent of the choice of resources.
* The folder [program_logic](program_logic) specializes the base logic to build
Iris, the program logic. Most crucially, this includes world satisfaction
and weakest preconditions. Furthermore, some language-independent derived
constructions (e.g., STSs) are defined in this folder.
* The folder [heap_lang](heap_lang) defines the ML-like concurrent heap language
* The subfolder [lib](heap_lang/lib) contains a few derived constructions
within this language, e.g., parallel composition.
Most notable here s [lib/barrier](heap_lang/lib/barrier), the implementation
and proof of a barrier as described in <http://doi.acm.org/10.1145/2818638>.
* The folder [proofmode](proofmode) contains the Iris proof mode, which extends
Coq with contexts for persistent and spatial Iris assertions. It also contains
tactics for interactive proofs in Iris. Documentation can be found in
[ProofMode.md](ProofMode.md).
* The folder [tests](tests) contains modules we use to test our infrastructure.
Users of the Iris Coq library should *not* depend on these modules; they may
change or disappear without any notice.
## Documentation
A LaTeX version of the core logic definitions and some derived forms is
available in [docs/iris.tex](docs/iris.tex). A compiled PDF version of this
document is [http://plv.mpi-sws.org/iris/appendix-3.0.pdf](available online).
- Coq 8.19.2 / 8.20.1
- A development version of [std++](https://gitlab.mpi-sws.org/iris/stdpp)
Generally we always aim to support the last two stable Coq releases. Support for
older versions will be dropped when it is convenient.
If you need to work with older versions of Coq, you can check out the
[tags](https://gitlab.mpi-sws.org/iris/iris/-/tags) for old Iris releases that
still support them.
### Working *with* Iris
To use Iris in your own proofs, we recommend you install Iris via opam (2.0.0 or
newer). To obtain the latest stable release, you have to add the Coq opam
repository:
opam repo add coq-released https://coq.inria.fr/opam/released
To obtain a development version, also add the Iris opam repository:
opam repo add iris-dev https://gitlab.mpi-sws.org/iris/opam.git
Either way, you can now install Iris:
- `opam install coq-iris` will install the libraries making up the Iris logic,
but leave it up to you to instantiate the `program_logic.language` interface
to define a programming language for Iris to reason about.
- `opam install coq-iris-heap-lang` will additionally install HeapLang, the
default language used by various Iris projects.
To fetch updates later, run `opam update && opam upgrade`.
#### Be notified of breaking changes
We do not guarantee backwards-compatibility, so upgrading Iris may break your
Iris-using developments. If you want to be notified of breaking changes, please
let us know your account name on the
[MPI-SWS GitLab](https://gitlab.mpi-sws.org/) so we can add you to the
notification group. Note that this excludes the "unstable" and "deprecated"
packages (see below).
#### Use of Iris in submitted artifacts
If you are using Iris as part of an artifact submitted for publication with a
paper, we recommend you make the artifact self-contained so that it can be built
in the future without relying in any other server to still exist. However, if
that is for some reason not possible, and if you are using opam to obtain the
right version of Iris and you used a `dev.*` version, please let us know which
exact Iris version you artifact relies on so that we can
[add it to this wiki page](https://gitlab.mpi-sws.org/iris/iris/-/wikis/Pinned-Iris-package-versions)
and avoid removing it from our opam repository in the future.
### Working *on* Iris
See the [contribution guide](CONTRIBUTING.md) for information on how to work on
the Iris development itself.
## Directory Structure
Iris is structured into multiple *packages*, some of which contain multiple
modules in separate folders.
* The [iris](iris) package contains the language-independent parts of Iris.
+ The folder [prelude](iris/prelude) contains modules imported everywhere in
Iris.
+ The folder [algebra](iris/algebra) contains the COFE and CMRA
constructions as well as the solver for recursive domain equations.
- The subfolder [lib](iris/algebra/lib) contains some general derived RA
constructions.
+ The folder [bi](iris/bi) contains the BI++ laws, as well as derived
connectives, laws and constructions that are applicable for general BIs.
- The subfolder [lib](iris/bi/lib) contains some general derived logical
constructions.
+ The folder [proofmode](iris/proofmode) contains
[MoSeL](http://iris-project.org/mosel/), which extends Coq with contexts for
intuitionistic and spatial BI++ assertions. It also contains tactics for
interactive proofs. Documentation can be found in
[proof_mode.md](docs/proof_mode.md).
+ The folder [base_logic](iris/base_logic) defines the Iris base logic and
the primitive connectives. It also contains derived constructions that are
entirely independent of the choice of resources.
- The subfolder [lib](iris/base_logic/lib) contains some generally useful
derived constructions. Most importantly, it defines composable
dynamic resources and ownership of them; the other constructions depend
on this setup.
+ The folder [program_logic](iris/program_logic) specializes the base logic
to build Iris, the program logic. This includes weakest preconditions that
are defined for any language satisfying some generic axioms, and some derived
constructions that work for any such language.
+ The folder [si_logic](iris/si_logic) defines a "plain" step-indexed logic
and shows that it is an instance of the BI interface.
* The [iris_heap_lang](iris_heap_lang) package defines the ML-like concurrent
language HeapLang and provides tactic support and proof mode integration.
+ The subfolder [lib](iris_heap_lang/lib) contains a few derived
constructions within this language, e.g., parallel composition.
For more examples of using Iris and heap_lang, have a look at the
[Iris Examples](https://gitlab.mpi-sws.org/iris/examples).
* The [iris_unstable](iris_unstable) package contains libraries that are not yet
ready for inclusion in Iris proper. For each library, there is a corresponding
"tracking issue" in the Iris issue tracker (also linked from the library
itself) which tracks the work that still needs to be done before moving the
library to Iris. No stability guarantees whatsoever are made for this package.
* The [iris_deprecated](iris_deprecated) package contains libraries that have been
removed from Iris proper, but are kept around to give users some more time to
switch to their intended replacements. The individual libraries come with comments
explaining the deprecation and making recommendations for what to use
instead. No stability guarantees whatsoever are made for this package.
* The folder [tests](tests) contains modules we use to test our
infrastructure. These modules are not installed by `make install`, and should
not be imported.
Note that the unstable and deprecated packages are not released, so they only
exist in the development version of Iris.
## Case Studies
The following is a (probably incomplete) list of case studies that use Iris, and
that should be compatible with this version:
* [Iris Examples](https://gitlab.mpi-sws.org/iris/examples) is where we
collect miscellaneous case studies that do not have their own repository.
* [LambdaRust](https://gitlab.mpi-sws.org/iris/lambda-rust) is a Coq
formalization of the core Rust type system.
* [GPFSL](https://gitlab.mpi-sws.org/iris/gpfsl) is a logic for release-acquire
and relaxed memory.
* [Iron](https://gitlab.mpi-sws.org/iris/iron) is a linear separation logic
built on top of Iris for precise reasoning about resources (such as making
sure there are no memory leaks).
* [Actris](https://gitlab.mpi-sws.org/iris/actris) is a separation logic
built on top of Iris for session-type based reasoning of message-passing
programs.
## Further Resources
Getting along with Iris in Coq:
* The coding style is documented in the [style guide](docs/style_guide.md).
* Iris proof patterns and conventions are documented in the
[proof guide](docs/proof_guide.md).
* Various notions of equality and logical entailment in Iris and their Coq
interface are described in the
[equality docs](docs/equalities_and_entailments.md).
* The Iris tactics are described in the
[the Iris Proof Mode (IPM) / MoSeL documentation](docs/proof_mode.md) as well as the
[HeapLang documentation](docs/heap_lang.md).
* The generated coqdoc is [available online](https://plv.mpi-sws.org/coqdoc/iris/).
Contacting the developers:
* Discussion about the Iris Coq development happens in the [Iris
Chat](https://iris-project.org/chat.html). This is also the right place to ask
questions.
* If you want to report a bug, please use the
[issue tracker](https://gitlab.mpi-sws.org/iris/iris/issues), which requires
an MPI-SWS GitLab account. The [chat page](https://iris-project.org/chat.html)
describes how to create such an account.
* To contribute to Iris itself, see the [contribution guide](CONTRIBUTING.md).
Miscellaneous:
* Information on how to set up your editor for unicode input and output is
collected in [editor.md](docs/editor.md).
* If you are writing a paper that uses Iris in one way or another, you could use
the [Iris LaTeX macros](tex/iris.sty) for typesetting the various Iris
connectives.
-Q . iris
prelude/option.v
prelude/fin_map_dom.v
prelude/bset.v
prelude/fin_maps.v
prelude/vector.v
prelude/pmap.v
prelude/stringmap.v
prelude/fin_collections.v
prelude/mapset.v
prelude/proof_irrel.v
prelude/hashset.v
prelude/pretty.v
prelude/countable.v
prelude/orders.v
prelude/natmap.v
prelude/strings.v
prelude/relations.v
prelude/collections.v
prelude/listset.v
prelude/streams.v
prelude/gmap.v
prelude/base.v
prelude/tactics.v
prelude/prelude.v
prelude/listset_nodup.v
prelude/finite.v
prelude/numbers.v
prelude/nmap.v
prelude/zmap.v
prelude/coPset.v
prelude/lexico.v
prelude/set.v
prelude/decidable.v
prelude/list.v
prelude/error.v
prelude/functions.v
prelude/hlist.v
prelude/sorting.v
algebra/cmra.v
algebra/cmra_big_op.v
algebra/cmra_tactics.v
algebra/sts.v
algebra/auth.v
algebra/gmap.v
algebra/cofe.v
algebra/base.v
algebra/dra.v
algebra/cofe_solver.v
algebra/agree.v
algebra/dec_agree.v
algebra/excl.v
algebra/iprod.v
algebra/frac.v
algebra/csum.v
algebra/list.v
algebra/updates.v
algebra/local_updates.v
algebra/gset.v
algebra/coPset.v
base_logic/upred.v
base_logic/primitive.v
base_logic/derived.v
base_logic/base_logic.v
base_logic/tactics.v
base_logic/big_op.v
base_logic/hlist.v
base_logic/soundness.v
base_logic/double_negation.v
program_logic/iprop.v
program_logic/adequacy.v
program_logic/lifting.v
program_logic/invariants.v
program_logic/wsat.v
program_logic/weakestpre.v
program_logic/fancy_updates.v
program_logic/hoare.v
program_logic/viewshifts.v
program_logic/language.v
program_logic/ectx_language.v
program_logic/ectxi_language.v
program_logic/ectx_lifting.v
program_logic/own.v
program_logic/saved_prop.v
program_logic/auth.v
program_logic/sts.v
program_logic/namespaces.v
program_logic/boxes.v
program_logic/counter_examples.v
program_logic/iris.v
program_logic/thread_local.v
program_logic/cancelable_invariants.v
heap_lang/lang.v
heap_lang/tactics.v
heap_lang/wp_tactics.v
heap_lang/lifting.v
heap_lang/derived.v
heap_lang/notation.v
heap_lang/heap.v
heap_lang/lib/spawn.v
heap_lang/lib/par.v
heap_lang/lib/assert.v
heap_lang/lib/lock.v
heap_lang/lib/spin_lock.v
heap_lang/lib/ticket_lock.v
heap_lang/lib/counter.v
heap_lang/lib/barrier/barrier.v
heap_lang/lib/barrier/specification.v
heap_lang/lib/barrier/protocol.v
heap_lang/lib/barrier/proof.v
heap_lang/proofmode.v
heap_lang/adequacy.v
tests/atomic.v
tests/heap_lang.v
tests/one_shot.v
tests/joining_existentials.v
tests/proofmode.v
tests/barrier_client.v
tests/list_reverse.v
tests/tree_sum.v
tests/counter.v
proofmode/coq_tactics.v
proofmode/environments.v
proofmode/intro_patterns.v
proofmode/spec_patterns.v
proofmode/sel_patterns.v
proofmode/tactics.v
proofmode/notation.v
proofmode/classes.v
proofmode/class_instances.v
# Search paths for all packages. They must all match the regex
# `-Q $PACKAGE[/ ]` so that we can filter out the right ones for each package.
-Q iris/prelude iris.prelude
-Q iris/algebra iris.algebra
-Q iris/si_logic iris.si_logic
-Q iris/bi iris.bi
-Q iris/proofmode iris.proofmode
-Q iris/base_logic iris.base_logic
-Q iris/program_logic iris.program_logic
-Q iris_heap_lang iris.heap_lang
-Q iris_unstable iris.unstable
-Q iris_deprecated iris.deprecated
# Custom flags (to be kept in sync with the dune file at the root of the repo).
# We sometimes want to locally override notation, and there is no good way to do that with scopes.
-arg -w -arg -notation-overridden
# Cannot use non-canonical projections as it causes massive unification failures
# (https://github.com/coq/coq/issues/6294).
-arg -w -arg -redundant-canonical-projection
# Warning seems incorrect, see https://gitlab.mpi-sws.org/iris/stdpp/-/issues/216
-arg -w -arg -notation-incompatible-prefix
# We can't do this migration yet until we require Coq 9.0
-arg -w -arg -deprecated-from-Coq
-arg -w -arg -deprecated-dirpath-Coq
iris/prelude/options.v
iris/prelude/prelude.v
iris/algebra/stepindex.v
iris/algebra/stepindex_finite.v
iris/algebra/monoid.v
iris/algebra/cmra.v
iris/algebra/big_op.v
iris/algebra/cmra_big_op.v
iris/algebra/sts.v
iris/algebra/numbers.v
iris/algebra/view.v
iris/algebra/auth.v
iris/algebra/gmap.v
iris/algebra/ofe.v
iris/algebra/cofe_solver.v
iris/algebra/agree.v
iris/algebra/excl.v
iris/algebra/functions.v
iris/algebra/frac.v
iris/algebra/dfrac.v
iris/algebra/csum.v
iris/algebra/list.v
iris/algebra/vector.v
iris/algebra/updates.v
iris/algebra/local_updates.v
iris/algebra/gset.v
iris/algebra/gmultiset.v
iris/algebra/coPset.v
iris/algebra/proofmode_classes.v
iris/algebra/ufrac.v
iris/algebra/reservation_map.v
iris/algebra/dyn_reservation_map.v
iris/algebra/max_prefix_list.v
iris/algebra/mra.v
iris/algebra/lib/excl_auth.v
iris/algebra/lib/frac_auth.v
iris/algebra/lib/ufrac_auth.v
iris/algebra/lib/dfrac_agree.v
iris/algebra/lib/gmap_view.v
iris/algebra/lib/mono_nat.v
iris/algebra/lib/mono_Z.v
iris/algebra/lib/mono_list.v
iris/algebra/lib/gset_bij.v
iris/si_logic/siprop.v
iris/si_logic/bi.v
iris/bi/notation.v
iris/bi/interface.v
iris/bi/derived_connectives.v
iris/bi/extensions.v
iris/bi/derived_laws.v
iris/bi/derived_laws_later.v
iris/bi/plainly.v
iris/bi/internal_eq.v
iris/bi/big_op.v
iris/bi/updates.v
iris/bi/ascii.v
iris/bi/bi.v
iris/bi/monpred.v
iris/bi/embedding.v
iris/bi/weakestpre.v
iris/bi/telescopes.v
iris/bi/lib/cmra.v
iris/bi/lib/counterexamples.v
iris/bi/lib/fixpoint_mono.v
iris/bi/lib/fixpoint_banach.v
iris/bi/lib/fractional.v
iris/bi/lib/laterable.v
iris/bi/lib/atomic.v
iris/bi/lib/core.v
iris/bi/lib/relations.v
iris/base_logic/upred.v
iris/base_logic/bi.v
iris/base_logic/derived.v
iris/base_logic/proofmode.v
iris/base_logic/base_logic.v
iris/base_logic/algebra.v
iris/base_logic/bupd_alt.v
iris/base_logic/lib/iprop.v
iris/base_logic/lib/own.v
iris/base_logic/lib/saved_prop.v
iris/base_logic/lib/wsat.v
iris/base_logic/lib/invariants.v
iris/base_logic/lib/fancy_updates.v
iris/base_logic/lib/boxes.v
iris/base_logic/lib/na_invariants.v
iris/base_logic/lib/cancelable_invariants.v
iris/base_logic/lib/gen_heap.v
iris/base_logic/lib/gen_inv_heap.v
iris/base_logic/lib/fancy_updates_from_vs.v
iris/base_logic/lib/proph_map.v
iris/base_logic/lib/ghost_var.v
iris/base_logic/lib/mono_nat.v
iris/base_logic/lib/gset_bij.v
iris/base_logic/lib/ghost_map.v
iris/base_logic/lib/later_credits.v
iris/base_logic/lib/token.v
iris/program_logic/adequacy.v
iris/program_logic/lifting.v
iris/program_logic/weakestpre.v
iris/program_logic/total_weakestpre.v
iris/program_logic/total_adequacy.v
iris/program_logic/language.v
iris/program_logic/ectx_language.v
iris/program_logic/ectxi_language.v
iris/program_logic/ectx_lifting.v
iris/program_logic/ownp.v
iris/program_logic/total_lifting.v
iris/program_logic/total_ectx_lifting.v
iris/program_logic/atomic.v
iris/proofmode/base.v
iris/proofmode/ident_name.v
iris/proofmode/string_ident.v
iris/proofmode/tokens.v
iris/proofmode/coq_tactics.v
iris/proofmode/ltac_tactics.v
iris/proofmode/environments.v
iris/proofmode/reduction.v
iris/proofmode/intro_patterns.v
iris/proofmode/spec_patterns.v
iris/proofmode/sel_patterns.v
iris/proofmode/tactics.v
iris/proofmode/notation.v
iris/proofmode/classes.v
iris/proofmode/classes_make.v
iris/proofmode/class_instances.v
iris/proofmode/class_instances_later.v
iris/proofmode/class_instances_updates.v
iris/proofmode/class_instances_embedding.v
iris/proofmode/class_instances_plainly.v
iris/proofmode/class_instances_internal_eq.v
iris/proofmode/class_instances_frame.v
iris/proofmode/class_instances_make.v
iris/proofmode/monpred.v
iris/proofmode/modalities.v
iris/proofmode/modality_instances.v
iris/proofmode/proofmode.v
iris_heap_lang/locations.v
iris_heap_lang/lang.v
iris_heap_lang/class_instances.v
iris_heap_lang/pretty.v
iris_heap_lang/metatheory.v
iris_heap_lang/tactics.v
iris_heap_lang/primitive_laws.v
iris_heap_lang/derived_laws.v
iris_heap_lang/notation.v
iris_heap_lang/proofmode.v
iris_heap_lang/adequacy.v
iris_heap_lang/total_adequacy.v
iris_heap_lang/proph_erasure.v
iris_heap_lang/lib/spawn.v
iris_heap_lang/lib/par.v
iris_heap_lang/lib/assert.v
iris_heap_lang/lib/lock.v
iris_heap_lang/lib/rw_lock.v
iris_heap_lang/lib/spin_lock.v
iris_heap_lang/lib/ticket_lock.v
iris_heap_lang/lib/rw_spin_lock.v
iris_heap_lang/lib/nondet_bool.v
iris_heap_lang/lib/lazy_coin.v
iris_heap_lang/lib/clairvoyant_coin.v
iris_heap_lang/lib/counter.v
iris_heap_lang/lib/atomic_heap.v
iris_heap_lang/lib/increment.v
iris_heap_lang/lib/diverge.v
iris_heap_lang/lib/arith.v
iris_heap_lang/lib/array.v
iris_heap_lang/lib/logatom_lock.v
iris_unstable/algebra/list.v
iris_unstable/base_logic/algebra.v
iris_unstable/base_logic/mono_list.v
iris_unstable/heap_lang/interpreter.v
iris_deprecated/base_logic/auth.v
iris_deprecated/base_logic/sts.v
iris_deprecated/base_logic/viewshifts.v
iris_deprecated/program_logic/hoare.v
From iris.algebra Require Export cmra.
From iris.base_logic Require Import base_logic.
Local Hint Extern 10 (_ _) => omega.
Record agree (A : Type) : Type := Agree {
agree_car : nat A;
agree_is_valid : nat Prop;
agree_valid_S n : agree_is_valid (S n) agree_is_valid n
}.
Arguments Agree {_} _ _ _.
Arguments agree_car {_} _ _.
Arguments agree_is_valid {_} _ _.
Section agree.
Context {A : cofeT}.
Instance agree_validN : ValidN (agree A) := λ n x,
agree_is_valid x n n', n' n agree_car x n {n'} agree_car x n'.
Instance agree_valid : Valid (agree A) := λ x, n, {n} x.
Lemma agree_valid_le n n' (x : agree A) :
agree_is_valid x n n' n agree_is_valid x n'.
Proof. induction 2; eauto using agree_valid_S. Qed.
Instance agree_equiv : Equiv (agree A) := λ x y,
( n, agree_is_valid x n agree_is_valid y n)
( n, agree_is_valid x n agree_car x n {n} agree_car y n).
Instance agree_dist : Dist (agree A) := λ n x y,
( n', n' n agree_is_valid x n' agree_is_valid y n')
( n', n' n agree_is_valid x n' agree_car x n' {n'} agree_car y n').
Program Instance agree_compl : Compl (agree A) := λ c,
{| agree_car n := agree_car (c n) n;
agree_is_valid n := agree_is_valid (c n) n |}.
Next Obligation.
intros c n ?. apply (chain_cauchy c n (S n)), agree_valid_S; auto.
Qed.
Definition agree_cofe_mixin : CofeMixin (agree A).
Proof.
split.
- intros x y; split.
+ by intros Hxy n; split; intros; apply Hxy.
+ by intros Hxy; split; intros; apply Hxy with n.
- split.
+ by split.
+ by intros x y Hxy; split; intros; symmetry; apply Hxy; auto; apply Hxy.
+ intros x y z Hxy Hyz; split; intros n'; intros.
* trans (agree_is_valid y n'). by apply Hxy. by apply Hyz.
* trans (agree_car y n'). by apply Hxy. by apply Hyz, Hxy.
- intros n x y Hxy; split; intros; apply Hxy; auto.
- intros n c; apply and_wlog_r; intros;
symmetry; apply (chain_cauchy c); naive_solver.
Qed.
Canonical Structure agreeC := CofeT (agree A) agree_cofe_mixin.
Program Instance agree_op : Op (agree A) := λ x y,
{| agree_car := agree_car x;
agree_is_valid n := agree_is_valid x n agree_is_valid y n x {n} y |}.
Next Obligation. naive_solver eauto using agree_valid_S, dist_S. Qed.
Instance agree_pcore : PCore (agree A) := Some.
Instance: Comm () (@op (agree A) _).
Proof. intros x y; split; [naive_solver|by intros n (?&?&Hxy); apply Hxy]. Qed.
Lemma agree_idemp (x : agree A) : x x x.
Proof. split; naive_solver. Qed.
Instance: n : nat, Proper (dist n ==> impl) (@validN (agree A) _ n).
Proof.
intros n x y Hxy [? Hx]; split; [by apply Hxy|intros n' ?].
rewrite -(proj2 Hxy n') -1?(Hx n'); eauto using agree_valid_le.
symmetry. by apply dist_le with n; try apply Hxy.
Qed.
Instance: x : agree A, Proper (dist n ==> dist n) (op x).
Proof.
intros n x y1 y2 [Hy' Hy]; split; [|done].
split; intros (?&?&Hxy); repeat (intro || split);
try apply Hy'; eauto using agree_valid_le.
- etrans; [apply Hxy|apply Hy]; eauto using agree_valid_le.
- etrans; [apply Hxy|symmetry; apply Hy, Hy'];
eauto using agree_valid_le.
Qed.
Instance: Proper (dist n ==> dist n ==> dist n) (@op (agree A) _).
Proof. by intros n x1 x2 Hx y1 y2 Hy; rewrite Hy !(comm _ _ y2) Hx. Qed.
Instance: Proper (() ==> () ==> ()) op := ne_proper_2 _.
Instance: Assoc () (@op (agree A) _).
Proof.
intros x y z; split; simpl; intuition;
repeat match goal with H : agree_is_valid _ _ |- _ => clear H end;
by cofe_subst; rewrite !agree_idemp.
Qed.
Lemma agree_included (x y : agree A) : x y y x y.
Proof.
split; [|by intros ?; exists y].
by intros [z Hz]; rewrite Hz assoc agree_idemp.
Qed.
Lemma agree_op_inv n (x1 x2 : agree A) : {n} (x1 x2) x1 {n} x2.
Proof. intros Hxy; apply Hxy. Qed.
Lemma agree_valid_includedN n (x y : agree A) : {n} y x {n} y x {n} y.
Proof.
move=> Hval [z Hy]; move: Hval; rewrite Hy.
by move=> /agree_op_inv->; rewrite agree_idemp.
Qed.
Definition agree_cmra_mixin : CMRAMixin (agree A).
Proof.
apply cmra_total_mixin; try apply _ || by eauto.
- intros n x [? Hx]; split; [by apply agree_valid_S|intros n' ?].
rewrite -(Hx n'); last auto.
symmetry; apply dist_le with n; try apply Hx; auto.
- intros x. apply agree_idemp.
- by intros n x y [(?&?&?) ?].
- intros n x y1 y2 Hval Hx; exists x, x; simpl; split.
+ by rewrite agree_idemp.
+ by move: Hval; rewrite Hx; move=> /agree_op_inv->; rewrite agree_idemp.
Qed.
Canonical Structure agreeR : cmraT :=
CMRAT (agree A) agree_cofe_mixin agree_cmra_mixin.
Global Instance agree_total : CMRATotal agreeR.
Proof. rewrite /CMRATotal; eauto. Qed.
Global Instance agree_persistent (x : agree A) : Persistent x.
Proof. by constructor. Qed.
Program Definition to_agree (x : A) : agree A :=
{| agree_car n := x; agree_is_valid n := True |}.
Solve Obligations with done.
Global Instance to_agree_ne n : Proper (dist n ==> dist n) to_agree.
Proof. intros x1 x2 Hx; split; naive_solver eauto using @dist_le. Qed.
Global Instance to_agree_proper : Proper (() ==> ()) to_agree := ne_proper _.
Global Instance to_agree_inj n : Inj (dist n) (dist n) (to_agree).
Proof. by intros x y [_ Hxy]; apply Hxy. Qed.
Lemma to_agree_uninj n (x : agree A) : {n} x y : A, to_agree y {n} x.
Proof.
intros [??]. exists (agree_car x n).
split; naive_solver eauto using agree_valid_le.
Qed.
(** Internalized properties *)
Lemma agree_equivI {M} a b : to_agree a to_agree b ⊣⊢ (a b : uPred M).
Proof.
uPred.unseal. do 2 split. by intros [? Hv]; apply (Hv n). apply: to_agree_ne.
Qed.
Lemma agree_validI {M} x y : (x y) (x y : uPred M).
Proof. uPred.unseal; split=> r n _ ?; by apply: agree_op_inv. Qed.
End agree.
Arguments agreeC : clear implicits.
Arguments agreeR : clear implicits.
Program Definition agree_map {A B} (f : A B) (x : agree A) : agree B :=
{| agree_car n := f (agree_car x n); agree_is_valid := agree_is_valid x;
agree_valid_S := agree_valid_S _ x |}.
Lemma agree_map_id {A} (x : agree A) : agree_map id x = x.
Proof. by destruct x. Qed.
Lemma agree_map_compose {A B C} (f : A B) (g : B C) (x : agree A) :
agree_map (g f) x = agree_map g (agree_map f x).
Proof. done. Qed.
Section agree_map.
Context {A B : cofeT} (f : A B) `{Hf: n, Proper (dist n ==> dist n) f}.
Instance agree_map_ne n : Proper (dist n ==> dist n) (agree_map f).
Proof. by intros x1 x2 Hx; split; simpl; intros; [apply Hx|apply Hf, Hx]. Qed.
Instance agree_map_proper : Proper (() ==> ()) (agree_map f) := ne_proper _.
Lemma agree_map_ext (g : A B) x :
( x, f x g x) agree_map f x agree_map g x.
Proof. by intros Hfg; split; simpl; intros; rewrite ?Hfg. Qed.
Global Instance agree_map_monotone : CMRAMonotone (agree_map f).
Proof.
split; first apply _.
- by intros n x [? Hx]; split; simpl; [|by intros n' ?; rewrite Hx].
- intros x y; rewrite !agree_included=> ->.
split; last done; split; simpl; last tauto.
by intros (?&?&Hxy); repeat split; intros;
try apply Hxy; try apply Hf; eauto using @agree_valid_le.
Qed.
End agree_map.
Definition agreeC_map {A B} (f : A -n> B) : agreeC A -n> agreeC B :=
CofeMor (agree_map f : agreeC A agreeC B).
Instance agreeC_map_ne A B n : Proper (dist n ==> dist n) (@agreeC_map A B).
Proof.
intros f g Hfg x; split; simpl; intros; first done.
by apply dist_le with n; try apply Hfg.
Qed.
Program Definition agreeRF (F : cFunctor) : rFunctor := {|
rFunctor_car A B := agreeR (cFunctor_car F A B);
rFunctor_map A1 A2 B1 B2 fg := agreeC_map (cFunctor_map F fg)
|}.
Next Obligation.
intros ? A1 A2 B1 B2 n ???; simpl. by apply agreeC_map_ne, cFunctor_ne.
Qed.
Next Obligation.
intros F A B x; simpl. rewrite -{2}(agree_map_id x).
apply agree_map_ext=>y. by rewrite cFunctor_id.
Qed.
Next Obligation.
intros F A1 A2 A3 B1 B2 B3 f g f' g' x; simpl. rewrite -agree_map_compose.
apply agree_map_ext=>y; apply cFunctor_compose.
Qed.
Instance agreeRF_contractive F :
cFunctorContractive F rFunctorContractive (agreeRF F).
Proof.
intros ? A1 A2 B1 B2 n ???; simpl.
by apply agreeC_map_ne, cFunctor_contractive.
Qed.
From iris.algebra Require Export excl local_updates.
From iris.base_logic Require Import base_logic.
From iris.proofmode Require Import class_instances.
Local Arguments valid _ _ !_ /.
Local Arguments validN _ _ _ !_ /.
Record auth (A : Type) := Auth { authoritative : excl' A; auth_own : A }.
Add Printing Constructor auth.
Arguments Auth {_} _ _.
Arguments authoritative {_} _.
Arguments auth_own {_} _.
Notation "◯ a" := (Auth None a) (at level 20).
Notation "● a" := (Auth (Excl' a) ) (at level 20).
(* COFE *)
Section cofe.
Context {A : cofeT}.
Implicit Types a : excl' A.
Implicit Types b : A.
Implicit Types x y : auth A.
Instance auth_equiv : Equiv (auth A) := λ x y,
authoritative x authoritative y auth_own x auth_own y.
Instance auth_dist : Dist (auth A) := λ n x y,
authoritative x {n} authoritative y auth_own x {n} auth_own y.
Global Instance Auth_ne : Proper (dist n ==> dist n ==> dist n) (@Auth A).
Proof. by split. Qed.
Global Instance Auth_proper : Proper (() ==> () ==> ()) (@Auth A).
Proof. by split. Qed.
Global Instance authoritative_ne: Proper (dist n ==> dist n) (@authoritative A).
Proof. by destruct 1. Qed.
Global Instance authoritative_proper : Proper (() ==> ()) (@authoritative A).
Proof. by destruct 1. Qed.
Global Instance own_ne : Proper (dist n ==> dist n) (@auth_own A).
Proof. by destruct 1. Qed.
Global Instance own_proper : Proper (() ==> ()) (@auth_own A).
Proof. by destruct 1. Qed.
Instance auth_compl : Compl (auth A) := λ c,
Auth (compl (chain_map authoritative c)) (compl (chain_map auth_own c)).
Definition auth_cofe_mixin : CofeMixin (auth A).
Proof.
split.
- intros x y; unfold dist, auth_dist, equiv, auth_equiv.
rewrite !equiv_dist; naive_solver.
- intros n; split.
+ by intros ?; split.
+ by intros ?? [??]; split; symmetry.
+ intros ??? [??] [??]; split; etrans; eauto.
- by intros ? [??] [??] [??]; split; apply dist_S.
- intros n c; split. apply (conv_compl n (chain_map authoritative c)).
apply (conv_compl n (chain_map auth_own c)).
Qed.
Canonical Structure authC := CofeT (auth A) auth_cofe_mixin.
Global Instance Auth_timeless a b :
Timeless a Timeless b Timeless (Auth a b).
Proof. by intros ?? [??] [??]; split; apply: timeless. Qed.
Global Instance auth_discrete : Discrete A Discrete authC.
Proof. intros ? [??]; apply _. Qed.
Global Instance auth_leibniz : LeibnizEquiv A LeibnizEquiv (auth A).
Proof. by intros ? [??] [??] [??]; f_equal/=; apply leibniz_equiv. Qed.
End cofe.
Arguments authC : clear implicits.
(* CMRA *)
Section cmra.
Context {A : ucmraT}.
Implicit Types a b : A.
Implicit Types x y : auth A.
Instance auth_valid : Valid (auth A) := λ x,
match authoritative x with
| Excl' a => ( n, auth_own x {n} a) a
| None => auth_own x
| ExclBot' => False
end.
Global Arguments auth_valid !_ /.
Instance auth_validN : ValidN (auth A) := λ n x,
match authoritative x with
| Excl' a => auth_own x {n} a {n} a
| None => {n} auth_own x
| ExclBot' => False
end.
Global Arguments auth_validN _ !_ /.
Instance auth_pcore : PCore (auth A) := λ x,
Some (Auth (core (authoritative x)) (core (auth_own x))).
Instance auth_op : Op (auth A) := λ x y,
Auth (authoritative x authoritative y) (auth_own x auth_own y).
Lemma auth_included (x y : auth A) :
x y authoritative x authoritative y auth_own x auth_own y.
Proof.
split; [intros [[z1 z2] Hz]; split; [exists z1|exists z2]; apply Hz|].
intros [[z1 Hz1] [z2 Hz2]]; exists (Auth z1 z2); split; auto.
Qed.
Lemma authoritative_validN n x : {n} x {n} authoritative x.
Proof. by destruct x as [[[]|]]. Qed.
Lemma auth_own_validN n x : {n} x {n} auth_own x.
Proof. destruct x as [[[]|]]; naive_solver eauto using cmra_validN_includedN. Qed.
Lemma auth_valid_discrete `{CMRADiscrete A} x :
x match authoritative x with
| Excl' a => auth_own x a a
| None => auth_own x
| ExclBot' => False
end.
Proof.
destruct x as [[[?|]|] ?]; simpl; try done.
setoid_rewrite <-cmra_discrete_included_iff; naive_solver eauto using 0.
Qed.
Lemma auth_valid_discrete_2 `{CMRADiscrete A} a b : ( a b) b a a.
Proof. by rewrite auth_valid_discrete /= left_id. Qed.
Lemma authoritative_valid x : x authoritative x.
Proof. by destruct x as [[[]|]]. Qed.
Lemma auth_own_valid `{CMRADiscrete A} x : x auth_own x.
Proof.
rewrite auth_valid_discrete.
destruct x as [[[]|]]; naive_solver eauto using cmra_valid_included.
Qed.
Lemma auth_cmra_mixin : CMRAMixin (auth A).
Proof.
apply cmra_total_mixin.
- eauto.
- by intros n x y1 y2 [Hy Hy']; split; simpl; rewrite ?Hy ?Hy'.
- by intros n y1 y2 [Hy Hy']; split; simpl; rewrite ?Hy ?Hy'.
- intros n [x a] [y b] [Hx Ha]; simpl in *.
destruct Hx as [?? Hx|]; first destruct Hx; intros ?; cofe_subst; auto.
- intros [[[?|]|] ?]; rewrite /= ?cmra_included_includedN ?cmra_valid_validN;
naive_solver eauto using O.
- intros n [[[]|] ?] ?; naive_solver eauto using cmra_includedN_S, cmra_validN_S.
- by split; simpl; rewrite assoc.
- by split; simpl; rewrite comm.
- by split; simpl; rewrite ?cmra_core_l.
- by split; simpl; rewrite ?cmra_core_idemp.
- intros ??; rewrite! auth_included; intros [??].
by split; simpl; apply cmra_core_mono.
- assert ( n (a b1 b2 : A), b1 b2 {n} a b1 {n} a).
{ intros n a b1 b2 <-; apply cmra_includedN_l. }
intros n [[[a1|]|] b1] [[[a2|]|] b2];
naive_solver eauto using cmra_validN_op_l, cmra_validN_includedN.
- intros n x y1 y2 ? [??]; simpl in *.
destruct (cmra_extend n (authoritative x) (authoritative y1)
(authoritative y2)) as (ea1&ea2&?&?&?); auto using authoritative_validN.
destruct (cmra_extend n (auth_own x) (auth_own y1) (auth_own y2))
as (b1&b2&?&?&?); auto using auth_own_validN.
by exists (Auth ea1 b1), (Auth ea2 b2).
Qed.
Canonical Structure authR := CMRAT (auth A) auth_cofe_mixin auth_cmra_mixin.
Global Instance auth_cmra_discrete : CMRADiscrete A CMRADiscrete authR.
Proof.
split; first apply _.
intros [[[?|]|] ?]; rewrite /= /cmra_valid /cmra_validN /=; auto.
- setoid_rewrite <-cmra_discrete_included_iff.
rewrite -cmra_discrete_valid_iff. tauto.
- by rewrite -cmra_discrete_valid_iff.
Qed.
Instance auth_empty : Empty (auth A) := Auth ∅.
Lemma auth_ucmra_mixin : UCMRAMixin (auth A).
Proof.
split; simpl.
- apply (@ucmra_unit_valid A).
- by intros x; constructor; rewrite /= left_id.
- do 2 constructor; simpl; apply (persistent_core _).
Qed.
Canonical Structure authUR :=
UCMRAT (auth A) auth_cofe_mixin auth_cmra_mixin auth_ucmra_mixin.
Global Instance auth_frag_persistent a : Persistent a Persistent ( a).
Proof. do 2 constructor; simpl; auto. by apply persistent_core. Qed.
(** Internalized properties *)
Lemma auth_equivI {M} (x y : auth A) :
x y ⊣⊢ (authoritative x authoritative y auth_own x auth_own y : uPred M).
Proof. by uPred.unseal. Qed.
Lemma auth_validI {M} (x : auth A) :
x ⊣⊢ (match authoritative x with
| Excl' a => ( b, a auth_own x b) a
| None => auth_own x
| ExclBot' => False
end : uPred M).
Proof. uPred.unseal. by destruct x as [[[]|]]. Qed.
Lemma auth_frag_op a b : (a b) a b.
Proof. done. Qed.
Lemma auth_frag_mono a b : a b a b.
Proof. intros [c ->]. rewrite auth_frag_op. apply cmra_included_l. Qed.
Global Instance auth_frag_cmra_homomorphism : UCMRAHomomorphism (Auth None).
Proof. done. Qed.
Lemma auth_both_op a b : Auth (Excl' a) b a b.
Proof. by rewrite /op /auth_op /= left_id. Qed.
Lemma auth_auth_valid a : a ( a).
Proof. intros; split; simpl; auto using ucmra_unit_leastN. Qed.
Lemma auth_update a b a' b' :
(a,b) ~l~> (a',b') a b ~~> a' b'.
Proof.
intros Hup; apply cmra_total_update.
move=> n [[[?|]|] bf1] // [[bf2 Ha] ?]; do 2 red; simpl in *.
move: Ha; rewrite !left_id -assoc=> Ha.
destruct (Hup n (Some (bf1 bf2))); auto.
split; last done. exists bf2. by rewrite -assoc.
Qed.
Lemma auth_update_alloc a a' b' : (a,) ~l~> (a',b') a ~~> a' b'.
Proof. intros. rewrite -(right_id _ _ ( a)). by apply auth_update. Qed.
Lemma auth_update_dealloc a b a' : (a,b) ~l~> (a',) a b ~~> a'.
Proof. intros. rewrite -(right_id _ _ ( a')). by apply auth_update. Qed.
End cmra.
Arguments authR : clear implicits.
Arguments authUR : clear implicits.
(* Proof mode class instances *)
Instance from_op_auth_frag {A : ucmraT} (a b1 b2 : A) :
FromOp a b1 b2 FromOp ( a) ( b1) ( b2).
Proof. done. Qed.
Instance into_op_auth_frag {A : ucmraT} (a b1 b2 : A) :
IntoOp a b1 b2 IntoOp ( a) ( b1) ( b2).
Proof. done. Qed.
(* Functor *)
Definition auth_map {A B} (f : A B) (x : auth A) : auth B :=
Auth (excl_map f <$> authoritative x) (f (auth_own x)).
Lemma auth_map_id {A} (x : auth A) : auth_map id x = x.
Proof. by destruct x as [[[]|]]. Qed.
Lemma auth_map_compose {A B C} (f : A B) (g : B C) (x : auth A) :
auth_map (g f) x = auth_map g (auth_map f x).
Proof. by destruct x as [[[]|]]. Qed.
Lemma auth_map_ext {A B : cofeT} (f g : A B) x :
( x, f x g x) auth_map f x auth_map g x.
Proof.
constructor; simpl; auto.
apply option_fmap_setoid_ext=> a; by apply excl_map_ext.
Qed.
Instance auth_map_ne {A B : cofeT} n :
Proper ((dist n ==> dist n) ==> dist n ==> dist n) (@auth_map A B).
Proof.
intros f g Hf [??] [??] [??]; split; simpl in *; [|by apply Hf].
apply option_fmap_ne; [|done]=> x y ?; by apply excl_map_ne.
Qed.
Instance auth_map_cmra_monotone {A B : ucmraT} (f : A B) :
CMRAMonotone f CMRAMonotone (auth_map f).
Proof.
split; try apply _.
- intros n [[[a|]|] b]; rewrite /= /cmra_validN /=; try
naive_solver eauto using cmra_monotoneN, cmra_monotone_validN.
- by intros [x a] [y b]; rewrite !auth_included /=;
intros [??]; split; simpl; apply: cmra_monotone.
Qed.
Definition authC_map {A B} (f : A -n> B) : authC A -n> authC B :=
CofeMor (auth_map f).
Lemma authC_map_ne A B n : Proper (dist n ==> dist n) (@authC_map A B).
Proof. intros f f' Hf [[[a|]|] b]; repeat constructor; apply Hf. Qed.
Program Definition authRF (F : urFunctor) : rFunctor := {|
rFunctor_car A B := authR (urFunctor_car F A B);
rFunctor_map A1 A2 B1 B2 fg := authC_map (urFunctor_map F fg)
|}.
Next Obligation.
by intros F A1 A2 B1 B2 n f g Hfg; apply authC_map_ne, urFunctor_ne.
Qed.
Next Obligation.
intros F A B x. rewrite /= -{2}(auth_map_id x).
apply auth_map_ext=>y; apply urFunctor_id.
Qed.
Next Obligation.
intros F A1 A2 A3 B1 B2 B3 f g f' g' x. rewrite /= -auth_map_compose.
apply auth_map_ext=>y; apply urFunctor_compose.
Qed.
Instance authRF_contractive F :
urFunctorContractive F rFunctorContractive (authRF F).
Proof.
by intros ? A1 A2 B1 B2 n f g Hfg; apply authC_map_ne, urFunctor_contractive.
Qed.
Program Definition authURF (F : urFunctor) : urFunctor := {|
urFunctor_car A B := authUR (urFunctor_car F A B);
urFunctor_map A1 A2 B1 B2 fg := authC_map (urFunctor_map F fg)
|}.
Next Obligation.
by intros F A1 A2 B1 B2 n f g Hfg; apply authC_map_ne, urFunctor_ne.
Qed.
Next Obligation.
intros F A B x. rewrite /= -{2}(auth_map_id x).
apply auth_map_ext=>y; apply urFunctor_id.
Qed.
Next Obligation.
intros F A1 A2 A3 B1 B2 B3 f g f' g' x. rewrite /= -auth_map_compose.
apply auth_map_ext=>y; apply urFunctor_compose.
Qed.
Instance authURF_contractive F :
urFunctorContractive F urFunctorContractive (authURF F).
Proof.
by intros ? A1 A2 B1 B2 n f g Hfg; apply authC_map_ne, urFunctor_contractive.
Qed.
From mathcomp Require Export ssreflect.
From iris.prelude Require Export prelude.
Global Set Bullet Behavior "Strict Subproofs".
Global Open Scope general_if_scope.
Ltac done := prelude.tactics.done.
\ No newline at end of file
From iris.algebra Require Export cofe.
Class PCore (A : Type) := pcore : A option A.
Instance: Params (@pcore) 2.
Class Op (A : Type) := op : A A A.
Instance: Params (@op) 2.
Infix "⋅" := op (at level 50, left associativity) : C_scope.
Notation "(⋅)" := op (only parsing) : C_scope.
(* The inclusion quantifies over [A], not [option A]. This means we do not get
reflexivity. However, if we used [option A], the following would no longer
hold:
x ≼ y ↔ x.1 ≼ y.1 ∧ x.2 ≼ y.2
*)
Definition included `{Equiv A, Op A} (x y : A) := z, y x z.
Infix "≼" := included (at level 70) : C_scope.
Notation "(≼)" := included (only parsing) : C_scope.
Hint Extern 0 (_ _) => reflexivity.
Instance: Params (@included) 3.
Class ValidN (A : Type) := validN : nat A Prop.
Instance: Params (@validN) 3.
Notation "✓{ n } x" := (validN n x)
(at level 20, n at next level, format "✓{ n } x").
Class Valid (A : Type) := valid : A Prop.
Instance: Params (@valid) 2.
Notation "✓ x" := (valid x) (at level 20) : C_scope.
Definition includedN `{Dist A, Op A} (n : nat) (x y : A) := z, y {n} x z.
Notation "x ≼{ n } y" := (includedN n x y)
(at level 70, n at next level, format "x ≼{ n } y") : C_scope.
Instance: Params (@includedN) 4.
Hint Extern 0 (_ {_} _) => reflexivity.
Record CMRAMixin A `{Dist A, Equiv A, PCore A, Op A, Valid A, ValidN A} := {
(* setoids *)
mixin_cmra_op_ne n (x : A) : Proper (dist n ==> dist n) (op x);
mixin_cmra_pcore_ne n x y cx :
x {n} y pcore x = Some cx cy, pcore y = Some cy cx {n} cy;
mixin_cmra_validN_ne n : Proper (dist n ==> impl) (validN n);
(* valid *)
mixin_cmra_valid_validN x : x n, {n} x;
mixin_cmra_validN_S n x : {S n} x {n} x;
(* monoid *)
mixin_cmra_assoc : Assoc () ();
mixin_cmra_comm : Comm () ();
mixin_cmra_pcore_l x cx : pcore x = Some cx cx x x;
mixin_cmra_pcore_idemp x cx : pcore x = Some cx pcore cx Some cx;
mixin_cmra_pcore_mono x y cx :
x y pcore x = Some cx cy, pcore y = Some cy cx cy;
mixin_cmra_validN_op_l n x y : {n} (x y) {n} x;
mixin_cmra_extend n x y1 y2 :
{n} x x {n} y1 y2
z1 z2, x z1 z2 z1 {n} y1 z2 {n} y2
}.
(** Bundeled version *)
Structure cmraT := CMRAT' {
cmra_car :> Type;
cmra_equiv : Equiv cmra_car;
cmra_dist : Dist cmra_car;
cmra_compl : Compl cmra_car;
cmra_pcore : PCore cmra_car;
cmra_op : Op cmra_car;
cmra_valid : Valid cmra_car;
cmra_validN : ValidN cmra_car;
cmra_cofe_mixin : CofeMixin cmra_car;
cmra_mixin : CMRAMixin cmra_car;
_ : Type
}.
Arguments CMRAT' _ {_ _ _ _ _ _ _} _ _ _.
Notation CMRAT A m m' := (CMRAT' A m m' A).
Arguments cmra_car : simpl never.
Arguments cmra_equiv : simpl never.
Arguments cmra_dist : simpl never.
Arguments cmra_compl : simpl never.
Arguments cmra_pcore : simpl never.
Arguments cmra_op : simpl never.
Arguments cmra_valid : simpl never.
Arguments cmra_validN : simpl never.
Arguments cmra_cofe_mixin : simpl never.
Arguments cmra_mixin : simpl never.
Add Printing Constructor cmraT.
Hint Extern 0 (PCore _) => eapply (@cmra_pcore _) : typeclass_instances.
Hint Extern 0 (Op _) => eapply (@cmra_op _) : typeclass_instances.
Hint Extern 0 (Valid _) => eapply (@cmra_valid _) : typeclass_instances.
Hint Extern 0 (ValidN _) => eapply (@cmra_validN _) : typeclass_instances.
Coercion cmra_cofeC (A : cmraT) : cofeT := CofeT A (cmra_cofe_mixin A).
Canonical Structure cmra_cofeC.
(** Lifting properties from the mixin *)
Section cmra_mixin.
Context {A : cmraT}.
Implicit Types x y : A.
Global Instance cmra_op_ne n (x : A) : Proper (dist n ==> dist n) (op x).
Proof. apply (mixin_cmra_op_ne _ (cmra_mixin A)). Qed.
Lemma cmra_pcore_ne n x y cx :
x {n} y pcore x = Some cx cy, pcore y = Some cy cx {n} cy.
Proof. apply (mixin_cmra_pcore_ne _ (cmra_mixin A)). Qed.
Global Instance cmra_validN_ne n : Proper (dist n ==> impl) (@validN A _ n).
Proof. apply (mixin_cmra_validN_ne _ (cmra_mixin A)). Qed.
Lemma cmra_valid_validN x : x n, {n} x.
Proof. apply (mixin_cmra_valid_validN _ (cmra_mixin A)). Qed.
Lemma cmra_validN_S n x : {S n} x {n} x.
Proof. apply (mixin_cmra_validN_S _ (cmra_mixin A)). Qed.
Global Instance cmra_assoc : Assoc () (@op A _).
Proof. apply (mixin_cmra_assoc _ (cmra_mixin A)). Qed.
Global Instance cmra_comm : Comm () (@op A _).
Proof. apply (mixin_cmra_comm _ (cmra_mixin A)). Qed.
Lemma cmra_pcore_l x cx : pcore x = Some cx cx x x.
Proof. apply (mixin_cmra_pcore_l _ (cmra_mixin A)). Qed.
Lemma cmra_pcore_idemp x cx : pcore x = Some cx pcore cx Some cx.
Proof. apply (mixin_cmra_pcore_idemp _ (cmra_mixin A)). Qed.
Lemma cmra_pcore_mono x y cx :
x y pcore x = Some cx cy, pcore y = Some cy cx cy.
Proof. apply (mixin_cmra_pcore_mono _ (cmra_mixin A)). Qed.
Lemma cmra_validN_op_l n x y : {n} (x y) {n} x.
Proof. apply (mixin_cmra_validN_op_l _ (cmra_mixin A)). Qed.
Lemma cmra_extend n x y1 y2 :
{n} x x {n} y1 y2
z1 z2, x z1 z2 z1 {n} y1 z2 {n} y2.
Proof. apply (mixin_cmra_extend _ (cmra_mixin A)). Qed.
End cmra_mixin.
Definition opM {A : cmraT} (x : A) (my : option A) :=
match my with Some y => x y | None => x end.
Infix "⋅?" := opM (at level 50, left associativity) : C_scope.
(** * Persistent elements *)
Class Persistent {A : cmraT} (x : A) := persistent : pcore x Some x.
Arguments persistent {_} _ {_}.
(** * Exclusive elements (i.e., elements that cannot have a frame). *)
Class Exclusive {A : cmraT} (x : A) := exclusive0_l y : {0} (x y) False.
Arguments exclusive0_l {_} _ {_} _ _.
(** * CMRAs whose core is total *)
(** The function [core] may return a dummy when used on CMRAs without total
core. *)
Class CMRATotal (A : cmraT) := cmra_total (x : A) : is_Some (pcore x).
Class Core (A : Type) := core : A A.
Instance: Params (@core) 2.
Instance core' `{PCore A} : Core A := λ x, from_option id x (pcore x).
Arguments core' _ _ _ /.
(** * CMRAs with a unit element *)
(** We use the notation ∅ because for most instances (maps, sets, etc) the
`empty' element is the unit. *)
Record UCMRAMixin A `{Dist A, Equiv A, PCore A, Op A, Valid A, Empty A} := {
mixin_ucmra_unit_valid : ;
mixin_ucmra_unit_left_id : LeftId () ();
mixin_ucmra_pcore_unit : pcore Some
}.
Structure ucmraT := UCMRAT' {
ucmra_car :> Type;
ucmra_equiv : Equiv ucmra_car;
ucmra_dist : Dist ucmra_car;
ucmra_compl : Compl ucmra_car;
ucmra_pcore : PCore ucmra_car;
ucmra_op : Op ucmra_car;
ucmra_valid : Valid ucmra_car;
ucmra_validN : ValidN ucmra_car;
ucmra_empty : Empty ucmra_car;
ucmra_cofe_mixin : CofeMixin ucmra_car;
ucmra_cmra_mixin : CMRAMixin ucmra_car;
ucmra_mixin : UCMRAMixin ucmra_car;
_ : Type;
}.
Arguments UCMRAT' _ {_ _ _ _ _ _ _ _} _ _ _ _.
Notation UCMRAT A m m' m'' := (UCMRAT' A m m' m'' A).
Arguments ucmra_car : simpl never.
Arguments ucmra_equiv : simpl never.
Arguments ucmra_dist : simpl never.
Arguments ucmra_compl : simpl never.
Arguments ucmra_pcore : simpl never.
Arguments ucmra_op : simpl never.
Arguments ucmra_valid : simpl never.
Arguments ucmra_validN : simpl never.
Arguments ucmra_cofe_mixin : simpl never.
Arguments ucmra_cmra_mixin : simpl never.
Arguments ucmra_mixin : simpl never.
Add Printing Constructor ucmraT.
Hint Extern 0 (Empty _) => eapply (@ucmra_empty _) : typeclass_instances.
Coercion ucmra_cofeC (A : ucmraT) : cofeT := CofeT A (ucmra_cofe_mixin A).
Canonical Structure ucmra_cofeC.
Coercion ucmra_cmraR (A : ucmraT) : cmraT :=
CMRAT A (ucmra_cofe_mixin A) (ucmra_cmra_mixin A).
Canonical Structure ucmra_cmraR.
(** Lifting properties from the mixin *)
Section ucmra_mixin.
Context {A : ucmraT}.
Implicit Types x y : A.
Lemma ucmra_unit_valid : ( : A).
Proof. apply (mixin_ucmra_unit_valid _ (ucmra_mixin A)). Qed.
Global Instance ucmra_unit_left_id : LeftId () (@op A _).
Proof. apply (mixin_ucmra_unit_left_id _ (ucmra_mixin A)). Qed.
Lemma ucmra_pcore_unit : pcore (∅:A) Some ∅.
Proof. apply (mixin_ucmra_pcore_unit _ (ucmra_mixin A)). Qed.
End ucmra_mixin.
(** * Discrete CMRAs *)
Class CMRADiscrete (A : cmraT) := {
cmra_discrete :> Discrete A;
cmra_discrete_valid (x : A) : {0} x x
}.
(** * Morphisms *)
Class CMRAMonotone {A B : cmraT} (f : A B) := {
cmra_monotone_ne n :> Proper (dist n ==> dist n) f;
cmra_monotone_validN n x : {n} x {n} f x;
cmra_monotone x y : x y f x f y
}.
Arguments cmra_monotone_validN {_ _} _ {_} _ _ _.
Arguments cmra_monotone {_ _} _ {_} _ _ _.
(* Not all intended homomorphisms preserve validity, in particular it does not
hold for the [ownM] and [own] connectives. *)
Class CMRAHomomorphism {A B : cmraT} (f : A B) := {
cmra_homomorphism_ne n :> Proper (dist n ==> dist n) f;
cmra_homomorphism x y : f (x y) f x f y
}.
Arguments cmra_homomorphism {_ _} _ _ _ _.
Class UCMRAHomomorphism {A B : ucmraT} (f : A B) := {
ucmra_homomorphism :> CMRAHomomorphism f;
ucmra_homomorphism_unit : f
}.
Arguments ucmra_homomorphism_unit {_ _} _ _.
(** * Properties **)
Section cmra.
Context {A : cmraT}.
Implicit Types x y z : A.
Implicit Types xs ys zs : list A.
(** ** Setoids *)
Global Instance cmra_pcore_ne' n : Proper (dist n ==> dist n) (@pcore A _).
Proof.
intros x y Hxy. destruct (pcore x) as [cx|] eqn:?.
{ destruct (cmra_pcore_ne n x y cx) as (cy&->&->); auto. }
destruct (pcore y) as [cy|] eqn:?; auto.
destruct (cmra_pcore_ne n y x cy) as (cx&?&->); simplify_eq/=; auto.
Qed.
Lemma cmra_pcore_proper x y cx :
x y pcore x = Some cx cy, pcore y = Some cy cx cy.
Proof.
intros. destruct (cmra_pcore_ne 0 x y cx) as (cy&?&?); auto.
exists cy; split; [done|apply equiv_dist=> n].
destruct (cmra_pcore_ne n x y cx) as (cy'&?&?); naive_solver.
Qed.
Global Instance cmra_pcore_proper' : Proper (() ==> ()) (@pcore A _).
Proof. apply (ne_proper _). Qed.
Global Instance cmra_op_ne' n : Proper (dist n ==> dist n ==> dist n) (@op A _).
Proof. intros x1 x2 Hx y1 y2 Hy. by rewrite Hy (comm _ x1) Hx (comm _ y2). Qed.
Global Instance cmra_op_proper' : Proper (() ==> () ==> ()) (@op A _).
Proof. apply (ne_proper_2 _). Qed.
Global Instance cmra_validN_ne' : Proper (dist n ==> iff) (@validN A _ n) | 1.
Proof. by split; apply cmra_validN_ne. Qed.
Global Instance cmra_validN_proper : Proper (() ==> iff) (@validN A _ n) | 1.
Proof. by intros n x1 x2 Hx; apply cmra_validN_ne', equiv_dist. Qed.
Global Instance cmra_valid_proper : Proper (() ==> iff) (@valid A _).
Proof.
intros x y Hxy; rewrite !cmra_valid_validN.
by split=> ? n; [rewrite -Hxy|rewrite Hxy].
Qed.
Global Instance cmra_includedN_ne n :
Proper (dist n ==> dist n ==> iff) (@includedN A _ _ n) | 1.
Proof.
intros x x' Hx y y' Hy.
by split; intros [z ?]; exists z; [rewrite -Hx -Hy|rewrite Hx Hy].
Qed.
Global Instance cmra_includedN_proper n :
Proper (() ==> () ==> iff) (@includedN A _ _ n) | 1.
Proof.
intros x x' Hx y y' Hy; revert Hx Hy; rewrite !equiv_dist=> Hx Hy.
by rewrite (Hx n) (Hy n).
Qed.
Global Instance cmra_included_proper :
Proper (() ==> () ==> iff) (@included A _ _) | 1.
Proof.
intros x x' Hx y y' Hy.
by split; intros [z ?]; exists z; [rewrite -Hx -Hy|rewrite Hx Hy].
Qed.
Global Instance cmra_opM_ne n : Proper (dist n ==> dist n ==> dist n) (@opM A).
Proof. destruct 2; by cofe_subst. Qed.
Global Instance cmra_opM_proper : Proper (() ==> () ==> ()) (@opM A).
Proof. destruct 2; by setoid_subst. Qed.
(** ** Op *)
Lemma cmra_opM_assoc x y mz : (x y) ? mz x (y ? mz).
Proof. destruct mz; by rewrite /= -?assoc. Qed.
(** ** Validity *)
Lemma cmra_validN_le n n' x : {n} x n' n {n'} x.
Proof. induction 2; eauto using cmra_validN_S. Qed.
Lemma cmra_valid_op_l x y : (x y) x.
Proof. rewrite !cmra_valid_validN; eauto using cmra_validN_op_l. Qed.
Lemma cmra_validN_op_r n x y : {n} (x y) {n} y.
Proof. rewrite (comm _ x); apply cmra_validN_op_l. Qed.
Lemma cmra_valid_op_r x y : (x y) y.
Proof. rewrite !cmra_valid_validN; eauto using cmra_validN_op_r. Qed.
(** ** Core *)
Lemma cmra_pcore_l' x cx : pcore x Some cx cx x x.
Proof. intros (cx'&?&->)%equiv_Some_inv_r'. by apply cmra_pcore_l. Qed.
Lemma cmra_pcore_r x cx : pcore x = Some cx x cx x.
Proof. intros. rewrite comm. by apply cmra_pcore_l. Qed.
Lemma cmra_pcore_r' x cx : pcore x Some cx x cx x.
Proof. intros (cx'&?&->)%equiv_Some_inv_r'. by apply cmra_pcore_r. Qed.
Lemma cmra_pcore_idemp' x cx : pcore x Some cx pcore cx Some cx.
Proof. intros (cx'&?&->)%equiv_Some_inv_r'. eauto using cmra_pcore_idemp. Qed.
Lemma cmra_pcore_dup x cx : pcore x = Some cx cx cx cx.
Proof. intros; symmetry; eauto using cmra_pcore_r', cmra_pcore_idemp. Qed.
Lemma cmra_pcore_dup' x cx : pcore x Some cx cx cx cx.
Proof. intros; symmetry; eauto using cmra_pcore_r', cmra_pcore_idemp'. Qed.
Lemma cmra_pcore_validN n x cx : {n} x pcore x = Some cx {n} cx.
Proof.
intros Hvx Hx%cmra_pcore_l. move: Hvx; rewrite -Hx. apply cmra_validN_op_l.
Qed.
Lemma cmra_pcore_valid x cx : x pcore x = Some cx cx.
Proof.
intros Hv Hx%cmra_pcore_l. move: Hv; rewrite -Hx. apply cmra_valid_op_l.
Qed.
(** ** Persistent elements *)
Lemma persistent_dup x `{!Persistent x} : x x x.
Proof. by apply cmra_pcore_dup' with x. Qed.
(** ** Exclusive elements *)
Lemma exclusiveN_l n x `{!Exclusive x} y : {n} (x y) False.
Proof. intros. eapply (exclusive0_l x y), cmra_validN_le; eauto with lia. Qed.
Lemma exclusiveN_r n x `{!Exclusive x} y : {n} (y x) False.
Proof. rewrite comm. by apply exclusiveN_l. Qed.
Lemma exclusive_l x `{!Exclusive x} y : (x y) False.
Proof. by move /cmra_valid_validN /(_ 0) /exclusive0_l. Qed.
Lemma exclusive_r x `{!Exclusive x} y : (y x) False.
Proof. rewrite comm. by apply exclusive_l. Qed.
Lemma exclusiveN_opM n x `{!Exclusive x} my : {n} (x ? my) my = None.
Proof. destruct my as [y|]. move=> /(exclusiveN_l _ x) []. done. Qed.
Lemma exclusive_includedN n x `{!Exclusive x} y : x {n} y {n} y False.
Proof. intros [? ->]. by apply exclusiveN_l. Qed.
Lemma exclusive_included x `{!Exclusive x} y : x y y False.
Proof. intros [? ->]. by apply exclusive_l. Qed.
(** ** Order *)
Lemma cmra_included_includedN n x y : x y x {n} y.
Proof. intros [z ->]. by exists z. Qed.
Global Instance cmra_includedN_trans n : Transitive (@includedN A _ _ n).
Proof.
intros x y z [z1 Hy] [z2 Hz]; exists (z1 z2). by rewrite assoc -Hy -Hz.
Qed.
Global Instance cmra_included_trans: Transitive (@included A _ _).
Proof.
intros x y z [z1 Hy] [z2 Hz]; exists (z1 z2). by rewrite assoc -Hy -Hz.
Qed.
Lemma cmra_valid_included x y : y x y x.
Proof. intros Hyv [z ?]; setoid_subst; eauto using cmra_valid_op_l. Qed.
Lemma cmra_validN_includedN n x y : {n} y x {n} y {n} x.
Proof. intros Hyv [z ?]; cofe_subst y; eauto using cmra_validN_op_l. Qed.
Lemma cmra_validN_included n x y : {n} y x y {n} x.
Proof. intros Hyv [z ?]; setoid_subst; eauto using cmra_validN_op_l. Qed.
Lemma cmra_includedN_S n x y : x {S n} y x {n} y.
Proof. by intros [z Hz]; exists z; apply dist_S. Qed.
Lemma cmra_includedN_le n n' x y : x {n} y n' n x {n'} y.
Proof. induction 2; auto using cmra_includedN_S. Qed.
Lemma cmra_includedN_l n x y : x {n} x y.
Proof. by exists y. Qed.
Lemma cmra_included_l x y : x x y.
Proof. by exists y. Qed.
Lemma cmra_includedN_r n x y : y {n} x y.
Proof. rewrite (comm op); apply cmra_includedN_l. Qed.
Lemma cmra_included_r x y : y x y.
Proof. rewrite (comm op); apply cmra_included_l. Qed.
Lemma cmra_pcore_mono' x y cx :
x y pcore x Some cx cy, pcore y = Some cy cx cy.
Proof.
intros ? (cx'&?&Hcx)%equiv_Some_inv_r'.
destruct (cmra_pcore_mono x y cx') as (cy&->&?); auto.
exists cy; by rewrite Hcx.
Qed.
Lemma cmra_pcore_monoN' n x y cx :
x {n} y pcore x {n} Some cx cy, pcore y = Some cy cx {n} cy.
Proof.
intros [z Hy] (cx'&?&Hcx)%dist_Some_inv_r'.
destruct (cmra_pcore_mono x (x z) cx')
as (cy&Hxy&?); auto using cmra_included_l.
assert (pcore y {n} Some cy) as (cy'&?&Hcy')%dist_Some_inv_r'.
{ by rewrite Hy Hxy. }
exists cy'; split; first done.
rewrite Hcx -Hcy'; auto using cmra_included_includedN.
Qed.
Lemma cmra_included_pcore x cx : pcore x = Some cx cx x.
Proof. exists x. by rewrite cmra_pcore_l. Qed.
Lemma cmra_monoN_l n x y z : x {n} y z x {n} z y.
Proof. by intros [z1 Hz1]; exists z1; rewrite Hz1 (assoc op). Qed.
Lemma cmra_mono_l x y z : x y z x z y.
Proof. by intros [z1 Hz1]; exists z1; rewrite Hz1 (assoc op). Qed.
Lemma cmra_monoN_r n x y z : x {n} y x z {n} y z.
Proof. by intros; rewrite -!(comm _ z); apply cmra_monoN_l. Qed.
Lemma cmra_mono_r x y z : x y x z y z.
Proof. by intros; rewrite -!(comm _ z); apply cmra_mono_l. Qed.
Lemma cmra_monoN n x1 x2 y1 y2 : x1 {n} y1 x2 {n} y2 x1 x2 {n} y1 y2.
Proof. intros; etrans; eauto using cmra_monoN_l, cmra_monoN_r. Qed.
Lemma cmra_mono x1 x2 y1 y2 : x1 y1 x2 y2 x1 x2 y1 y2.
Proof. intros; etrans; eauto using cmra_mono_l, cmra_mono_r. Qed.
Global Instance cmra_monoN' n :
Proper (includedN n ==> includedN n ==> includedN n) (@op A _).
Proof. intros x1 x2 Hx y1 y2 Hy. by apply cmra_monoN. Qed.
Global Instance cmra_mono' :
Proper (included ==> included ==> included) (@op A _).
Proof. intros x1 x2 Hx y1 y2 Hy. by apply cmra_mono. Qed.
Lemma cmra_included_dist_l n x1 x2 x1' :
x1 x2 x1' {n} x1 x2', x1' x2' x2' {n} x2.
Proof.
intros [z Hx2] Hx1; exists (x1' z); split; auto using cmra_included_l.
by rewrite Hx1 Hx2.
Qed.
(** ** Total core *)
Section total_core.
Context `{CMRATotal A}.
Lemma cmra_core_l x : core x x x.
Proof.
destruct (cmra_total x) as [cx Hcx]. by rewrite /core /= Hcx cmra_pcore_l.
Qed.
Lemma cmra_core_idemp x : core (core x) core x.
Proof.
destruct (cmra_total x) as [cx Hcx]. by rewrite /core /= Hcx cmra_pcore_idemp.
Qed.
Lemma cmra_core_mono x y : x y core x core y.
Proof.
intros; destruct (cmra_total x) as [cx Hcx].
destruct (cmra_pcore_mono x y cx) as (cy&Hcy&?); auto.
by rewrite /core /= Hcx Hcy.
Qed.
Global Instance cmra_core_ne n : Proper (dist n ==> dist n) (@core A _).
Proof.
intros x y Hxy. destruct (cmra_total x) as [cx Hcx].
by rewrite /core /= -Hxy Hcx.
Qed.
Global Instance cmra_core_proper : Proper (() ==> ()) (@core A _).
Proof. apply (ne_proper _). Qed.
Lemma cmra_core_r x : x core x x.
Proof. by rewrite (comm _ x) cmra_core_l. Qed.
Lemma cmra_core_dup x : core x core x core x.
Proof. by rewrite -{3}(cmra_core_idemp x) cmra_core_r. Qed.
Lemma cmra_core_validN n x : {n} x {n} core x.
Proof. rewrite -{1}(cmra_core_l x); apply cmra_validN_op_l. Qed.
Lemma cmra_core_valid x : x core x.
Proof. rewrite -{1}(cmra_core_l x); apply cmra_valid_op_l. Qed.
Lemma persistent_total x : Persistent x core x x.
Proof.
split; [intros; by rewrite /core /= (persistent x)|].
rewrite /Persistent /core /=.
destruct (cmra_total x) as [? ->]. by constructor.
Qed.
Lemma persistent_core x `{!Persistent x} : core x x.
Proof. by apply persistent_total. Qed.
Global Instance cmra_core_persistent x : Persistent (core x).
Proof.
destruct (cmra_total x) as [cx Hcx].
rewrite /Persistent /core /= Hcx /=. eauto using cmra_pcore_idemp.
Qed.
Lemma cmra_included_core x : core x x.
Proof. by exists x; rewrite cmra_core_l. Qed.
Global Instance cmra_includedN_preorder n : PreOrder (@includedN A _ _ n).
Proof.
split; [|apply _]. by intros x; exists (core x); rewrite cmra_core_r.
Qed.
Global Instance cmra_included_preorder : PreOrder (@included A _ _).
Proof.
split; [|apply _]. by intros x; exists (core x); rewrite cmra_core_r.
Qed.
Lemma cmra_core_monoN n x y : x {n} y core x {n} core y.
Proof.
intros [z ->].
apply cmra_included_includedN, cmra_core_mono, cmra_included_l.
Qed.
End total_core.
(** ** Timeless *)
Lemma cmra_timeless_included_l x y : Timeless x {0} y x {0} y x y.
Proof.
intros ?? [x' ?].
destruct (cmra_extend 0 y x x') as (z&z'&Hy&Hz&Hz'); auto; simpl in *.
by exists z'; rewrite Hy (timeless x z).
Qed.
Lemma cmra_timeless_included_r x y : Timeless y x {0} y x y.
Proof. intros ? [x' ?]. exists x'. by apply (timeless y). Qed.
Lemma cmra_op_timeless x1 x2 :
(x1 x2) Timeless x1 Timeless x2 Timeless (x1 x2).
Proof.
intros ??? z Hz.
destruct (cmra_extend 0 z x1 x2) as (y1&y2&Hz'&?&?); auto; simpl in *.
{ rewrite -?Hz. by apply cmra_valid_validN. }
by rewrite Hz' (timeless x1 y1) // (timeless x2 y2).
Qed.
(** ** Discrete *)
Lemma cmra_discrete_valid_iff `{CMRADiscrete A} n x : x {n} x.
Proof.
split; first by rewrite cmra_valid_validN.
eauto using cmra_discrete_valid, cmra_validN_le with lia.
Qed.
Lemma cmra_discrete_included_iff `{Discrete A} n x y : x y x {n} y.
Proof.
split; first by apply cmra_included_includedN.
intros [z ->%(timeless_iff _ _)]; eauto using cmra_included_l.
Qed.
End cmra.
(** * Properties about CMRAs with a unit element **)
Section ucmra.
Context {A : ucmraT}.
Implicit Types x y z : A.
Lemma ucmra_unit_validN n : {n} (∅:A).
Proof. apply cmra_valid_validN, ucmra_unit_valid. Qed.
Lemma ucmra_unit_leastN n x : {n} x.
Proof. by exists x; rewrite left_id. Qed.
Lemma ucmra_unit_least x : x.
Proof. by exists x; rewrite left_id. Qed.
Global Instance ucmra_unit_right_id : RightId () (@op A _).
Proof. by intros x; rewrite (comm op) left_id. Qed.
Global Instance ucmra_unit_persistent : Persistent (∅:A).
Proof. apply ucmra_pcore_unit. Qed.
Global Instance cmra_unit_total : CMRATotal A.
Proof.
intros x. destruct (cmra_pcore_mono' x ) as (cx&->&?);
eauto using ucmra_unit_least, (persistent ).
Qed.
End ucmra.
Hint Immediate cmra_unit_total.
(** * Properties about CMRAs with Leibniz equality *)
Section cmra_leibniz.
Context {A : cmraT} `{!LeibnizEquiv A}.
Implicit Types x y : A.
Global Instance cmra_assoc_L : Assoc (=) (@op A _).
Proof. intros x y z. unfold_leibniz. by rewrite assoc. Qed.
Global Instance cmra_comm_L : Comm (=) (@op A _).
Proof. intros x y. unfold_leibniz. by rewrite comm. Qed.
Lemma cmra_pcore_l_L x cx : pcore x = Some cx cx x = x.
Proof. unfold_leibniz. apply cmra_pcore_l'. Qed.
Lemma cmra_pcore_idemp_L x cx : pcore x = Some cx pcore cx = Some cx.
Proof. unfold_leibniz. apply cmra_pcore_idemp'. Qed.
Lemma cmra_opM_assoc_L x y mz : (x y) ? mz = x (y ? mz).
Proof. unfold_leibniz. apply cmra_opM_assoc. Qed.
(** ** Core *)
Lemma cmra_pcore_r_L x cx : pcore x = Some cx x cx = x.
Proof. unfold_leibniz. apply cmra_pcore_r'. Qed.
Lemma cmra_pcore_dup_L x cx : pcore x = Some cx cx = cx cx.
Proof. unfold_leibniz. apply cmra_pcore_dup'. Qed.
(** ** Persistent elements *)
Lemma persistent_dup_L x `{!Persistent x} : x x x.
Proof. unfold_leibniz. by apply persistent_dup. Qed.
(** ** Total core *)
Section total_core.
Context `{CMRATotal A}.
Lemma cmra_core_r_L x : x core x = x.
Proof. unfold_leibniz. apply cmra_core_r. Qed.
Lemma cmra_core_l_L x : core x x = x.
Proof. unfold_leibniz. apply cmra_core_l. Qed.
Lemma cmra_core_idemp_L x : core (core x) = core x.
Proof. unfold_leibniz. apply cmra_core_idemp. Qed.
Lemma cmra_core_dup_L x : core x = core x core x.
Proof. unfold_leibniz. apply cmra_core_dup. Qed.
Lemma persistent_total_L x : Persistent x core x = x.
Proof. unfold_leibniz. apply persistent_total. Qed.
Lemma persistent_core_L x `{!Persistent x} : core x = x.
Proof. by apply persistent_total_L. Qed.
End total_core.
End cmra_leibniz.
Section ucmra_leibniz.
Context {A : ucmraT} `{!LeibnizEquiv A}.
Implicit Types x y z : A.
Global Instance ucmra_unit_left_id_L : LeftId (=) (@op A _).
Proof. intros x. unfold_leibniz. by rewrite left_id. Qed.
Global Instance ucmra_unit_right_id_L : RightId (=) (@op A _).
Proof. intros x. unfold_leibniz. by rewrite right_id. Qed.
End ucmra_leibniz.
(** * Constructing a CMRA with total core *)
Section cmra_total.
Context A `{Dist A, Equiv A, PCore A, Op A, Valid A, ValidN A}.
Context (total : x, is_Some (pcore x)).
Context (op_ne : n (x : A), Proper (dist n ==> dist n) (op x)).
Context (core_ne : n, Proper (dist n ==> dist n) (@core A _)).
Context (validN_ne : n, Proper (dist n ==> impl) (@validN A _ n)).
Context (valid_validN : (x : A), x n, {n} x).
Context (validN_S : n (x : A), {S n} x {n} x).
Context (op_assoc : Assoc () (@op A _)).
Context (op_comm : Comm () (@op A _)).
Context (core_l : x : A, core x x x).
Context (core_idemp : x : A, core (core x) core x).
Context (core_mono : x y : A, x y core x core y).
Context (validN_op_l : n (x y : A), {n} (x y) {n} x).
Context (extend : n (x y1 y2 : A),
{n} x x {n} y1 y2
z1 z2, x z1 z2 z1 {n} y1 z2 {n} y2).
Lemma cmra_total_mixin : CMRAMixin A.
Proof.
split; auto.
- intros n x y ? Hcx%core_ne Hx; move: Hcx. rewrite /core /= Hx /=.
case (total y)=> [cy ->]; eauto.
- intros x cx Hcx. move: (core_l x). by rewrite /core /= Hcx.
- intros x cx Hcx. move: (core_idemp x). rewrite /core /= Hcx /=.
case (total cx)=>[ccx ->]; by constructor.
- intros x y cx Hxy%core_mono Hx. move: Hxy.
rewrite /core /= Hx /=. case (total y)=> [cy ->]; eauto.
Qed.
End cmra_total.
(** * Properties about monotone functions *)
Instance cmra_monotone_id {A : cmraT} : CMRAMonotone (@id A).
Proof. repeat split; by try apply _. Qed.
Instance cmra_monotone_compose {A B C : cmraT} (f : A B) (g : B C) :
CMRAMonotone f CMRAMonotone g CMRAMonotone (g f).
Proof.
split.
- apply _.
- move=> n x Hx /=. by apply cmra_monotone_validN, cmra_monotone_validN.
- move=> x y Hxy /=. by apply cmra_monotone, cmra_monotone.
Qed.
Section cmra_monotone.
Context {A B : cmraT} (f : A B) `{!CMRAMonotone f}.
Global Instance cmra_monotone_proper : Proper (() ==> ()) f := ne_proper _.
Lemma cmra_monotoneN n x y : x {n} y f x {n} f y.
Proof.
intros [z ->].
apply cmra_included_includedN, (cmra_monotone f), cmra_included_l.
Qed.
Lemma cmra_monotone_valid x : x f x.
Proof. rewrite !cmra_valid_validN; eauto using cmra_monotone_validN. Qed.
End cmra_monotone.
Instance cmra_homomorphism_id {A : cmraT} : CMRAHomomorphism (@id A).
Proof. repeat split; by try apply _. Qed.
Instance cmra_homomorphism_compose {A B C : cmraT} (f : A B) (g : B C) :
CMRAHomomorphism f CMRAHomomorphism g CMRAHomomorphism (g f).
Proof.
split.
- apply _.
- move=> x y /=. rewrite -(cmra_homomorphism g).
by apply (ne_proper _), cmra_homomorphism.
Qed.
Instance cmra_homomorphism_proper {A B : cmraT} (f : A B) :
CMRAHomomorphism f Proper (() ==> ()) f := λ _, ne_proper _.
Instance ucmra_homomorphism_id {A : ucmraT} : UCMRAHomomorphism (@id A).
Proof. repeat split; by try apply _. Qed.
Instance ucmra_homomorphism_compose {A B C : ucmraT} (f : A B) (g : B C) :
UCMRAHomomorphism f UCMRAHomomorphism g UCMRAHomomorphism (g f).
Proof. split. apply _. by rewrite /= !ucmra_homomorphism_unit. Qed.
(** Functors *)
Structure rFunctor := RFunctor {
rFunctor_car : cofeT cofeT cmraT;
rFunctor_map {A1 A2 B1 B2} :
((A2 -n> A1) * (B1 -n> B2)) rFunctor_car A1 B1 -n> rFunctor_car A2 B2;
rFunctor_ne A1 A2 B1 B2 n :
Proper (dist n ==> dist n) (@rFunctor_map A1 A2 B1 B2);
rFunctor_id {A B} (x : rFunctor_car A B) : rFunctor_map (cid,cid) x x;
rFunctor_compose {A1 A2 A3 B1 B2 B3}
(f : A2 -n> A1) (g : A3 -n> A2) (f' : B1 -n> B2) (g' : B2 -n> B3) x :
rFunctor_map (fg, g'f') x rFunctor_map (g,g') (rFunctor_map (f,f') x);
rFunctor_mono {A1 A2 B1 B2} (fg : (A2 -n> A1) * (B1 -n> B2)) :
CMRAMonotone (rFunctor_map fg)
}.
Existing Instances rFunctor_ne rFunctor_mono.
Instance: Params (@rFunctor_map) 5.
Class rFunctorContractive (F : rFunctor) :=
rFunctor_contractive A1 A2 B1 B2 :> Contractive (@rFunctor_map F A1 A2 B1 B2).
Definition rFunctor_diag (F: rFunctor) (A: cofeT) : cmraT := rFunctor_car F A A.
Coercion rFunctor_diag : rFunctor >-> Funclass.
Program Definition constRF (B : cmraT) : rFunctor :=
{| rFunctor_car A1 A2 := B; rFunctor_map A1 A2 B1 B2 f := cid |}.
Solve Obligations with done.
Instance constRF_contractive B : rFunctorContractive (constRF B).
Proof. rewrite /rFunctorContractive; apply _. Qed.
Structure urFunctor := URFunctor {
urFunctor_car : cofeT cofeT ucmraT;
urFunctor_map {A1 A2 B1 B2} :
((A2 -n> A1) * (B1 -n> B2)) urFunctor_car A1 B1 -n> urFunctor_car A2 B2;
urFunctor_ne A1 A2 B1 B2 n :
Proper (dist n ==> dist n) (@urFunctor_map A1 A2 B1 B2);
urFunctor_id {A B} (x : urFunctor_car A B) : urFunctor_map (cid,cid) x x;
urFunctor_compose {A1 A2 A3 B1 B2 B3}
(f : A2 -n> A1) (g : A3 -n> A2) (f' : B1 -n> B2) (g' : B2 -n> B3) x :
urFunctor_map (fg, g'f') x urFunctor_map (g,g') (urFunctor_map (f,f') x);
urFunctor_mono {A1 A2 B1 B2} (fg : (A2 -n> A1) * (B1 -n> B2)) :
CMRAMonotone (urFunctor_map fg)
}.
Existing Instances urFunctor_ne urFunctor_mono.
Instance: Params (@urFunctor_map) 5.
Class urFunctorContractive (F : urFunctor) :=
urFunctor_contractive A1 A2 B1 B2 :> Contractive (@urFunctor_map F A1 A2 B1 B2).
Definition urFunctor_diag (F: urFunctor) (A: cofeT) : ucmraT := urFunctor_car F A A.
Coercion urFunctor_diag : urFunctor >-> Funclass.
Program Definition constURF (B : ucmraT) : urFunctor :=
{| urFunctor_car A1 A2 := B; urFunctor_map A1 A2 B1 B2 f := cid |}.
Solve Obligations with done.
Instance constURF_contractive B : urFunctorContractive (constURF B).
Proof. rewrite /urFunctorContractive; apply _. Qed.
(** * Transporting a CMRA equality *)
Definition cmra_transport {A B : cmraT} (H : A = B) (x : A) : B :=
eq_rect A id x _ H.
Section cmra_transport.
Context {A B : cmraT} (H : A = B).
Notation T := (cmra_transport H).
Global Instance cmra_transport_ne n : Proper (dist n ==> dist n) T.
Proof. by intros ???; destruct H. Qed.
Global Instance cmra_transport_proper : Proper (() ==> ()) T.
Proof. by intros ???; destruct H. Qed.
Lemma cmra_transport_op x y : T (x y) = T x T y.
Proof. by destruct H. Qed.
Lemma cmra_transport_core x : T (core x) = core (T x).
Proof. by destruct H. Qed.
Lemma cmra_transport_validN n x : {n} T x {n} x.
Proof. by destruct H. Qed.
Lemma cmra_transport_valid x : T x x.
Proof. by destruct H. Qed.
Global Instance cmra_transport_timeless x : Timeless x Timeless (T x).
Proof. by destruct H. Qed.
Global Instance cmra_transport_persistent x : Persistent x Persistent (T x).
Proof. by destruct H. Qed.
End cmra_transport.
(** * Instances *)
(** ** Discrete CMRA *)
Record RAMixin A `{Equiv A, PCore A, Op A, Valid A} := {
(* setoids *)
ra_op_proper (x : A) : Proper (() ==> ()) (op x);
ra_core_proper x y cx :
x y pcore x = Some cx cy, pcore y = Some cy cx cy;
ra_validN_proper : Proper (() ==> impl) valid;
(* monoid *)
ra_assoc : Assoc () ();
ra_comm : Comm () ();
ra_pcore_l x cx : pcore x = Some cx cx x x;
ra_pcore_idemp x cx : pcore x = Some cx pcore cx Some cx;
ra_pcore_mono x y cx :
x y pcore x = Some cx cy, pcore y = Some cy cx cy;
ra_valid_op_l x y : (x y) x
}.
Section discrete.
Context `{Equiv A, PCore A, Op A, Valid A, @Equivalence A ()}.
Context (ra_mix : RAMixin A).
Existing Instances discrete_dist discrete_compl.
Instance discrete_validN : ValidN A := λ n x, x.
Definition discrete_cmra_mixin : CMRAMixin A.
Proof.
destruct ra_mix; split; try done.
- intros x; split; first done. by move=> /(_ 0).
- intros n x y1 y2 ??; by exists y1, y2.
Qed.
End discrete.
Notation discreteR A ra_mix :=
(CMRAT A discrete_cofe_mixin (discrete_cmra_mixin ra_mix)).
Notation discreteUR A ra_mix ucmra_mix :=
(UCMRAT A discrete_cofe_mixin (discrete_cmra_mixin ra_mix) ucmra_mix).
Global Instance discrete_cmra_discrete `{Equiv A, PCore A, Op A, Valid A,
@Equivalence A ()} (ra_mix : RAMixin A) : CMRADiscrete (discreteR A ra_mix).
Proof. split. apply _. done. Qed.
Section ra_total.
Context A `{Equiv A, PCore A, Op A, Valid A}.
Context (total : x, is_Some (pcore x)).
Context (op_proper : (x : A), Proper (() ==> ()) (op x)).
Context (core_proper: Proper (() ==> ()) (@core A _)).
Context (valid_proper : Proper (() ==> impl) (@valid A _)).
Context (op_assoc : Assoc () (@op A _)).
Context (op_comm : Comm () (@op A _)).
Context (core_l : x : A, core x x x).
Context (core_idemp : x : A, core (core x) core x).
Context (core_mono : x y : A, x y core x core y).
Context (valid_op_l : x y : A, (x y) x).
Lemma ra_total_mixin : RAMixin A.
Proof.
split; auto.
- intros x y ? Hcx%core_proper Hx; move: Hcx. rewrite /core /= Hx /=.
case (total y)=> [cy ->]; eauto.
- intros x cx Hcx. move: (core_l x). by rewrite /core /= Hcx.
- intros x cx Hcx. move: (core_idemp x). rewrite /core /= Hcx /=.
case (total cx)=>[ccx ->]; by constructor.
- intros x y cx Hxy%core_mono Hx. move: Hxy.
rewrite /core /= Hx /=. case (total y)=> [cy ->]; eauto.
Qed.
End ra_total.
(** ** CMRA for the unit type *)
Section unit.
Instance unit_valid : Valid () := λ x, True.
Instance unit_validN : ValidN () := λ n x, True.
Instance unit_pcore : PCore () := λ x, Some x.
Instance unit_op : Op () := λ x y, ().
Lemma unit_cmra_mixin : CMRAMixin ().
Proof. apply discrete_cmra_mixin, ra_total_mixin; by eauto. Qed.
Canonical Structure unitR : cmraT := CMRAT () unit_cofe_mixin unit_cmra_mixin.
Instance unit_empty : Empty () := ().
Lemma unit_ucmra_mixin : UCMRAMixin ().
Proof. done. Qed.
Canonical Structure unitUR : ucmraT :=
UCMRAT () unit_cofe_mixin unit_cmra_mixin unit_ucmra_mixin.
Global Instance unit_cmra_discrete : CMRADiscrete unitR.
Proof. done. Qed.
Global Instance unit_persistent (x : ()) : Persistent x.
Proof. by constructor. Qed.
End unit.
(** ** Natural numbers *)
Section nat.
Instance nat_valid : Valid nat := λ x, True.
Instance nat_validN : ValidN nat := λ n x, True.
Instance nat_pcore : PCore nat := λ x, Some 0.
Instance nat_op : Op nat := plus.
Definition nat_op_plus x y : x y = x + y := eq_refl.
Lemma nat_included (x y : nat) : x y x y.
Proof.
split.
- intros [z ->]; unfold op, nat_op; lia.
- exists (y - x). by apply le_plus_minus.
Qed.
Lemma nat_ra_mixin : RAMixin nat.
Proof.
apply ra_total_mixin; try by eauto.
- solve_proper.
- intros x y z. apply Nat.add_assoc.
- intros x y. apply Nat.add_comm.
- by exists 0.
Qed.
Canonical Structure natR : cmraT := discreteR nat nat_ra_mixin.
Instance nat_empty : Empty nat := 0.
Lemma nat_ucmra_mixin : UCMRAMixin nat.
Proof. split; apply _ || done. Qed.
Canonical Structure natUR : ucmraT :=
discreteUR nat nat_ra_mixin nat_ucmra_mixin.
Global Instance nat_cmra_discrete : CMRADiscrete natR.
Proof. constructor; apply _ || done. Qed.
End nat.
Definition mnat := nat.
Section mnat.
Instance mnat_valid : Valid mnat := λ x, True.
Instance mnat_validN : ValidN mnat := λ n x, True.
Instance mnat_pcore : PCore mnat := Some.
Instance mnat_op : Op mnat := Nat.max.
Definition mnat_op_max x y : x y = x `max` y := eq_refl.
Lemma mnat_included (x y : mnat) : x y x y.
Proof.
split.
- intros [z ->]; unfold op, mnat_op; lia.
- exists y. by symmetry; apply Nat.max_r.
Qed.
Lemma mnat_ra_mixin : RAMixin mnat.
Proof.
apply ra_total_mixin; try by eauto.
- solve_proper.
- solve_proper.
- intros x y z. apply Nat.max_assoc.
- intros x y. apply Nat.max_comm.
- intros x. apply Max.max_idempotent.
Qed.
Canonical Structure mnatR : cmraT := discreteR mnat mnat_ra_mixin.
Instance mnat_empty : Empty mnat := 0.
Lemma mnat_ucmra_mixin : UCMRAMixin mnat.
Proof. split; apply _ || done. Qed.
Canonical Structure mnatUR : ucmraT :=
discreteUR mnat mnat_ra_mixin mnat_ucmra_mixin.
Global Instance mnat_cmra_discrete : CMRADiscrete mnatR.
Proof. constructor; apply _ || done. Qed.
Global Instance mnat_persistent (x : mnat) : Persistent x.
Proof. by constructor. Qed.
End mnat.
(** ** Product *)
Section prod.
Context {A B : cmraT}.
Local Arguments pcore _ _ !_ /.
Local Arguments cmra_pcore _ !_/.
Instance prod_op : Op (A * B) := λ x y, (x.1 y.1, x.2 y.2).
Instance prod_pcore : PCore (A * B) := λ x,
c1 pcore (x.1); c2 pcore (x.2); Some (c1, c2).
Arguments prod_pcore !_ /.
Instance prod_valid : Valid (A * B) := λ x, x.1 x.2.
Instance prod_validN : ValidN (A * B) := λ n x, {n} x.1 {n} x.2.
Lemma prod_pcore_Some (x cx : A * B) :
pcore x = Some cx pcore (x.1) = Some (cx.1) pcore (x.2) = Some (cx.2).
Proof. destruct x, cx; by intuition simplify_option_eq. Qed.
Lemma prod_pcore_Some' (x cx : A * B) :
pcore x Some cx pcore (x.1) Some (cx.1) pcore (x.2) Some (cx.2).
Proof.
split; [by intros (cx'&[-> ->]%prod_pcore_Some&->)%equiv_Some_inv_r'|].
rewrite {3}/pcore /prod_pcore. (* TODO: use setoid rewrite *)
intros [Hx1 Hx2]; inversion_clear Hx1; simpl; inversion_clear Hx2.
by constructor.
Qed.
Lemma prod_included (x y : A * B) : x y x.1 y.1 x.2 y.2.
Proof.
split; [intros [z Hz]; split; [exists (z.1)|exists (z.2)]; apply Hz|].
intros [[z1 Hz1] [z2 Hz2]]; exists (z1,z2); split; auto.
Qed.
Lemma prod_includedN (x y : A * B) n : x {n} y x.1 {n} y.1 x.2 {n} y.2.
Proof.
split; [intros [z Hz]; split; [exists (z.1)|exists (z.2)]; apply Hz|].
intros [[z1 Hz1] [z2 Hz2]]; exists (z1,z2); split; auto.
Qed.
Definition prod_cmra_mixin : CMRAMixin (A * B).
Proof.
split; try apply _.
- by intros n x y1 y2 [Hy1 Hy2]; split; rewrite /= ?Hy1 ?Hy2.
- intros n x y cx; setoid_rewrite prod_pcore_Some=> -[??] [??].
destruct (cmra_pcore_ne n (x.1) (y.1) (cx.1)) as (z1&->&?); auto.
destruct (cmra_pcore_ne n (x.2) (y.2) (cx.2)) as (z2&->&?); auto.
exists (z1,z2); repeat constructor; auto.
- by intros n y1 y2 [Hy1 Hy2] [??]; split; rewrite /= -?Hy1 -?Hy2.
- intros x; split.
+ intros [??] n; split; by apply cmra_valid_validN.
+ intros Hxy; split; apply cmra_valid_validN=> n; apply Hxy.
- by intros n x [??]; split; apply cmra_validN_S.
- by split; rewrite /= assoc.
- by split; rewrite /= comm.
- intros x y [??]%prod_pcore_Some;
constructor; simpl; eauto using cmra_pcore_l.
- intros x y; rewrite prod_pcore_Some prod_pcore_Some'.
naive_solver eauto using cmra_pcore_idemp.
- intros x y cx; rewrite prod_included prod_pcore_Some=> -[??] [??].
destruct (cmra_pcore_mono (x.1) (y.1) (cx.1)) as (z1&?&?); auto.
destruct (cmra_pcore_mono (x.2) (y.2) (cx.2)) as (z2&?&?); auto.
exists (z1,z2). by rewrite prod_included prod_pcore_Some.
- intros n x y [??]; split; simpl in *; eauto using cmra_validN_op_l.
- intros n x y1 y2 [??] [??]; simpl in *.
destruct (cmra_extend n (x.1) (y1.1) (y2.1)) as (z11&z12&?&?&?); auto.
destruct (cmra_extend n (x.2) (y1.2) (y2.2)) as (z21&z22&?&?&?); auto.
by exists (z11,z21), (z12,z22).
Qed.
Canonical Structure prodR :=
CMRAT (A * B) prod_cofe_mixin prod_cmra_mixin.
Lemma pair_op (a a' : A) (b b' : B) : (a, b) (a', b') = (a a', b b').
Proof. done. Qed.
Global Instance prod_cmra_total : CMRATotal A CMRATotal B CMRATotal prodR.
Proof.
intros H1 H2 [a b]. destruct (H1 a) as [ca ?], (H2 b) as [cb ?].
exists (ca,cb); by simplify_option_eq.
Qed.
Global Instance prod_cmra_discrete :
CMRADiscrete A CMRADiscrete B CMRADiscrete prodR.
Proof. split. apply _. by intros ? []; split; apply cmra_discrete_valid. Qed.
Global Instance pair_persistent x y :
Persistent x Persistent y Persistent (x,y).
Proof. by rewrite /Persistent prod_pcore_Some'. Qed.
Global Instance pair_exclusive_l x y : Exclusive x Exclusive (x,y).
Proof. by intros ?[][?%exclusive0_l]. Qed.
Global Instance pair_exclusive_r x y : Exclusive y Exclusive (x,y).
Proof. by intros ?[][??%exclusive0_l]. Qed.
End prod.
Arguments prodR : clear implicits.
Section prod_unit.
Context {A B : ucmraT}.
Instance prod_empty `{Empty A, Empty B} : Empty (A * B) := (, ).
Lemma prod_ucmra_mixin : UCMRAMixin (A * B).
Proof.
split.
- split; apply ucmra_unit_valid.
- by split; rewrite /=left_id.
- rewrite prod_pcore_Some'; split; apply (persistent _).
Qed.
Canonical Structure prodUR :=
UCMRAT (A * B) prod_cofe_mixin prod_cmra_mixin prod_ucmra_mixin.
Lemma pair_split (x : A) (y : B) : (x, y) (x, ) (, y).
Proof. by rewrite pair_op left_id right_id. Qed.
Lemma pair_split_L `{!LeibnizEquiv A, !LeibnizEquiv B} (x : A) (y : B) :
(x, y) = (x, ) (, y).
Proof. unfold_leibniz. apply pair_split. Qed.
End prod_unit.
Arguments prodUR : clear implicits.
Instance prod_map_cmra_monotone {A A' B B' : cmraT} (f : A A') (g : B B') :
CMRAMonotone f CMRAMonotone g CMRAMonotone (prod_map f g).
Proof.
split; first apply _.
- by intros n x [??]; split; simpl; apply cmra_monotone_validN.
- intros x y; rewrite !prod_included=> -[??] /=.
by split; apply cmra_monotone.
Qed.
Program Definition prodRF (F1 F2 : rFunctor) : rFunctor := {|
rFunctor_car A B := prodR (rFunctor_car F1 A B) (rFunctor_car F2 A B);
rFunctor_map A1 A2 B1 B2 fg :=
prodC_map (rFunctor_map F1 fg) (rFunctor_map F2 fg)
|}.
Next Obligation.
intros F1 F2 A1 A2 B1 B2 n ???. by apply prodC_map_ne; apply rFunctor_ne.
Qed.
Next Obligation. by intros F1 F2 A B [??]; rewrite /= !rFunctor_id. Qed.
Next Obligation.
intros F1 F2 A1 A2 A3 B1 B2 B3 f g f' g' [??]; simpl.
by rewrite !rFunctor_compose.
Qed.
Instance prodRF_contractive F1 F2 :
rFunctorContractive F1 rFunctorContractive F2
rFunctorContractive (prodRF F1 F2).
Proof.
intros ?? A1 A2 B1 B2 n ???;
by apply prodC_map_ne; apply rFunctor_contractive.
Qed.
Program Definition prodURF (F1 F2 : urFunctor) : urFunctor := {|
urFunctor_car A B := prodUR (urFunctor_car F1 A B) (urFunctor_car F2 A B);
urFunctor_map A1 A2 B1 B2 fg :=
prodC_map (urFunctor_map F1 fg) (urFunctor_map F2 fg)
|}.
Next Obligation.
intros F1 F2 A1 A2 B1 B2 n ???. by apply prodC_map_ne; apply urFunctor_ne.
Qed.
Next Obligation. by intros F1 F2 A B [??]; rewrite /= !urFunctor_id. Qed.
Next Obligation.
intros F1 F2 A1 A2 A3 B1 B2 B3 f g f' g' [??]; simpl.
by rewrite !urFunctor_compose.
Qed.
Instance prodURF_contractive F1 F2 :
urFunctorContractive F1 urFunctorContractive F2
urFunctorContractive (prodURF F1 F2).
Proof.
intros ?? A1 A2 B1 B2 n ???;
by apply prodC_map_ne; apply urFunctor_contractive.
Qed.
(** ** CMRA for the option type *)
Section option.
Context {A : cmraT}.
Local Arguments core _ _ !_ /.
Local Arguments pcore _ _ !_ /.
Instance option_valid : Valid (option A) := λ mx,
match mx with Some x => x | None => True end.
Instance option_validN : ValidN (option A) := λ n mx,
match mx with Some x => {n} x | None => True end.
Instance option_pcore : PCore (option A) := λ mx, Some (mx ≫= pcore).
Arguments option_pcore !_ /.
Instance option_op : Op (option A) := union_with (λ x y, Some (x y)).
Definition Some_valid a : Some a a := reflexivity _.
Definition Some_op a b : Some (a b) = Some a Some b := eq_refl.
Lemma Some_core `{CMRATotal A} a : Some (core a) = core (Some a).
Proof. rewrite /core /=. by destruct (cmra_total a) as [? ->]. Qed.
Lemma Some_op_opM x my : Some x my = Some (x ? my).
Proof. by destruct my. Qed.
Lemma option_included (mx my : option A) :
mx my mx = None x y, mx = Some x my = Some y (x y x y).
Proof.
split.
- intros [mz Hmz].
destruct mx as [x|]; [right|by left].
destruct my as [y|]; [exists x, y|destruct mz; inversion_clear Hmz].
destruct mz as [z|]; inversion_clear Hmz; split_and?; auto;
setoid_subst; eauto using cmra_included_l.
- intros [->|(x&y&->&->&[Hz|[z Hz]])].
+ exists my. by destruct my.
+ exists None; by constructor.
+ exists (Some z); by constructor.
Qed.
Lemma option_cmra_mixin : CMRAMixin (option A).
Proof.
apply cmra_total_mixin.
- eauto.
- by intros n [x|]; destruct 1; constructor; cofe_subst.
- destruct 1; by cofe_subst.
- by destruct 1; rewrite /validN /option_validN //=; cofe_subst.
- intros [x|]; [apply cmra_valid_validN|done].
- intros n [x|]; unfold validN, option_validN; eauto using cmra_validN_S.
- intros [x|] [y|] [z|]; constructor; rewrite ?assoc; auto.
- intros [x|] [y|]; constructor; rewrite 1?comm; auto.
- intros [x|]; simpl; auto.
destruct (pcore x) as [cx|] eqn:?; constructor; eauto using cmra_pcore_l.
- intros [x|]; simpl; auto.
destruct (pcore x) as [cx|] eqn:?; simpl; eauto using cmra_pcore_idemp.
- intros mx my; setoid_rewrite option_included.
intros [->|(x&y&->&->&[?|?])]; simpl; eauto.
+ destruct (pcore x) as [cx|] eqn:?; eauto.
destruct (cmra_pcore_proper x y cx) as (?&?&?); eauto 10.
+ destruct (pcore x) as [cx|] eqn:?; eauto.
destruct (cmra_pcore_mono x y cx) as (?&?&?); eauto 10.
- intros n [x|] [y|]; rewrite /validN /option_validN /=;
eauto using cmra_validN_op_l.
- intros n mx my1 my2.
destruct mx as [x|], my1 as [y1|], my2 as [y2|]; intros Hx Hx';
inversion_clear Hx'; auto.
+ destruct (cmra_extend n x y1 y2) as (z1&z2&?&?&?); auto.
by exists (Some z1), (Some z2); repeat constructor.
+ by exists (Some x), None; repeat constructor.
+ by exists None, (Some x); repeat constructor.
+ exists None, None; repeat constructor.
Qed.
Canonical Structure optionR :=
CMRAT (option A) option_cofe_mixin option_cmra_mixin.
Global Instance option_cmra_discrete : CMRADiscrete A CMRADiscrete optionR.
Proof. split; [apply _|]. by intros [x|]; [apply (cmra_discrete_valid x)|]. Qed.
Instance option_empty : Empty (option A) := None.
Lemma option_ucmra_mixin : UCMRAMixin optionR.
Proof. split. done. by intros []. done. Qed.
Canonical Structure optionUR :=
UCMRAT (option A) option_cofe_mixin option_cmra_mixin option_ucmra_mixin.
(** Misc *)
Global Instance Some_cmra_monotone : CMRAMonotone Some.
Proof. split; [apply _|done|intros x y [z ->]; by exists (Some z)]. Qed.
Global Instance Some_cmra_homomorphism : CMRAHomomorphism Some.
Proof. split. apply _. done. Qed.
Lemma op_None mx my : mx my = None mx = None my = None.
Proof. destruct mx, my; naive_solver. Qed.
Lemma op_is_Some mx my : is_Some (mx my) is_Some mx is_Some my.
Proof. rewrite -!not_eq_None_Some op_None. destruct mx, my; naive_solver. Qed.
Global Instance Some_persistent (x : A) : Persistent x Persistent (Some x).
Proof. by constructor. Qed.
Global Instance option_persistent (mx : option A) :
( x : A, Persistent x) Persistent mx.
Proof. intros. destruct mx; apply _. Qed.
Lemma exclusiveN_Some_l n x `{!Exclusive x} my :
{n} (Some x my) my = None.
Proof. destruct my. move=> /(exclusiveN_l _ x) []. done. Qed.
Lemma exclusiveN_Some_r n x `{!Exclusive x} my :
{n} (my Some x) my = None.
Proof. rewrite comm. by apply exclusiveN_Some_l. Qed.
Lemma exclusive_Some_l x `{!Exclusive x} my : (Some x my) my = None.
Proof. destruct my. move=> /(exclusive_l x) []. done. Qed.
Lemma exclusive_Some_r x `{!Exclusive x} my : (my Some x) my = None.
Proof. rewrite comm. by apply exclusive_Some_l. Qed.
Lemma Some_included x y : Some x Some y x y x y.
Proof. rewrite option_included; naive_solver. Qed.
Lemma Some_included_2 x y : x y Some x Some y.
Proof. rewrite Some_included; eauto. Qed.
Lemma Some_included_total `{CMRATotal A} x y : Some x Some y x y.
Proof. rewrite Some_included. split. by intros [->|?]. eauto. Qed.
Lemma Some_included_exclusive x `{!Exclusive x} y :
Some x Some y y x y.
Proof. move=> /Some_included [//|/exclusive_included]; tauto. Qed.
Lemma is_Some_included mx my : mx my is_Some mx is_Some my.
Proof. rewrite -!not_eq_None_Some option_included. naive_solver. Qed.
End option.
Arguments optionR : clear implicits.
Arguments optionUR : clear implicits.
Section option_prod.
Context {A B : cmraT}.
Lemma Some_pair_included (x1 x2 : A) (y1 y2 : B) :
Some (x1,y1) Some (x2,y2) Some x1 Some x2 Some y1 Some y2.
Proof. rewrite !Some_included. intros [[??]|[??]%prod_included]; eauto. Qed.
Lemma Some_pair_included_total_1 `{CMRATotal A} (x1 x2 : A) (y1 y2 : B) :
Some (x1,y1) Some (x2,y2) x1 x2 Some y1 Some y2.
Proof. intros ?%Some_pair_included. by rewrite -(Some_included_total x1). Qed.
Lemma Some_pair_included_total_2 `{CMRATotal B} (x1 x2 : A) (y1 y2 : B) :
Some (x1,y1) Some (x2,y2) Some x1 Some x2 y1 y2.
Proof. intros ?%Some_pair_included. by rewrite -(Some_included_total y1). Qed.
End option_prod.
Instance option_fmap_cmra_monotone {A B : cmraT} (f: A B) `{!CMRAMonotone f} :
CMRAMonotone (fmap f : option A option B).
Proof.
split; first apply _.
- intros n [x|] ?; rewrite /cmra_validN //=. by apply (cmra_monotone_validN f).
- intros mx my; rewrite !option_included.
intros [->|(x&y&->&->&[Hxy|?])]; simpl; eauto 10 using @cmra_monotone.
right; exists (f x), (f y). by rewrite {3}Hxy; eauto.
Qed.
Program Definition optionURF (F : rFunctor) : urFunctor := {|
urFunctor_car A B := optionUR (rFunctor_car F A B);
urFunctor_map A1 A2 B1 B2 fg := optionC_map (rFunctor_map F fg)
|}.
Next Obligation.
by intros F A1 A2 B1 B2 n f g Hfg; apply optionC_map_ne, rFunctor_ne.
Qed.
Next Obligation.
intros F A B x. rewrite /= -{2}(option_fmap_id x).
apply option_fmap_setoid_ext=>y; apply rFunctor_id.
Qed.
Next Obligation.
intros F A1 A2 A3 B1 B2 B3 f g f' g' x. rewrite /= -option_fmap_compose.
apply option_fmap_setoid_ext=>y; apply rFunctor_compose.
Qed.
Instance optionURF_contractive F :
rFunctorContractive F urFunctorContractive (optionURF F).
Proof.
by intros ? A1 A2 B1 B2 n f g Hfg; apply optionC_map_ne, rFunctor_contractive.
Qed.
From iris.algebra Require Export cmra list.
From iris.prelude Require Import functions gmap.
(** The operator [ [⋅] Ps ] folds [⋅] over the list [Ps]. This operator is not a
quantifier, so it binds strongly.
Apart from that, we define the following big operators with binders build in:
- The operator [ [⋅ list] k ↦ x ∈ l, P ] folds over a list [l]. The binder [x]
refers to each element at index [k].
- The operator [ [⋅ map] k ↦ x ∈ m, P ] folds over a map [m]. The binder [x]
refers to each element at index [k].
- The operator [ [⋅ set] x ∈ X, P ] folds over a set [m]. The binder [x] refers
to each element.
Since these big operators are like quantifiers, they have the same precedence as
[∀] and [∃]. *)
(** * Big ops over lists *)
(* This is the basic building block for other big ops *)
Fixpoint big_op {M : ucmraT} (xs : list M) : M :=
match xs with [] => | x :: xs => x big_op xs end.
Arguments big_op _ !_ /.
Instance: Params (@big_op) 1.
Notation "'[⋅]' xs" := (big_op xs) (at level 20) : C_scope.
(** * Other big ops *)
Definition big_opL {M : ucmraT} {A} (l : list A) (f : nat A M) : M :=
[] (imap f l).
Instance: Params (@big_opL) 2.
Typeclasses Opaque big_opL.
Notation "'[⋅' 'list' ] k ↦ x ∈ l , P" := (big_opL l (λ k x, P))
(at level 200, l at level 10, k, x at level 1, right associativity,
format "[⋅ list ] k ↦ x ∈ l , P") : C_scope.
Notation "'[⋅' 'list' ] x ∈ l , P" := (big_opL l (λ _ x, P))
(at level 200, l at level 10, x at level 1, right associativity,
format "[⋅ list ] x ∈ l , P") : C_scope.
Definition big_opM {M : ucmraT} `{Countable K} {A}
(m : gmap K A) (f : K A M) : M :=
[] (curry f <$> map_to_list m).
Instance: Params (@big_opM) 6.
Typeclasses Opaque big_opM.
Notation "'[⋅' 'map' ] k ↦ x ∈ m , P" := (big_opM m (λ k x, P))
(at level 200, m at level 10, k, x at level 1, right associativity,
format "[⋅ map ] k ↦ x ∈ m , P") : C_scope.
Notation "'[⋅' 'map' ] x ∈ m , P" := (big_opM m (λ _ x, P))
(at level 200, m at level 10, x at level 1, right associativity,
format "[⋅ map ] x ∈ m , P") : C_scope.
Definition big_opS {M : ucmraT} `{Countable A}
(X : gset A) (f : A M) : M := [] (f <$> elements X).
Instance: Params (@big_opS) 5.
Typeclasses Opaque big_opS.
Notation "'[⋅' 'set' ] x ∈ X , P" := (big_opS X (λ x, P))
(at level 200, X at level 10, x at level 1, right associativity,
format "[⋅ set ] x ∈ X , P") : C_scope.
(** * Properties about big ops *)
Section big_op.
Context {M : ucmraT}.
Implicit Types xs : list M.
(** * Big ops *)
Lemma big_op_Forall2 R :
Reflexive R Proper (R ==> R ==> R) (@op M _)
Proper (Forall2 R ==> R) (@big_op M).
Proof. rewrite /Proper /respectful. induction 3; eauto. Qed.
Global Instance big_op_ne n : Proper (dist n ==> dist n) (@big_op M).
Proof. apply big_op_Forall2; apply _. Qed.
Global Instance big_op_proper : Proper (() ==> ()) (@big_op M) := ne_proper _.
Lemma big_op_nil : [] (@nil M) = ∅.
Proof. done. Qed.
Lemma big_op_cons x xs : [] (x :: xs) = x [] xs.
Proof. done. Qed.
Lemma big_op_app xs ys : [] (xs ++ ys) [] xs [] ys.
Proof.
induction xs as [|x xs IH]; simpl; first by rewrite ?left_id.
by rewrite IH assoc.
Qed.
Lemma big_op_mono xs ys : Forall2 () xs ys [] xs [] ys.
Proof. induction 1 as [|x y xs ys Hxy ? IH]; simpl; eauto using cmra_mono. Qed.
Global Instance big_op_permutation : Proper (() ==> ()) (@big_op M).
Proof.
induction 1 as [|x xs1 xs2 ? IH|x y xs|xs1 xs2 xs3]; simpl; auto.
- by rewrite IH.
- by rewrite !assoc (comm _ x).
- by trans (big_op xs2).
Qed.
Lemma big_op_contains xs ys : xs `contains` ys [] xs [] ys.
Proof.
intros [xs' ->]%contains_Permutation.
rewrite big_op_app; apply cmra_included_l.
Qed.
Lemma big_op_delete xs i x : xs !! i = Some x x [] delete i xs [] xs.
Proof. by intros; rewrite {2}(delete_Permutation xs i x). Qed.
Lemma big_sep_elem_of xs x : x xs x [] xs.
Proof.
intros [i ?]%elem_of_list_lookup. rewrite -big_op_delete //.
apply cmra_included_l.
Qed.
(** ** Big ops over lists *)
Section list.
Context {A : Type}.
Implicit Types l : list A.
Implicit Types f g : nat A M.
Lemma big_opL_nil f : ([ list] ky nil, f k y) = ∅.
Proof. done. Qed.
Lemma big_opL_cons f x l :
([ list] ky x :: l, f k y) = f 0 x [ list] ky l, f (S k) y.
Proof. by rewrite /big_opL imap_cons. Qed.
Lemma big_opL_singleton f x : ([ list] ky [x], f k y) f 0 x.
Proof. by rewrite big_opL_cons big_opL_nil right_id. Qed.
Lemma big_opL_app f l1 l2 :
([ list] ky l1 ++ l2, f k y)
([ list] ky l1, f k y) ([ list] ky l2, f (length l1 + k) y).
Proof. by rewrite /big_opL imap_app big_op_app. Qed.
Lemma big_opL_forall R f g l :
Reflexive R Proper (R ==> R ==> R) (@op M _)
( k y, l !! k = Some y R (f k y) (g k y))
R ([ list] k y l, f k y) ([ list] k y l, g k y).
Proof.
intros ? Hop. revert f g. induction l as [|x l IH]=> f g Hf; [done|].
rewrite !big_opL_cons. apply Hop; eauto.
Qed.
Lemma big_opL_mono f g l :
( k y, l !! k = Some y f k y g k y)
([ list] k y l, f k y) [ list] k y l, g k y.
Proof. apply big_opL_forall; apply _. Qed.
Lemma big_opL_ext f g l :
( k y, l !! k = Some y f k y = g k y)
([ list] k y l, f k y) = [ list] k y l, g k y.
Proof. apply big_opL_forall; apply _. Qed.
Lemma big_opL_proper f g l :
( k y, l !! k = Some y f k y g k y)
([ list] k y l, f k y) ([ list] k y l, g k y).
Proof. apply big_opL_forall; apply _. Qed.
Global Instance big_opL_ne l n :
Proper (pointwise_relation _ (pointwise_relation _ (dist n)) ==> (dist n))
(big_opL (M:=M) l).
Proof. intros f g Hf. apply big_opL_forall; apply _ || intros; apply Hf. Qed.
Global Instance big_opL_proper' l :
Proper (pointwise_relation _ (pointwise_relation _ ()) ==> ())
(big_opL (M:=M) l).
Proof. intros f g Hf. apply big_opL_forall; apply _ || intros; apply Hf. Qed.
Global Instance big_opL_mono' l :
Proper (pointwise_relation _ (pointwise_relation _ ()) ==> ())
(big_opL (M:=M) l).
Proof. intros f g Hf. apply big_opL_forall; apply _ || intros; apply Hf. Qed.
Lemma big_opL_consZ_l (f : Z A M) x l :
([ list] ky x :: l, f k y) = f 0 x [ list] ky l, f (1 + k)%Z y.
Proof. rewrite big_opL_cons. auto using big_opL_ext with f_equal lia. Qed.
Lemma big_opL_consZ_r (f : Z A M) x l :
([ list] ky x :: l, f k y) = f 0 x [ list] ky l, f (k + 1)%Z y.
Proof. rewrite big_opL_cons. auto using big_opL_ext with f_equal lia. Qed.
Lemma big_opL_lookup f l i x :
l !! i = Some x f i x [ list] ky l, f k y.
Proof.
intros. rewrite -(take_drop_middle l i x) // big_opL_app big_opL_cons.
rewrite Nat.add_0_r take_length_le; eauto using lookup_lt_Some, Nat.lt_le_incl.
eapply transitivity, cmra_included_r; eauto using cmra_included_l.
Qed.
Lemma big_opL_elem_of (f : A M) l x : x l f x [ list] y l, f y.
Proof.
intros [i ?]%elem_of_list_lookup; eauto using (big_opL_lookup (λ _, f)).
Qed.
Lemma big_opL_fmap {B} (h : A B) (f : nat B M) l :
([ list] ky h <$> l, f k y) ([ list] ky l, f k (h y)).
Proof. by rewrite /big_opL imap_fmap. Qed.
Lemma big_opL_opL f g l :
([ list] kx l, f k x g k x)
([ list] kx l, f k x) ([ list] kx l, g k x).
Proof.
revert f g; induction l as [|x l IH]=> f g.
{ by rewrite !big_opL_nil left_id. }
rewrite !big_opL_cons IH.
by rewrite -!assoc (assoc _ (g _ _)) [(g _ _ _)]comm -!assoc.
Qed.
End list.
(** ** Big ops over finite maps *)
Section gmap.
Context `{Countable K} {A : Type}.
Implicit Types m : gmap K A.
Implicit Types f g : K A M.
Lemma big_opM_forall R f g m :
Reflexive R Proper (R ==> R ==> R) (@op M _)
( k x, m !! k = Some x R (f k x) (g k x))
R ([ map] k x m, f k x) ([ map] k x m, g k x).
Proof.
intros ?? Hf. apply (big_op_Forall2 R _ _), Forall2_fmap, Forall_Forall2.
apply Forall_forall=> -[i x] ? /=. by apply Hf, elem_of_map_to_list.
Qed.
Lemma big_opM_mono f g m1 m2 :
m1 m2 ( k x, m2 !! k = Some x f k x g k x)
([ map] k x m1, f k x) [ map] k x m2, g k x.
Proof.
intros Hm Hf. trans ([ map] kx m2, f k x).
- by apply big_op_contains, fmap_contains, map_to_list_contains.
- apply big_opM_forall; apply _ || auto.
Qed.
Lemma big_opM_ext f g m :
( k x, m !! k = Some x f k x = g k x)
([ map] k x m, f k x) = ([ map] k x m, g k x).
Proof. apply big_opM_forall; apply _. Qed.
Lemma big_opM_proper f g m :
( k x, m !! k = Some x f k x g k x)
([ map] k x m, f k x) ([ map] k x m, g k x).
Proof. apply big_opM_forall; apply _. Qed.
Global Instance big_opM_ne m n :
Proper (pointwise_relation _ (pointwise_relation _ (dist n)) ==> (dist n))
(big_opM (M:=M) m).
Proof. intros f g Hf. apply big_opM_forall; apply _ || intros; apply Hf. Qed.
Global Instance big_opM_proper' m :
Proper (pointwise_relation _ (pointwise_relation _ ()) ==> ())
(big_opM (M:=M) m).
Proof. intros f g Hf. apply big_opM_forall; apply _ || intros; apply Hf. Qed.
Global Instance big_opM_mono' m :
Proper (pointwise_relation _ (pointwise_relation _ ()) ==> ())
(big_opM (M:=M) m).
Proof. intros f g Hf. apply big_opM_forall; apply _ || intros; apply Hf. Qed.
Lemma big_opM_empty f : ([ map] kx , f k x) = ∅.
Proof. by rewrite /big_opM map_to_list_empty. Qed.
Lemma big_opM_insert f m i x :
m !! i = None
([ map] ky <[i:=x]> m, f k y) f i x [ map] ky m, f k y.
Proof. intros ?. by rewrite /big_opM map_to_list_insert. Qed.
Lemma big_opM_delete f m i x :
m !! i = Some x
([ map] ky m, f k y) f i x [ map] ky delete i m, f k y.
Proof.
intros. rewrite -big_opM_insert ?lookup_delete //.
by rewrite insert_delete insert_id.
Qed.
Lemma big_opM_lookup f m i x :
m !! i = Some x f i x [ map] ky m, f k y.
Proof. intros. rewrite big_opM_delete //. apply cmra_included_l. Qed.
Lemma big_opM_singleton f i x : ([ map] ky {[i:=x]}, f k y) f i x.
Proof.
rewrite -insert_empty big_opM_insert/=; last auto using lookup_empty.
by rewrite big_opM_empty right_id.
Qed.
Lemma big_opM_fmap {B} (h : A B) (f : K B M) m :
([ map] ky h <$> m, f k y) ([ map] ky m, f k (h y)).
Proof.
rewrite /big_opM map_to_list_fmap -list_fmap_compose.
f_equiv; apply reflexive_eq, list_fmap_ext. by intros []. done.
Qed.
Lemma big_opM_insert_override (f : K M) m i x y :
m !! i = Some x
([ map] k↦_ <[i:=y]> m, f k) ([ map] k↦_ m, f k).
Proof.
intros. rewrite -insert_delete big_opM_insert ?lookup_delete //.
by rewrite -big_opM_delete.
Qed.
Lemma big_opM_fn_insert {B} (g : K A B M) (f : K B) m i (x : A) b :
m !! i = None
([ map] ky <[i:=x]> m, g k y (<[i:=b]> f k))
(g i x b [ map] ky m, g k y (f k)).
Proof.
intros. rewrite big_opM_insert // fn_lookup_insert.
apply cmra_op_proper', big_opM_proper; auto=> k y ?.
by rewrite fn_lookup_insert_ne; last set_solver.
Qed.
Lemma big_opM_fn_insert' (f : K M) m i x P :
m !! i = None
([ map] ky <[i:=x]> m, <[i:=P]> f k) (P [ map] ky m, f k).
Proof. apply (big_opM_fn_insert (λ _ _, id)). Qed.
Lemma big_opM_opM f g m :
([ map] kx m, f k x g k x)
([ map] kx m, f k x) ([ map] kx m, g k x).
Proof.
rewrite /big_opM.
induction (map_to_list m) as [|[i x] l IH]; csimpl; rewrite ?right_id //.
by rewrite IH -!assoc (assoc _ (g _ _)) [(g _ _ _)]comm -!assoc.
Qed.
End gmap.
(** ** Big ops over finite sets *)
Section gset.
Context `{Countable A}.
Implicit Types X : gset A.
Implicit Types f : A M.
Lemma big_opS_forall R f g X :
Reflexive R Proper (R ==> R ==> R) (@op M _)
( x, x X R (f x) (g x))
R ([ set] x X, f x) ([ set] x X, g x).
Proof.
intros ?? Hf. apply (big_op_Forall2 R _ _), Forall2_fmap, Forall_Forall2.
apply Forall_forall=> x ? /=. by apply Hf, elem_of_elements.
Qed.
Lemma big_opS_mono f g X Y :
X Y ( x, x Y f x g x)
([ set] x X, f x) [ set] x Y, g x.
Proof.
intros HX Hf. trans ([ set] x Y, f x).
- by apply big_op_contains, fmap_contains, elements_contains.
- apply big_opS_forall; apply _ || auto.
Qed.
Lemma big_opS_ext f g X :
( x, x X f x = g x)
([ set] x X, f x) = ([ set] x X, g x).
Proof. apply big_opS_forall; apply _. Qed.
Lemma big_opS_proper f g X :
( x, x X f x g x)
([ set] x X, f x) ([ set] x X, g x).
Proof. apply big_opS_forall; apply _. Qed.
Lemma big_opS_ne X n :
Proper (pointwise_relation _ (dist n) ==> dist n) (big_opS (M:=M) X).
Proof. intros f g Hf. apply big_opS_forall; apply _ || intros; apply Hf. Qed.
Lemma big_opS_proper' X :
Proper (pointwise_relation _ () ==> ()) (big_opS (M:=M) X).
Proof. intros f g Hf. apply big_opS_forall; apply _ || intros; apply Hf. Qed.
Lemma big_opS_mono' X :
Proper (pointwise_relation _ () ==> ()) (big_opS (M:=M) X).
Proof. intros f g Hf. apply big_opS_forall; apply _ || intros; apply Hf. Qed.
Lemma big_opS_empty f : ([ set] x , f x) = ∅.
Proof. by rewrite /big_opS elements_empty. Qed.
Lemma big_opS_insert f X x :
x X ([ set] y {[ x ]} X, f y) (f x [ set] y X, f y).
Proof. intros. by rewrite /big_opS elements_union_singleton. Qed.
Lemma big_opS_fn_insert {B} (f : A B M) h X x b :
x X
([ set] y {[ x ]} X, f y (<[x:=b]> h y))
(f x b [ set] y X, f y (h y)).
Proof.
intros. rewrite big_opS_insert // fn_lookup_insert.
apply cmra_op_proper', big_opS_proper; auto=> y ?.
by rewrite fn_lookup_insert_ne; last set_solver.
Qed.
Lemma big_opS_fn_insert' f X x P :
x X ([ set] y {[ x ]} X, <[x:=P]> f y) (P [ set] y X, f y).
Proof. apply (big_opS_fn_insert (λ y, id)). Qed.
Lemma big_opS_delete f X x :
x X ([ set] y X, f y) f x [ set] y X {[ x ]}, f y.
Proof.
intros. rewrite -big_opS_insert; last set_solver.
by rewrite -union_difference_L; last set_solver.
Qed.
Lemma big_opS_elem_of f X x : x X f x [ set] y X, f y.
Proof. intros. rewrite big_opS_delete //. apply cmra_included_l. Qed.
Lemma big_opS_singleton f x : ([ set] y {[ x ]}, f y) f x.
Proof. intros. by rewrite /big_opS elements_singleton /= right_id. Qed.
Lemma big_opS_opS f g X :
([ set] y X, f y g y) ([ set] y X, f y) ([ set] y X, g y).
Proof.
rewrite /big_opS.
induction (elements X) as [|x l IH]; csimpl; first by rewrite ?right_id.
by rewrite IH -!assoc (assoc _ (g _)) [(g _ _)]comm -!assoc.
Qed.
End gset.
End big_op.
(** Option *)
Lemma big_opL_None {M : cmraT} {A} (f : nat A option M) l :
([ list] kx l, f k x) = None k x, l !! k = Some x f k x = None.
Proof.
revert f. induction l as [|x l IH]=> f //=.
rewrite big_opL_cons op_None IH. split.
- intros [??] [|k] y ?; naive_solver.
- intros Hl. split. by apply (Hl 0). intros k. apply (Hl (S k)).
Qed.
Lemma big_opM_None {M : cmraT} `{Countable K} {A} (f : K A option M) m :
([ map] kx m, f k x) = None k x, m !! k = Some x f k x = None.
Proof.
induction m as [|i x m ? IH] using map_ind=> //=.
rewrite -equiv_None big_opM_insert // equiv_None op_None IH. split.
{ intros [??] k y. rewrite lookup_insert_Some; naive_solver. }
intros Hm; split.
- apply (Hm i). by simplify_map_eq.
- intros k y ?. apply (Hm k). by simplify_map_eq.
Qed.
Lemma big_opS_None {M : cmraT} `{Countable A} (f : A option M) X :
([ set] x X, f x) = None x, x X f x = None.
Proof.
induction X as [|x X ? IH] using collection_ind_L; [done|].
rewrite -equiv_None big_opS_insert // equiv_None op_None IH. set_solver.
Qed.
(** Commuting with respect to homomorphisms *)
Lemma big_opL_commute {M1 M2 : ucmraT} {A} (h : M1 M2)
`{!UCMRAHomomorphism h} (f : nat A M1) l :
h ([ list] kx l, f k x) ([ list] kx l, h (f k x)).
Proof.
revert f. induction l as [|x l IH]=> f.
- by rewrite !big_opL_nil ucmra_homomorphism_unit.
- by rewrite !big_opL_cons cmra_homomorphism -IH.
Qed.
Lemma big_opL_commute1 {M1 M2 : ucmraT} {A} (h : M1 M2)
`{!CMRAHomomorphism h} (f : nat A M1) l :
l [] h ([ list] kx l, f k x) ([ list] kx l, h (f k x)).
Proof.
intros ?. revert f. induction l as [|x [|x' l'] IH]=> f //.
- by rewrite !big_opL_singleton.
- by rewrite !(big_opL_cons _ x) cmra_homomorphism -IH.
Qed.
Lemma big_opM_commute {M1 M2 : ucmraT} `{Countable K} {A} (h : M1 M2)
`{!UCMRAHomomorphism h} (f : K A M1) m :
h ([ map] kx m, f k x) ([ map] kx m, h (f k x)).
Proof.
intros. induction m as [|i x m ? IH] using map_ind.
- by rewrite !big_opM_empty ucmra_homomorphism_unit.
- by rewrite !big_opM_insert // cmra_homomorphism -IH.
Qed.
Lemma big_opM_commute1 {M1 M2 : ucmraT} `{Countable K} {A} (h : M1 M2)
`{!CMRAHomomorphism h} (f : K A M1) m :
m h ([ map] kx m, f k x) ([ map] kx m, h (f k x)).
Proof.
intros. induction m as [|i x m ? IH] using map_ind; [done|].
destruct (decide (m = )) as [->|].
- by rewrite !big_opM_insert // !big_opM_empty !right_id.
- by rewrite !big_opM_insert // cmra_homomorphism -IH //.
Qed.
Lemma big_opS_commute {M1 M2 : ucmraT} `{Countable A}
(h : M1 M2) `{!UCMRAHomomorphism h} (f : A M1) X :
h ([ set] x X, f x) ([ set] x X, h (f x)).
Proof.
intros. induction X as [|x X ? IH] using collection_ind_L.
- by rewrite !big_opS_empty ucmra_homomorphism_unit.
- by rewrite !big_opS_insert // cmra_homomorphism -IH.
Qed.
Lemma big_opS_commute1 {M1 M2 : ucmraT} `{Countable A}
(h : M1 M2) `{!CMRAHomomorphism h} (f : A M1) X :
X h ([ set] x X, f x) ([ set] x X, h (f x)).
Proof.
intros. induction X as [|x X ? IH] using collection_ind_L; [done|].
destruct (decide (X = )) as [->|].
- by rewrite !big_opS_insert // !big_opS_empty !right_id.
- by rewrite !big_opS_insert // cmra_homomorphism -IH //.
Qed.
Lemma big_opL_commute_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2} {A}
(h : M1 M2) `{!UCMRAHomomorphism h} (f : nat A M1) l :
h ([ list] kx l, f k x) = ([ list] kx l, h (f k x)).
Proof. unfold_leibniz. by apply big_opL_commute. Qed.
Lemma big_opL_commute1_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2} {A}
(h : M1 M2) `{!CMRAHomomorphism h} (f : nat A M1) l :
l [] h ([ list] kx l, f k x) = ([ list] kx l, h (f k x)).
Proof. unfold_leibniz. by apply big_opL_commute1. Qed.
Lemma big_opM_commute_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2, Countable K} {A}
(h : M1 M2) `{!UCMRAHomomorphism h} (f : K A M1) m :
h ([ map] kx m, f k x) = ([ map] kx m, h (f k x)).
Proof. unfold_leibniz. by apply big_opM_commute. Qed.
Lemma big_opM_commute1_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2, Countable K} {A}
(h : M1 M2) `{!CMRAHomomorphism h} (f : K A M1) m :
m h ([ map] kx m, f k x) = ([ map] kx m, h (f k x)).
Proof. unfold_leibniz. by apply big_opM_commute1. Qed.
Lemma big_opS_commute_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2, Countable A}
(h : M1 M2) `{!UCMRAHomomorphism h} (f : A M1) X :
h ([ set] x X, f x) = ([ set] x X, h (f x)).
Proof. unfold_leibniz. by apply big_opS_commute. Qed.
Lemma big_opS_commute1_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2, Countable A}
(h : M1 M2) `{!CMRAHomomorphism h} (f : A M1) X :
X h ([ set] x X, f x) = ([ set] x X, h (f x)).
Proof. intros. rewrite <-leibniz_equiv_iff. by apply big_opS_commute1. Qed.
From iris.algebra Require Export cmra.
From iris.algebra Require Import cmra_big_op.
(** * Simple solver for validity and inclusion by reflection *)
Module ra_reflection. Section ra_reflection.
Context {A : ucmraT}.
Inductive expr :=
| EVar : nat expr
| EEmpty : expr
| EOp : expr expr expr.
Fixpoint eval (Σ : list A) (e : expr) : A :=
match e with
| EVar n => from_option id (Σ !! n)
| EEmpty =>
| EOp e1 e2 => eval Σ e1 eval Σ e2
end.
Fixpoint flatten (e : expr) : list nat :=
match e with
| EVar n => [n]
| EEmpty => []
| EOp e1 e2 => flatten e1 ++ flatten e2
end.
Lemma eval_flatten Σ e :
eval Σ e big_op ((λ n, from_option id (Σ !! n)) <$> flatten e).
Proof.
induction e as [| |e1 IH1 e2 IH2]; rewrite /= ?right_id //.
by rewrite fmap_app IH1 IH2 big_op_app.
Qed.
Lemma flatten_correct Σ e1 e2 :
flatten e1 `contains` flatten e2 eval Σ e1 eval Σ e2.
Proof.
by intros He; rewrite !eval_flatten; apply big_op_contains; rewrite ->He.
Qed.
Class Quote (Σ1 Σ2 : list A) (l : A) (e : expr) := {}.
Global Instance quote_empty: Quote E1 E1 EEmpty.
Global Instance quote_var Σ1 Σ2 e i:
rlist.QuoteLookup Σ1 Σ2 e i Quote Σ1 Σ2 e (EVar i) | 1000.
Global Instance quote_app Σ1 Σ2 Σ3 x1 x2 e1 e2 :
Quote Σ1 Σ2 x1 e1 Quote Σ2 Σ3 x2 e2 Quote Σ1 Σ3 (x1 x2) (EOp e1 e2).
End ra_reflection.
Ltac quote :=
match goal with
| |- @included _ _ _ ?x ?y =>
lazymatch type of (_ : Quote [] _ x _) with Quote _ ?Σ2 _ ?e1 =>
lazymatch type of (_ : Quote Σ2 _ y _) with Quote _ ?Σ3 _ ?e2 =>
change (eval Σ3 e1 eval Σ3 e2)
end end
end.
End ra_reflection.
Ltac solve_included :=
ra_reflection.quote;
apply ra_reflection.flatten_correct, (bool_decide_unpack _);
vm_compute; apply I.
Ltac solve_validN :=
match goal with
| H : {?n} ?y |- {?n'} ?x =>
let Hn := fresh in let Hx := fresh in
assert (n' n) as Hn by omega;
assert (x y) as Hx by solve_included;
eapply cmra_validN_le, Hn; eapply cmra_validN_included, Hx; apply H
end.