Papers
Topics
Authors
Recent
Search
2000 character limit reached

RustyDL: Source-Level Logic for Rust

Updated 5 July 2026
  • RustyDL is a program logic for safe Rust that supports human-in-the-loop deductive verification by reasoning directly over Rust source code and its semantics.
  • It extends dynamic logic with modalities to model Rust-specific features such as ownership, borrowing, mutable references, and control flow without intermediate translations.
  • RustyDL’s source-level approach enables clear, inspectable proof states that align intimately with Rust syntax, facilitating effective debugging of verification failures.

Searching arXiv for the named topic and closely related Rust research to ground the article in current papers. RustyDL is a program logic for Rust that is designed as a source-level foundation for auto-interactive, human-in-the-loop deductive verification. It reasons about Rust programs directly on the source code level, rather than through translation to an intermediate verification language, and is presented as the core of a prototype Rust instance of the KeY verification system (Drodt et al., 25 Feb 2026). Within its current scope, RustyDL targets a substantial subset of safe Rust, including primitive values, arrays, shared and mutable references, loops, and function calls, and develops explicit logical machinery for Rust-specific phenomena such as ownership transfer, borrowing, and mutation through &mut references (Drodt et al., 25 Feb 2026).

1. Intellectual setting and verification objective

RustyDL emerges from a line of research that treats Rust’s ownership discipline as a first-class semantic object rather than as a compilation artifact. Earlier source-oriented semantics such as Oxide modeled ownership and borrowing without the details of lifetime analysis and organized Rust as a family of languages of increasing expressive power (Weiss et al., 2018). RustyDL moves from source-level semantics to source-level program logic: its purpose is not merely to explain Rust, but to support deductive proofs over Rust source programs in a human-in-the-loop style (Drodt et al., 25 Feb 2026).

Its central motivation is methodological. Translation-based Rust verifiers typically compile Rust into an intermediate verification language and then rely on VC generation and SMT solving. RustyDL instead treats direct reasoning over Rust source as crucial for highly complex functional verification, because source-level proof states remain legible in terms of Rust constructs such as if, loops, borrowing, moves, and array indexing (Drodt et al., 25 Feb 2026). This suggests a verification workflow in which failed proofs are debugged at the level of Rust source rather than at the level of an intermediate encoding.

The logic is explicitly restricted to safe Rust. unsafe blocks are not modeled as part of the proof system’s current trusted core; rather, they are assumed to be encapsulated and verified separately (Drodt et al., 25 Feb 2026). This boundary is consistent with broader verification practice in Rust, where UB-oriented tools and larger library-verification campaigns often treat unsafe code as a specialized target requiring different machinery (Cook et al., 16 Jun 2026).

2. Dynamic-logic foundation

RustyDL is based on dynamic logic, extending typed first-order logic with modalities that internalize program execution into formulas (Drodt et al., 25 Feb 2026). The two central modalities are the box modality for partial correctness and the diamond modality for total correctness: $\dlbox{p}\,\phi$ and

$\dia{p}\,\phi .$

The intended reading is standard. The box modality states that either program fragment pp does not terminate normally, or, if it does terminate normally, the resulting state satisfies ϕ\phi. The diamond modality states that pp terminates normally and the resulting state satisfies ϕ\phi (Drodt et al., 25 Feb 2026). Hoare-style specifications are represented as implications, for example: $\{\pre\}\ p\ \{\post\} \quad\equiv\quad \pre \rightarrow \dlbox{p}\post .$

Semantically, RustyDL uses a Kripke structure

$\Kstruct = (\States,\rho)$

where $\States$ is a set of first-order structures representing program states, and ρ\rho maps each legal program fragment $\dia{p}\,\phi .$0 to a partial function

$\dia{p}\,\phi .$1

that is defined exactly when $\dia{p}\,\phi .$2 terminates normally (Drodt et al., 25 Feb 2026). This keeps nontermination and abnormal termination inside the modal semantics, while ordinary state changes are handled by updates.

The logic’s sort system is tailored to Rust. It includes $\dia{p}\,\phi .$3 as a top sort, $\dia{p}\,\phi .$4 as a bottom sort, base sorts such as $\dia{p}\,\phi .$5, $\dia{p}\,\phi .$6, and $\dia{p}\,\phi .$7, array sorts $\dia{p}\,\phi .$8, and distinct sorts for shared and mutable references: $\dia{p}\,\phi .$9 It also introduces technical sorts such as pp0 and pp1, which are needed to model indexing and mutable-reference targets (Drodt et al., 25 Feb 2026).

A significant design decision is that integer types are represented as mathematical integers, with Rust-specific range restrictions expressed via predicates such as inU32. This makes arithmetic reasoning classical at the logical level while preserving Rust’s debug-style overflow behavior through explicit case splits that either continue normally or yield panic!() (Drodt et al., 25 Feb 2026).

3. Ownership, moves, and borrowing

RustyDL’s most distinctive contribution lies in its treatment of ownership transfer and references. Rust assignment on non-Copy types is modeled as a move, not a copy. Rather than introducing a special uninitialized value, RustyDL handles moves by anonymizing the source variable with a fresh constant of the same type (Drodt et al., 25 Feb 2026). The rule has the shape

pp2

for fresh pp3, capturing that x receives the old value of y while y can no longer be reasoned about via its previous value.

Shared borrowing is modeled value-theoretically. Creating pp7 is represented by updating x to a shared-reference term: pp4 Dereferencing a shared reference is then reduced by a simplification rule of the form

pp5

This reflects the read-only, aliasable status of &T in safe Rust (Drodt et al., 25 Feb 2026).

Mutable references require a different treatment because they denote places that can be written through. RustyDL introduces the sort pp6 together with place constants and constructors such as pp7 for variables and pp8 for mutable array positions (Drodt et al., 25 Feb 2026). A mutable reference is then represented by

pp9

Thus pp8 becomes

ϕ\phi0

Mutation through a mutable reference is captured by RustyDL’s novel mutating update: ϕ\phi1 Its semantic role is to update the place borrowed by ϕ\phi2 to the value ϕ\phi3 (Drodt et al., 25 Feb 2026). In particular, pp9 is modeled by a mutating update, and when y is known to be of the form ϕ\phi4, a rewrite turns

ϕ\phi5

into the ordinary elementary update

ϕ\phi6

This is the key mechanism by which RustyDL internalizes the operational meaning of writing through &mut without lowering to an intermediate store model (Drodt et al., 25 Feb 2026).

This treatment also supports the state dependence of mutable dereferencing. Shared dereferences can collapse immediately to values, but mutable dereferences must reflect the current lender state, because the borrowed place may have changed since the reference was created (Drodt et al., 25 Feb 2026). The calculus therefore includes dedicated rewrite rules that propagate ordinary updates into dereferences of mutable references.

4. Arrays, arithmetic, and control flow

Arrays are modeled functionally. For each array sort ϕ\phi7, RustyDL provides operations analogous to read and write: ϕ\phi8 and

ϕ\phi9

An index term is translated by

pp0

This yields the expected functional-array behavior for expressions such as successive indexed writes followed by a read (Drodt et al., 25 Feb 2026).

Array access rules are explicit about Rust’s bounds checks. Reading ϕ\phi0 splits on whether pp1 is within pp2: out-of-bounds access leads to panic!(), whereas an in-bounds access produces an update

pp3

Writing ϕ\phi1 similarly splits between panic and a functional-array update using set (Drodt et al., 25 Feb 2026). Mutable borrowing of array elements, ϕ\phi2 combines the place-based model of &mut with the same bounds discipline, yielding a mutable reference to an array place pp4 (Drodt et al., 25 Feb 2026).

Arithmetic is handled in debug semantics. For unsigned 32-bit addition, RustyDL uses a rule that branches on

pp5

If the bound holds, the assignment proceeds normally; otherwise execution follows the panic!() branch (Drodt et al., 25 Feb 2026). This makes overflow part of the explicit proof obligation rather than hidden inside machine arithmetic.

Control flow is treated proof-theoretically. An if expression is handled by branching the sequent into the true and false cases. For simple guards, RustyDL uses a direct split on

pp6

For complex guards, it first normalizes by introducing a temporary variable holding the guard expression, then splits over that variable (Drodt et al., 25 Feb 2026). This keeps symbolic execution close to Rust source structure and avoids premature expansion of complex conditions.

5. Proof calculus and prototype realization

RustyDL is presented as a sequent calculus for source-level Rust verification (Drodt et al., 25 Feb 2026). The calculus combines symbolic execution rules for Rust statements and expressions with logical reasoning in typed first-order dynamic logic. Because proofs are represented explicitly as sequents and proof trees, the system is intended for auto-interactive use rather than purely push-button discharge.

The prototype realization is a Rust instance of KeY, described as “Rusty KeY” (Drodt et al., 25 Feb 2026). This is a proof-of-concept rather than a finished verifier, but it demonstrates the intended architecture: Rust programs are taken at a normalized source representation close to HIR, and proof steps operate directly over Rust constructs. A human verifier can therefore inspect intermediate states that still refer to Rust-level variables, references, arrays, and control-flow structure.

This source-level strategy sharply distinguishes RustyDL from other major Rust verifiers. Tools such as Prusti, Creusot, Aeneas, and Verus are characterized as translation-based: they compile Rust into an intermediate verification language and then rely on VC generation and SMT automation (Drodt et al., 25 Feb 2026). RustyDL instead prioritizes explicit inference steps and source fidelity. A plausible implication is that it is particularly suited to the verification of proofs whose difficulty lies less in discovering loop invariants mechanically than in guiding a large, semantically rich argument over source structure.

The same orientation also clarifies its present limitations. The current logic covers a rich subset of safe Rust, but not unsafe, explicit lifetimes, traits, unions, smart pointers, macros, or async constructs (Drodt et al., 25 Feb 2026). Those omissions are not incidental; they mark precisely the frontier between a source-level proof system already capable of nontrivial functional reasoning and a fuller logic for the whole language.

6. Position within Rust verification research

RustyDL belongs to a broader Rust verification landscape that includes source-level semantics, bounded model checking, refinement types, separation logic, fuzzing, and runtime enforcement. Within that landscape, its closest conceptual predecessor is Oxide, which models ownership and borrowing without the details of lifetime analysis and structures Rust as an expressive tower of languages (Weiss et al., 2018). RustyDL can be read as a move from such semantic distillation toward proof-calculus engineering at the source level.

A different strand of work targets library-scale automated verification. A recent campaign on the Rust standard library integrates Kani, ESBMC, Flux, and VeriFast into continuous integration for core, alloc, and std, focusing primarily on absence of UB and selected functional invariants (Cook et al., 16 Jun 2026). RustyDL addresses a different point in the design space: source-level, human-guided deductive verification of functional properties, rather than repository-scale automated checking over an intermediate representation (Drodt et al., 25 Feb 2026).

Other research addresses problems RustyDL does not yet target. deepSURF detects memory-safety vulnerabilities in unsafe Rust libraries by combining static analysis with LLM-augmented fuzzing harnesses (Androutsopoulos et al., 18 Jun 2025). CapsLock proposes runtime enforcement of ownership, borrowing, and AXM in mixed Rust, FFI, and inline assembly via hardware capabilities and revoke-on-use semantics (Yu et al., 4 Jul 2025). Static deadlock detection for Rust programs uses MIR-based pointer analysis and lock graphs to identify double lock, conflict lock, and condition-variable deadlocks (Zhang et al., 2024). These efforts are complementary rather than competitive: they concern unsafe code, mixed-language execution, or concurrency bugs, whereas RustyDL currently concentrates on safe Rust and deductive functional reasoning (Drodt et al., 25 Feb 2026).

Taken together, this context makes RustyDL significant as a distinct verification paradigm for Rust. It is neither an IR-based VC generator nor a runtime monitor nor a fuzzing framework. It is a source-level program logic whose central thesis is that Rust verification, especially in human-in-the-loop settings, benefits from keeping ownership, borrowing, moves, mutation, and control flow visible all the way through the proof calculus (Drodt et al., 25 Feb 2026).

Topic to Video (Beta)

No one has generated a video about this topic yet.

Whiteboard

No one has generated a whiteboard explanation for this topic yet.

Follow Topic

Get notified by email when new papers are published related to RustyDL.