Nola is a framework for later-free higher-order ghost state, enabling termination verification in the presence of advanced features such as Rust's ownership types.
It is fully mechanized in Rocq (formerly known as Coq) as a library of the Iris separation logic framework.
The name Nola comes from 'No later' and the nickname for New Orleans, Louisiana, USA, in memory of POPL 2020 held in that city.
- Yusuke Matsushita and Takeshi Tsukada. Nola: Later-Free Ghost State for
Verifying Termination in Iris.
ACM PLDI 2025. June 2025.- Yusuke Matsushita and Takeshi Tsukada. Artifact for "Nola: Later-Free Ghost State for Verifying Termination in Iris". Zenodo. 2025. https://doi.org/10.5281/zenodo.15050271
- Yusuke Matsushita. Non-Step-Indexed Separation Logic with Invariants and
Rust-Style Borrows.
Ph.D. Dissertation, University of Tokyo. Dec 6, 2023. Paper, Talk slides.- Yusuke Matsushita. Non-Step-Indexed Separation Logic with Invariants and
Rust-Style Borrows.
Bulletin of Ph.D. Dissertations in AY 2023 Recommended by SIGs, Information Processing Society of Japan. Aug 15, 2024. HTML (Japanese).
- Yusuke Matsushita. Non-Step-Indexed Separation Logic with Invariants and
Rust-Style Borrows.
Now we explain how to get started.
We use opam ver 2.*
for package management. To
install opam, you can refer to
the official installation guide.
To create a new opam switch
named for_nola
(you can choose any name), run:
opam switch create for_nola 4.14.2 # Choose any OCaml version you like
To activate the opam switch for_nola
just globally, run:
opam switch set for_nola
Or, to activate the opam switch for_nola
locally in the directory NOLA_DIR
where this README.md
is located, run:
opam switch link for_nola NOLA_DIR
To enable installing a development version of Iris for the active opam switch, run:
opam repo add iris-dev https://gitlab.mpi-sws.org/iris/opam.git
First, go to the directory NOLA_DIR
where this README.md
is located:
cd NOLA_DIR
To fix the development dependencies and install them, run:
make devdep
To build Nola's Rocq code locally, run:
make -j16 # Choose a job number
Or, to install Nola as an opam library, run:
opam install .
To generate and browse a document for Nola's Rocq code, run:
make viewdoc
To check statements of the PLDI 2025 paper, you can refer to the following parts of our Rocq mechanization.
- Paradoxes
- Later-Free Ghost State
- View Shifts and Hoare Triples
- Modular Construction of Formula Syntax
- Magic Derivability
- Examples and RustHalt
- Paradoxes:
nola.bi.paradox
.- Paradoxes of the naive later-free invariant.
- For the program logic based on Landin's knot:
inv_landin
. - Purely logically for view shifts:
inv_vs
.
- For the program logic based on Landin's knot:
- Paradox of the step-indexed total Hoare triple:
twp
. - Paradoxes of unbounded later weakening.
- Under finite step-indexing:
exist_laterN
. - Under transfinite step-indexing:
exist_laterOrd
.
- Under finite step-indexing:
- Paradoxes of the naive later-free invariant.
All the proof rules are proved to be sound with respect to the semantic model.
- Nola's later-free invariant:
nola.iris.inv
.- INV-PERSIST:
inv_tok_persistent
, INV-ALLOC:inv_tok_alloc
, INV-ACC:inv_tok_acc_vs
, THOARE-INV:inv_tok_acc_twp
, WINV-CREATE:inv_wsat_alloc
.
- INV-PERSIST:
- Nola's later-free borrow.
- Lifetime:
nola.iris.lft
- LFT-ALLOC:
lft_alloc
, LFT-END:lft_end
.
- LFT-ALLOC:
- Borrow:
nola.iris.borrow
- BOR-LEND-NEW:
bor_lend_tok_new
, LEND-BACK:lend_tok_retrieve
, BOR-OPEN:bor_tok_open
, OBOR-CLOSE:obor_tok_close
, WBOR-CREATE:borrow_wsat_alloc
.
- BOR-LEND-NEW:
- Prophetic borrow:
nola.iris.pborrow
- Lifetime:
- Parameterized view shifts:
nola.iris.modw
.- VS-EXPAND:
vsw-expand
.
- VS-EXPAND:
- Parameterized Hoare triples:
nola.iris.wpw
.- VS-THOARE:
vsw-thoarew
, THOARE-VS:thoarew-vsw
, THOARE-EXPAND:thoarew-expand
.
- VS-THOARE:
- Extended HeapLang:
nola.heap_lang
.- Adequacy of the total Hoare triple:
total_adequacy.heap_total
.
- Adequacy of the total Hoare triple:
- Extended λRust, RustBelt's core language:
nola.lrust
.- Adequacy of the total Hoare triple:
adequacy.lrust_total
.
- Adequacy of the total Hoare triple:
- Modular construction of formula syntax:
nola.iris.cif
.
- Magic derivability:
nola.bi.deriv
.- DER-SOUND:
der_sound
, DER-DERIV:der_Deriv
, DERIV-MAP:Deriv_mapl
.
- DER-SOUND:
- Demonstration of how our program logic can emulate CFML:
nola.examples.cfml
. - Basic examples:
nola.examples.basic
.- Loop decrementing the value of a location:
twp_decr_loop
, With non-deterministic initialization:twp_decr_loop_nd
.
- Loop decrementing the value of a location:
- Examples of shared mutable infinite lists:
nola.examples.ilist
.- Verifying tail access:
twp_tail_list
. - Verifying iterc:
twp_iter_ilist
, Verifying two threads running iterc:twp_fork2_iter_ilist
, Verifying iterc for the multiple-of-three invariant:twp_iter_ilist_add3_mul3
. - Verifying iterc2, with two counters under the lexicographic order:
twp_iter2_ilist
. - Verifying iteration using any step function under any well-founded relation:
twp_iterst_ilist
, with an instantiation exampletwp_iterst_ilist_step2
.
- Verifying tail access:
- Basic examples for borrows:
nola.examples.borrow
.- Dereference of nested mutable borrows:
bor_bor_deref
. - Load from an immutable shared borrow over an integer:
imbor_load
.
- Dereference of nested mutable borrows:
- Mutex examples for borrows:
nola.examples.mutex
.- Acquiring a lock via a shared borrow of a mutex:
mutex_bor_try_acquire
, Create a shared borrow of a mutex:mutex_bor_lend_new
.
- Acquiring a lock via a shared borrow of a mutex:
- Examples for magic derivability:
nola.examples.deriv
.- Examples of semantic alteration:
inv'_sep_comm
,inv'_inv'_sep_comm
andinv'_bor_lft
. - Access via a view shift
invd_acc_vs
, Access via a total Hoare tripleinvd_acc_thoare
, Allocationinv'_alloc
, General rule for semantic alteration:inv'_iff'
.
- Examples of semantic alteration:
- RustHalt:
nola.examples.rust_halt
.- INT-ADD:
num.type_add_int
, BOX-MUT-BORROW:ptrs_more.sub_borrow_box
, MUT-REF-WRITE:mutref.write_mutref
, MUT-REF-SHARE:ptrs_more.type_share
, FN-REC-CALL:core.type_call
, REAL:core.type_real
. - Borrow subdivision:
prod_more.sub_mutref_prod_split
,sum_more.type_case_sum_mutref
etc., Reborrowing:ptrs_more.sub_reborrow
,ptrs_more.type_deref_mutref_mutref
etc. - Verification examples:
verify
.- Verifying mutation of a list:
list_more.type_iter_list_mut_fun
. - Verifying mutation of a rich list over a mutable reference:
mutlist_more.type_iter_mutlist_mut_fun
.
- Verifying mutation of a list:
- Adequacy:
adequacy
.
- INT-ADD:
The Rocq code is all in nola/
and is structured as follows:
prelude
: Preludeutil/
: General-purpose utilities, extending std++eq
(Equality),uip
(UIP)fn
(Functions),gmap
(Ongmap
),gmultiset
(Ongmultiset
)prod
(Modified product),bin
(Binary tree),plist
(Product list),tagged
(Tagged type)proph
(Prophecy)order
(Order theory),psg
(Pseudo-gfp)wf
(Well-foundedness)productive
(Productivity)nary
(N-ary maps),cit
(Coinductive-inductive tree)
bi/
: Libraries for bunched implication logiciris/
: Libraries for Iris base logiciprop
(Utility foriProp
),own
(Utility forown
)list
(On lists),option
(Onoption
),agree
(Onagree
),csum
(Oncsum
)sinv
(Simple invariants)inv
(Invariants),inv_deriv
(Invariants relaxed with derivability),na_inv
(Non-atomic invariants),na_inv_deriv
(Non-atomic invariants relaxed with derivability)dinv
(Direct invariants),dinv_deriv
(Direct invariants relaxed with derivability),store
(Stored propositions),store_deriv
(Stored propositions relaxed with derivability)lft
(Lifetime),borrow
(Borrows),borrow_deriv
(Borrows relaxed with derivability),fborrow
(Fractured borrows)proph
(Prophecy),proph_ag
(Prophetic agreement),pborrow
(Prophetic borrows),pborrow_deriv
(Prophetic borrows relaxed with derivability)cif
(Modular construction of coinductive-inductive formulas)paradox
(Paradox)
heap_lang/
: Variant of Iris HeapLang, supporting program logic with custom world satisfactions for Nolalocations
(On locations)lang
(Language),pretty
(Pretty printing for the language),notation
(Notation for the language),tactics
(Tactics for the language)metatheory
(Metatheory on the language),proph_erasure
(Prophecy erasure theorem for the language)class_instances
(Class instances for the program logic),definitions
(Definitions for the program logic),primitive_laws
(Primitive laws of the program logic),derived_laws
(Derived laws of the program logic),proofmode
(Proof mode utility for the program logic)adequacy
(Safety adequacy of the program logic),total_adequacy
(Termination adequacy of the program logic)
lrust/
: Variant of λRust, RustBelt's core language, supporting program logic with custom world satisfactions for Nolaexamples/
: Examplesxty
(Syntactic type),con
(Constructors)cfml
(Demonstration of how our program logic can emulate CFML),basic
(Basic examples),ilist
(Infinite list),borrow
(Borrow),mutex
(Mutex),deriv
(Derivability)rust_halt/
: RustHalt, a semantic foundation for total correctness verification of Rust programsbase
(Basics),type
(Type model)core
(Core features)num
(Numeric types),uninit
(Uninitialized data type)prod
(Product type),sum
(Sum type)rec
(Recursive type),mod
(Modification type)ptr
(Utility for pointer types),box
(Box pointer type),shrref
(Shared reference type),mutref
(Mutable reference type)ptrs_more
(More on basic pointer types),prod_more
(More on the product type),sum_more
(More on the sum type)adequacy
(Adequacy)verify/
: Verification examples