Iris-Lean

repository·master·Indexed 42 days ago

https://github.com/leanprover-community/iris-lean

A Lean 4 port of Iris, a higher-order concurrent separation logic framework used for reasoning about concurrent programs, logical relations, type-systems, and data-abstraction. It includes a specialized proof mode with tactics (e.g., iintro, isplit), a logic interface via BIBase and BI typeclasses, and a Porting Completeness Checker to track progress against the original Rocq implementation.

Tokens
8.5K
Snippets
20
Records
38
Agent score
53%

What's inside Iris-Lean

  1. What is Iris-Lean?

    master

    Iris-Lean is a Lean 4 port of Iris, a higher-order concurrent separation logic framework. It is used for reasoning about the safety of concurrent programs, logical relations, type-systems, and data-abstraction.

    Currently, the port supports:

    • MoSeL: The proof interface of Iris (supports different separation logics).
    • UPred: The Iris base logic.
    • IProp: The standard model of Iris.
    • A selection of Iris resources, including invariants, later credits, and more.
  2. Project structure of Iris-Lean

    master

    The project is organized into several key directories:

    DirectoryDescription
    BI/Logic interface (Interface.lean, Extensions.lean, Classes.lean), notation, and derived laws.
    Examples/Proof examples and partial logic interface instances.
    Instances/Full instances of the logic interface (e.g., Classical, Data).
    Proofmode/The proof interface, including tactics, typeclasses, and environment/context definitions.
    Proofmode/Patterns/Syntax for patterns used in tactic arguments.
    Proofmode/Tactics/Implementation of complex tactics.
    Std/Standard functionality missing from Lean.
    Tests/Test suites for the framework.
  3. Use the Iris Proof Mode and tactics

    master

    Separation logic proofs are performed in the Iris Proof Mode.

    Entering Proof Mode: Use the istart tactic. Note that most separation logic tactics call istart automatically, so explicit invocation is often unnecessary.

    Tactic State: When in Iris Proof Mode, the Lean tactic state displays two additional contexts beneath the standard Lean context:

    1. Intuitionistic context (denoted by □)
    2. Spatial context (denoted by ∗)

    Tactics: Tactics in this mode follow Lean conventions but are prefixed with i (e.g., iintro, isplit, iexact, ispecialize, icases, iexists).

    theorem proof_example [BI PROP] (P Q R : PROP) (Φ : α → PROP) :
      P ∗ Q ∗ □ R ⊢ □ (R -∗ ∃ x, Φ x) -∗ ∃ x, Φ x ∗ P ∗ Q
    := by
      iintro ⟨HP, HQ, □HR⟩ □HRΦ
      ispecialize HRΦ HR as HΦ
      icases HΦ with ⟨x, HΦ⟩
      iexists x
      isplit r
      · iassumption
      isplit l [HP]
      · iexact HP
      · iexact HQ
  4. How Iris proof modes and contexts work

    master

    The Iris proof mode manages three distinct types of contexts to handle different logical properties:

    1. Pure (Lean) Context: Standard Lean hypotheses.
    2. Intuitionistic Context: Hypotheses prefixed with □. These are usable multiple times (duplicable).
    3. Spatial Context: Hypotheses that are 'owned'. They can be used only once and are subject to separation logic rules (e.g., splitting and framing).

    Understanding these boundaries is essential for choosing the correct tactics for context management and goal solving.

  5. Distinguish between Lean and Iris hypotheses in naming

    master

    When working in proof mode, distinguish between ambient Lean local contexts and the Iris hypothesis context managed by IPM using capitalization:

    • Pure Lean hypotheses: Use lowercase (e.g., h, h1, hP, hpq, hAcc).
    • Iris hypotheses: Use uppercase (e.g., H, H1, HP, Hinv, Hclose, Hα).
  6. Understand Proof Mode Terms (pmTerm)

    master

    A Proof Mode Term (pmTerm) is a construction used to specialize premises of a hypothesis or Lean term. It follows the syntax:

    H $$ specPat₁ ... specPatₙ

    Where H is a hypothesis or a Lean term whose conclusion is an entailment, and specPatᵢ are specialization patterns applied to its premises. This allows for fine-grained control over how premises of wands or universal quantifiers are satisfied.

    -- Examples of pmTerm usage:
    iapply (wand_trans HPQ)        -- Lean term as pmTerm
    ispecialize HPQ $$ %x HP [HQ]  -- instantiate ∀ with x, use HP, prove premise from HQ
    imod (own_update ... $$ Hown)  -- specialize and eliminate the update modality
  7. How the Porting Completeness Checker works

    master

    The tool operates in three main stages:

    1. Lean Data Extraction: Running lake exe dumpPortingData scans the compiled Lean environment and writes a JSON file (default .lake/porting_data.json) containing all @[rocq_alias] mappings, #rocq_ignore entries, #rocq_ignore_file entries, and #rocq_concept entries.
    2. Rocq Data Acquisition: The script downloads the Iris-Rocq source tarball at the revision specified in scripts/ROCQ_REVISION, parses .v files for definition names, and caches them in --cache-dir.
    3. Comparison (Diff): Definitions are classified as:
      • ported: Has a matching @[rocq_alias] in Lean.
      • ignored: Listed via #rocq_ignore, #rocq_ignore_file, or in a package's ignoredDirs.
      • missing: No alias or ignore entry found.
      • stale_alias / stale_ignore: Lean-side aliases or ignores that point to Rocq targets that no longer exist upstream.
  8. Handling bidirectional entailment with Setoids

    master

    The project uses bidirectional entailment ⊣⊢ to represent equivalence ≡ between separation logic propositions. Because Lean does not support rewriting with equivalences, ⊣⊢ is defined as equality = in the implementation.

    If your separation logic requires this, you may need to use a quotient type with a Setoid instance when instantiating the separation logic interface. Note that this approach limits the interface to logics with a non-parameterized equivalence and is not suitable for logics like Iris that use an Ordered Family of Equivalences (OFE).

    instance myPropSetoid : Setoid MyProp where
      r P Q := ...
      iseqv := { ... }
    
    instance : BI (Quotient myPropSetoid) where
      ...
  9. Organize modules and entry points

    master

    Iris-Lean requires a specific directory structure for module organization:

    1. Entry Point Modules: Every directory Foo/ must have a corresponding module Foo.lean acting as its entry point (e.g., Iris/BI/BigOp/ must have Iris/BI/BigOp.lean).
    2. Transitive Imports: The entry-point module must transitively import every module within its directory. For example, Iris/ProofMode.lean must be able to reach Iris/ProofMode/Tactics/Frame.lean through its hierarchy.
    3. Exceptions: Directories named Iris/*/Lib (specifically Iris.Algebra.Lib, Iris.BI.Lib, Iris.HeapLang.Lib, and Iris.Instances.Lib) are exempt; their entry points are not imported by their parents.
    4. Iris.Init: Every module must import Iris.Init (directly or transitively) to ensure a consistent environment (options, notation, etc.). New leaf modules that import nothing from the project must add import Iris.Init explicitly.
  10. Quick Start: Generate a Porting Completeness Report

    master

    To compare Iris-Rocq definitions against Iris-Lean's @[rocq_alias] annotations and track porting progress, run the check_porting.py script. By default, it builds Lean, downloads the necessary Rocq source, and generates an HTML report.

    python3 scripts/check_porting.py --format html -o report.html
    python3 scripts/check_porting.py --format html -o report.html
  11. Use Rocq prefixes for aliases and ignores in Lean

    master

    To avoid name collisions between different Rocq packages, use a package prefix when declaring aliases or ignores in Lean. Each package has a unique prefix (except for the iris package, which uses an unprefixed namespace).

    Example usage of prefixes:

    @[rocq_alias heap_lang.pointsto] theorem pointsTo ...
    #rocq_ignore heap_lang.pretty_int "Rocq-specific pretty printing"
    
    #rocq_ignore_file heap_lang.lib "diverge.v" "Not needed"
  12. How to use the Iris-Lean Proofmode

    master

    Using the separation logic framework involves four main steps:

    1. Instantiate the separation logic interface: Provide instances for the BIBase and BI typeclasses. BIBase defines operators (entailment, conjunction, etc.), while BI provides proofs for axioms. You can instantiate BI directly to provide both.
    2. Add custom notation (optional): Define new syntax for your logic using syntax and macro_rules. Note that logic syntax must be wrapped in iprop quotations to distinguish it from Lean propositions.
    3. Instantiate existing typeclasses (optional): Provide instances for properties like Affine for custom constructs or logic-wide properties using typeclasses like BIAffine.
    4. Write proofs: Use the istart tactic to enter the Iris Proof Mode, where you can use separation logic-specific tactics (e.g., iintro, isplit, iexact).
    -- 1. Instantiate the interface
    instance : BIBase (HeapProp Val) where
      entails P Q := ∀ σ, P σ → Q σ
      emp         := fun σ => σ = ∅
      and P Q     := fun σ => P σ ∧ Q σ
      sep P Q     := fun σ => ∃ σ1 σ2 , σ = σ1 ∪ σ2 ∧ σ1 || σ2 ∧ P σ1 ∧ Q σ2
      ...
    
    instance : BI (HeapProp Val) where
      entails_preorder := { ... }
      and_elim_l       := by ...
      ...
    
    -- 4. Write a proof
    theorem proof_example [BI PROP] (P Q R : PROP) (Φ : α → PROP) :
      P ∗ Q ∗ □ R ⊢ □ (R -∗ ∃ x, Φ x) -∗ ∃ x, Φ x ∗ P ∗ Q
    := by
      iintro ⟨HP, HQ, □HR⟩ □HRΦ
      ispecialize HRΦ HR as HΦ
      icases HΦ with ⟨x, HΦ⟩
      iexists x
      isplit r
      · iassumption
      isplit l [HP]
      · iexact HP
      · iexact HQ