Skip to content

Appendix B: Coming From Viper, Dafny, or Iris

A quick dictionary, not a full comparison — if you already know one of these tools, this is meant to shortcut your intuition to the nearest Raven concept.

From Viper

Viper's own field/heap model is exactly the same as Raven's — a field access is a permission plus a value, and fractional permissions work identically in both. What Raven adds on top is ghost fields: fields whose values come from a user-definable resource algebra rather than a plain type, which is what everything from Part 4 onward is built on.

ViperRavenNote
acc(x.f)own(x.f, v)Raven's own names the value too, not just the permission.
acc(x.f, perc)own(x.f, v, q)Same fractional-permission model.
(no direct equivalent)own(x.g, a), g a ghost fielda here is an element of whatever user-definable resource algebra g's declared type names (Part 4) — a fact about proof-only state with its own composition rule, not just a permission on an ordinary value. Viper has no ghost fields and no notion of a resource algebra at all; this is the other half of what Raven adds on top of Viper's own field/heap model.
predicate, fold/unfoldpred, fold/unfoldDirectly analogous.
(no direct equivalent)invViper has no built-in shared-invariant concept — front-ends targeting Viper that need concurrency encode it themselves on top. This is Raven's central addition.
macrosauto predAutomatically inlined, no fold/unfold.
inhale/exhaleinhale/exhaleSame ghost statements, same role — Raven's own compilation pipeline reduces everything else down to exactly these two, the same way Viper's does.
domainADTs (data), or the module systemA Viper domain is closest to a restricted interface: a rep type plus axioms characterizing it, but no functors, no implementations, no functor composition. For a simple algebraic sum type, Raven's data is the direct match; for anything with more structure (a domain used to axiomatize a whole data structure), Raven's module system is the more general — and more capable — analogue.
quantified permissionsiterated separating conjunctions (Part 5c)Raven's ISC design is explicitly built on Viper's, generalized to arbitrary resource algebras rather than just permissions.
magic wand (A --* B)(not currently supported)A magic wand asserts "give up A and you get B back" — handy for partially unfolding a recursive predicate (walk partway into a linked list, leave a wand behind that remembers how to fold it back up once you're done with the part you unfolded) without committing to the whole structure at once. Raven has no equivalent construct yet; the same traversals are instead written by carrying the "rest of the structure" explicitly as a separate resource, which is more verbose but doesn't need anything new.
decreases e1, ..., endecreases e1, ..., enSame contract syntax, same lexicographic-tuple concept — but Viper has no equivalent of Raven's user-definable WellFoundedOrder instances (Part 3).
no built-in concurrencyinvariants, ghost fields/RAs, atomic contracts, prophecy variablesThe actual gap Raven is designed to fill; see the Part 4/5 story in this tutorial, and Appendix D for prophecies specifically.

One deeper design difference, worth knowing about even though it rarely surfaces day to day: Viper is built on implicit dynamic frames, a close cousin of separation logic where expressions — in both programs and specifications — can be heap-dependent. Raven instead keeps expressions pure everywhere; a heap read is always a statement (val x := e.f;), never buried inside a larger expression. That restriction is what lets Raven treat evaluating an expression as happening in one atomic step, no matter how many sub-terms it has — no other thread can observe or interfere with it partway through, by a Lipton-style reduction argument — and Raven gets that reasoning for free, rather than as something a concurrency proof has to establish itself. It's a real part of why Raven's pure-expression design is a better fit for concurrency than Viper's.

From Dafny

DafnyRavenNote
method/functionproc/funcSame split: side-effecting vs. pure-and-spec-usable.
requires/ensuresrequires/ensuresSame.
loop invariantloop invariantSame concept — but Raven also has a completely different, unrelated use of the word invariant for shared concurrent state (inv); don't conflate the two just because Dafny only needs the first.
decreasesdecreasesSame role, for recursive func/lemma termination — see Part 1 §4.
classes, thisheap-allocated objects via field/Ref, no implicit thisDafny's memory model already assumes ownership tracking under the hood; Raven makes ownership the explicit thing you reason about, which is the entire subject of Part 2.
datatypedataSame idea, algebraic sum types.
modifies(implicit, via own)The deeper difference, not just a syntax swap: Dafny is classical Hoare logic — there's no notion of a "heap resource," or any resource at all. Frame conditions have to be stated explicitly, by hand, via modifies; Raven's ownership model (Part 2) makes framing a consequence of what you own, rather than something you separately declare.
no built-in concurrencyinvariants, ghost fields/RAs, atomic contractsDafny is sequential-only; this is the single biggest thing to unlearn coming from it — see Part 4's "why this matters for concurrency" callouts throughout Parts 1–3.
compiles to executable code(no compilation backend)Dafny compiles verified programs to real executables (C#, Java, Go, Python, JS, take your pick). Raven, as of this writing, is purely a verification language — there's no backend that turns a verified .rav file into something you run; the point is checking a design or an algorithm's correctness, not producing a deployable artifact from it.

From Iris

If you know Iris, you already know the ideas behind Parts 2–5 — ownership, invariants, resource algebras (Iris's cameras, restricted here to Iris's simpler, non-step-indexed unital-RA fragment), atomic triples. What Raven adds is automation: everything you'd build by hand in the Iris Proof Mode inside Rocq is instead compiled down to a first-order SMT query and discharged by Z3. Concretely:

IrisRaven
Invariant Inv N Pinv
A cameraA resource algebra implementing Library.ResourceAlgebra (Appendix A) — deliberately the non-step-indexed, non-higher-order fragment of Iris's cameras, since that's what stays SMT-automatable.
Atomic triple << P >> e << v, Q >>atomic requires/atomic ensures (Part 5b)
Ghost state ownership own γ aghost field, own(e.g, v)
Frame-preserving updatefpu
View shift / mask-aware invariant openingRaven's atomicity analysis, checked automatically rather than proved by hand each time

The trade-off, honestly: Raven's fragment is deliberately less expressive than full Iris — no impredicative invariants, no step-indexing, no higher-order ghost state. That's what makes it automatable; landmark, foundational proofs like RustBelt still need full Iris in Rocq. Raven is aimed at the more common case of everyday concurrent data structure proofs that don't.