Dafny is an
imperative and
functional compiled language
Compiled language categorizes a programming language as used with a compiler and generally implies not used with an interpreter. But, since any language can theoretically be compiled or interpreted the term lacks clarity. In practice, for some lan ...
that compiles to other
programming language
A programming language is a system of notation for writing computer programs.
Programming languages are described in terms of their Syntax (programming languages), syntax (form) and semantics (computer science), semantics (meaning), usually def ...
s, such as
C#,
Java
Java is one of the Greater Sunda Islands in Indonesia. It is bordered by the Indian Ocean to the south and the Java Sea (a part of Pacific Ocean) to the north. With a population of 156.9 million people (including Madura) in mid 2024, proje ...
,
JavaScript
JavaScript (), often abbreviated as JS, is a programming language and core technology of the World Wide Web, alongside HTML and CSS. Ninety-nine percent of websites use JavaScript on the client side for webpage behavior.
Web browsers have ...
,
Go, and
Python. It supports
formal specification
In computer science, formal specifications are mathematically based techniques whose purpose is to help with the implementation of systems and software. They are used to describe a system, to analyze its behavior, and to aid in its design by verify ...
through
preconditions,
postconditions,
loop invariant
In computer science, a loop invariant is a property of a program loop that is true before (and after) each iteration. It is a logical assertion, sometimes checked with a code assertion. Knowing its invariant(s) is essential in understanding th ...
s,
loop variants, termination specifications and read/write framing specifications. The language combines ideas from the
functional programming
In computer science, functional programming is a programming paradigm where programs are constructed by Function application, applying and Function composition (computer science), composing Function (computer science), functions. It is a declarat ...
and
imperative programming
In computer science, imperative programming is a programming paradigm of software that uses Statement (computer science), statements that change a program's state (computer science), state. In much the same way that the imperative mood in natural ...
paradigms; it includes support for
object-oriented programming
Object-oriented programming (OOP) is a programming paradigm based on the concept of '' objects''. Objects can contain data (called fields, attributes or properties) and have actions they can perform (called procedures or methods and impl ...
. Features include ''generic classes'', ''dynamic allocation'', ''inductive datatypes'' and a variation of
separation logic
In computer science, separation logic is an extension of Hoare logic, a way of reasoning about programs.
It was developed by John C. Reynolds, Peter O'Hearn, Samin Ishtiaq and Hongseok Yang, drawing upon early work by Rod Burstall. The assertio ...
known as ''implicit dynamic frames'' for reasoning about side effects. Dafny was created by Rustan Leino at
Microsoft Research
Microsoft Research (MSR) is the research subsidiary of Microsoft. It was created in 1991 by Richard Rashid, Bill Gates and Nathan Myhrvold with the intent to advance state-of-the-art computing and solve difficult world problems through technologi ...
after his prior work on developing ESC/
Modula-3
Modula-3 is a programming language conceived as a successor to an upgraded version of Modula-2 known as Modula-2+. It has been influential in research circles (influencing the designs of languages such as Java, C#, Python and Nim), but it ha ...
,
ESC/Java, and Spec#.
Dafny is regularly featured in software verification competitions (e.g. VSTTE'08, VSCOMP'10, COST'11, and VerifyThis'12).
Dafny was designed as a verification-aware programming language, requiring verification along with code development. It thus fits the ''
Correct by Construction'' software development paradigm. Verification proofs are supported by a mathematical toolbox that includes mathematical integers and reals, bit-vectors, sequences, sets, multisets, infinite sequences and sets, induction, co-induction, and calculational proofs. Verification obligations are discharged automatically, given sufficient specification. Dafny uses some program analysis to infer many specification assertions, reducing the burden on the user of writing specifications. The general proof framework is that of
Hoare logic
Hoare logic (also known as Floyd–Hoare logic or Hoare rules) is a formal system with a set of logical rules for reasoning rigorously about the correctness of computer programs. It was proposed in 1969 by the British computer scientist and l ...
.
Dafny builds on the Boogie
intermediate language
An intermediate representation (IR) is the data structure or code used internally by a compiler or virtual machine to represent source code. An IR is designed to be conducive to further processing, such as optimization and translation. A "good" ...
which uses the
Z3 automated theorem prover for discharging proof obligations.
Data types
Dafny provides methods for implementation which may have
side-effects
In medicine, a side effect is an effect of the use of a medicinal drug or other treatment, usually adverse but sometimes beneficial, that is unintended. Herbal and traditional medicines also have side effects.
A drug or procedure usually used ...
and functions for use in specification which are
pure.
Methods consist of sequences of statements following a familiar imperative style whilst, in contrast, the body of a function is simply an expression. Any side-effecting statements in a method (e.g. assigning an element of an array parameter) must be accounted for by noting which parameters can be mutated, using the
modifies
clause. Dafny also provides a range of ''immutable'' collection types including: sequences (e.g.
seq<int>
), sets (e.g.
set<int>
), maps (
map<int,int>
), tuples, inductive datatypes and ''mutable'' arrays (e.g.
array<int>
).
Imperative features
The following illustrates many of the features in Dafny, including the use of preconditions, postconditions, loop invariants and loop variants.
method max(arr:array) returns (max:int)
// Array must have at least one element
requires arr.Length > 0
// Return cannot be smaller than any element in array
ensures forall j : int :: j >= 0 && j < arr.Length > max >= arr // Return must match some element in array
ensures exists j : int :: j>=0 && j < arr.Length && max arr
This example computes the maximum element of an array. The method's precondition and postcondition are given with the
requires
and
ensures
clauses (respectively). Likewise, the loop invariant and loop variant are given through the
invariant
and
decreases
clauses (respectively).
Loop invariants
The treatment of loop invariants in Dafny differs from traditional
Hoare logic
Hoare logic (also known as Floyd–Hoare logic or Hoare rules) is a formal system with a set of logical rules for reasoning rigorously about the correctness of computer programs. It was proposed in 1969 by the British computer scientist and l ...
. Variables mutated in a loop are treated such that (most) information known about them before the loop is discarded. Information required to prove properties of such variables must be expressed explicitly in the loop invariant. In contrast, variables not mutated in the loop retain all information known about them beforehand. The following example illustrates using loops:
method sumAndZero(arr: array) returns (sum: nat)
requires forall i :: 0 <= i < arr.Length > arr >= 0
modifies arr
This fails verification because Dafny cannot establish that
(sum + arr >= 0
holds at the assignment. From the precondition, intuitively,
forall i :: 0 <= i < arr.Length > arr >= 0
holds in the loop since
arr := arr
is a
NOP. However, this assignment causes Dafny to treat
arr
as a mutable variable and drop information known about it from before the loop. To verify this program in Dafny we can either (a) remove the redundant assignment
arr := arr
; or (b) add the loop invariant
invariant forall i :: 0 <= i < arr.Length > arr >= 0
Dafny also employs limited
static program analysis
In computer science, static program analysis (also known as static analysis or static simulation) is the analysis of computer programs performed without executing them, in contrast with dynamic program analysis, which is performed on programs duri ...
to infer simple loop invariants where possible. In the example above, it would seem that the loop invariant
invariant i >= 0
is also required as variable
i
is mutated within the loop. Whilst the underlying logic requires such an invariant, Dafny infers this automatically, and hence, it can be omitted at the source level.
Proof features
Dafny includes features which further support its use as a
proof assistant
In computer science and mathematical logic, a proof assistant or interactive theorem prover is a software tool to assist with the development of formal proofs by human–machine collaboration. This involves some sort of interactive proof edi ...
. Although proofs of simple properties within a
function
or
method
(as shown above) are not unusual for tools of this nature, Dafny also allows the proof of properties between one
function
and another. As is common for a
proof assistant
In computer science and mathematical logic, a proof assistant or interactive theorem prover is a software tool to assist with the development of formal proofs by human–machine collaboration. This involves some sort of interactive proof edi ...
, such proofs are often
inductive in nature. Dafny may be unusual in employing method invocation as a mechanism for applying the inductive hypothesis. The following illustrates:
datatype List = Nil , Link(data: int, next: List)
function sum(l: List): int
predicate isNatList(l: List)
lemma NatSumLemma(l: List, n: int)
requires isNatList(l) && n sum(l)
ensures n >= 0
Here,
NatSumLemma
proves a useful property ''between''
sum()
and
isNatList()
(i.e. that
isNatList(l) > (sum(l) >= 0)
). The use of a
ghost method
for encoding
lemmas and theorems is standard in Dafny with recursion employed for induction (typically,
structural induction
Structural induction is a proof method that is used in mathematical logic (e.g., in the proof of Łoś' theorem), computer science, graph theory, and some other mathematical fields. It is a generalization of mathematical induction over natural ...
).
Case analysis is performed using
match
statements and non-inductive cases are often discharged automatically. The verifier must also have complete access to the contents of a
function
or
predicate
to unroll them as necessary. This has implications when used in conjunction with
access modifiers
Access modifiers (or access specifiers) are keywords in object-oriented languages that set the accessibility of classes, methods, and other members. Access modifiers are a specific part of programming language syntax used to facilitate the e ...
. Specifically, hiding the contents of a
function
using the
protected
modifier can limit what properties can be established about it.
See also
*
Design by contract
Design by contract (DbC), also known as contract programming, programming by contract and design-by-contract programming, is an approach for designing software.
It prescribes that software designers should define formal, precise and verifiable ...
References
Further reading
*
*
External links
Dafny: A Language and Program Verifier for Functional Correctness - Microsoft Research*, verification-aware programming language
{{Microsoft Research
Academic programming languages
Experimental programming languages
Microsoft free software
Microsoft programming languages
Microsoft Research
Programming languages created in 2009
Proof assistants
Software using the MIT license
Statically typed programming languages
Articles with example code