\newcommand\qset{\ensuremath{\mathbb{Q}}\xspace}
\newcommand\NV[1]{\columnbreak}


\chapter{Decidable Type Systems}\label{sec:liquid}
%%Simplify!!!
In 1991 Freeman and Pfennning \cite{FreemanPfenning91} introduced
a decidable refinement type system for a subset of ML.
%
In their system, the programmer defines refinement
types for the vanilla data types; 
for example, the vanilla 
list data type can be refined to 
describe \textit{nil} lists, or \textit{singleton} lists, i.e., lists
with exactly one element.
%
These definitions are used to 
construct a finite datatype lattice of each ML type;
a singleton list or a nill list is
also a vanilla list, thus both refined lists are 
less than the unrefined one in the lattice.
%
The datatype lattice is a representation of the subtype
relationship that is used in the 
refinement type inference algorithm. 
Since each lattice is finite, the 
subtyping relation is decidable.

Later, 
they extended~\cite{pfenningxi98} their language to support
linear arithmetic constraints; thus they could
encode a list with length some integer $n$ and 
reason about safety of list indexing.
In this system, subtyping reduces to predicate implication
and they used a variant of Fourier's method \cite{OmegaTestCACM} 
for constraint solving.
%
Finally, they created DML(C)~\cite{XiPfenning99}, 
an extension of ML with refinement types, that supports 
array bounds check elimination,
redundant pattern matching clause removal, 
tag check elimination and untagged representation of datatypes.
%
Refinements in DML(C) are restricted to a finite and decidable
constrain domain $C$, 
which renders constraint solving, and thus subtyping decidable.
%

DML(C)  is a practical programming language, in the sense that 
programs can often be annotated with
very little internal change and the resulting
constraint simplification problems can be solved efficiently
in practice. 
%
Its disadvantage is that annotation burden is high for the programmer,  
as often 10-20\% of
the code is typing annotations.
%
In order to encourage programmers to use refinement specifications in their programs,
Ou \etal \cite{Ou2004}, proposed a language design and type system that allows programmers to add
semantic specifications to program fragments bit by bit. 
More specifically, for certain program components the type checker verifies
statically the refinement type specifications.
%
The rest of the components are written as in any ordinary simply-typed programming language. 
When control passes between different components, data flowing
from simply-typed code into refinement-typed code is checked dynamically 
to ensure that the invariants hold.
%

Another system that combines static verification with dynamic checks is presented in 
Flanagan's Hybrid Type Checking \cite{flanagan06}. 
Flanagan's type system uses syntactic sybtyping to create implications, as discusses in
Section \ref{subsec:formal}. 
Moreover, he assumes an algorithm that decides the validity of the implications.
For each implication the algorithm runs for limited time: 
if it answers unsafe, the program is unsafe, 
but if it does not terminate, a cast is added to postpone the check 
until runtime.
%
Thus, his system
checks implications statically, whenever possible
and dynamically, only when necessary.

In Liquid Types \cite{LiquidPLDI08}, 
implication checking always terminates, 
as implications belong to 
a decidable subset of first order logic.
This is achieved by restricting the refinement language
according to a finite set of qualifiers.
With this technique, liquid type system allows 
type inference, as a means of decreasing the annotation burden.
We present Liquid Types in the rest of the section.

%Semantic Subtyping
%\mypara{SMT solvers}
Many systems discussed so far, including DML(C), Hybrid Type System and Liquid Types, 
use \textit{syntactic subtyping} for constraint 
generation and SMT solvers for constraint solving.
\textit{Satisfiability Modulo Theories} (SMT) solvers solve implications 
for (fragments of) first-order logic plus various standard theories such as
equality, real and integer (linear) arithmetic, uninterpreted functions, bit vectors, and (extensional) arrays. 
Some of the leading systems include  CVC3~\cite{CVC3}, Yices~\cite{Yices}, and Z3~\cite{z3}.

% EXTENSIONS
With the advent of SMT solvers, 
the combination of syntactic subtyping for constraint generation
and an SMT solver for constraint solving has been used in various systems:
%
Mandelbaum \etal \cite{MandelbaumWalker03},
extended the domain of predicates to describe the state 
and the effects of the verified programs.
%
Suter \etal \cite{SuterKK11} increase the power of reasoning 
to support user defined recursive functions.
% automatic inference of ghost variables
Finally, Unno \etal \cite{UnnoTK13},
created a relatively complete system for higher-order functional programs.

%% Partial property: if the program terminates then it is safe 
% relatively completeness for every partial property, if it is safe
% there exists a derivation.
% refinemet language: FOL including all Peano arithmetic
% extended with parameters
 
Apart from syntactic subtyping, SMT solvers can be used in other 
refinement decidable systems:
Dminor \cite{dminor} uses \textit{semantic subtyping} where subtyping is totally 
decided by first order implication checking, while 
HALO \cite{VytiniotisJCR13} uses \textit{denotational semantics}
to prove specification checking.




%{\color{green}
%add other decidable systems:
%\begin{itemize}
%\item \cite{SwamyCFSBY11}
%\item 
%\item \cite{} 
%\end{itemize}
%
%AND SITE Z3 \cite{z3}
%}

\section{Liquid Types}\label{subsec:liquid}

In Liquid Types~\cite{LiquidPLDI08}, 
Rondon \etal restrict the refinement language according to a 
finite set of qualifiers, and achieve not only decidable type checking, but also automatic
type inference.

The system takes as input a program and 
a finite set of \textit{logical qualifiers}
which are simple boolean predicates 
that encode the properties to be verified. 
The system then infers
\textit{liquid types}, which are refinement types where the refinement predicates are conjunctions of the logical qualifiers.
Type checking and inference are decidable for
three reasons. 
%
First, they use a conservative but decidable
notion of subtyping, where 
subtyping reduces to implication checks in a decidable logic.
Each implication holds if and only if it yields a valid formula in
the logic. 
%
Second, an expression has a valid liquid type derivation
only if it has a valid unrefined type derivation, and the refinement 
type of every subexpression is a refinement of its vanilla type. 
%
Third, in any valid type derivation, the types of certain expressions
must be liquid. Thus, inference becomes decidable, as the space of
possible types is bounded. 


\mypara{Logical Qualifiers and Liquid Types}
A logical qualifier is a
boolean-valued expression over the program variables, 
the special value variable @v@ which is distinct from the
program variables, and the special placeholder variable $\star$ that
can be instantiated with program variables. 
Let \qset be the set of logical qualifiers
@{0 < @$\star$@, v < @$\star$@,  v = @$\star$@ + 1}@. 
%
A qualifier $q$ matches the qualifier $q'$
if replacing some variables in $q$ with $\star$ yields $q'$.
For example, the qualifier
@v < x@ matches the qualifier @v < @$\star$. 
$\qset^\star$
is the set of all
qualifiers not containing $\star$ that match some qualifier in \qset. 
For instance, %when \qset\ is as defined as above, 
if @x@, @y@ and @n@ are program variables,
$\qset^\star$
includes the qualifiers
@{0 < x, v = n + 1, v < n, v < y}@. 
A liquid type over \qset\ is a refinement type where the refinement predicates are
conjunctions of qualifiers from $\qset ^ \star$.

%\subsection{Overview}
\mypara{Type Inference}
Type inference is performed in three steps:
(1) the vanilla type of each expression is refined with liquid variables
which represent the unknown refinements;
(2) syntactic subtyping is used to create implication constraints 
between the unknown variables and the concrete refinements;
(3) a theorem prover is used to find the strongest conjunction
of qualifiers in \qset\
that satisfies the subtyping constraints.   

To illustrate this procedure, consider our @pred@ example:
$$\centering
\begin{tabular}{c}
\begin{code}
pred n = n - 1
\end{code}
\end{tabular}
$$

The liquid type for @pred@ can be inferred in three steps:

(Step 1) By Hindley-Milner, 
we can infer that @pred@ has the type @Int -> Int@.
Using this type we create a template for the liquid type of @pred@,
$$\centering
\begin{tabular}{c}
\begin{code}
pred :: n:{v:Int | kn} -> {v:Int | kp}
\end{code}
\end{tabular}
$$
where @kn@ and @kp@
are liquid type variables representing the unknown refinements for the 
argument @n@ and the body of @pred@, respectively.


(Step 2)
We assume a descriptive type for minus:
$$\centering
\begin{tabular}{c}
\begin{code}
(-) :: x:Int -> y:Int -> {v:Int | v = x - y}
\end{code}
\end{tabular}
$$
%
and use it to construct the type of @pred@'s result:
$$\centering
\begin{tabular}{c}
\begin{code}
{v:Int | v = x - y}[x/n][y/1] = {v:Int | v = n - 1} 
\end{code}
\end{tabular}
$$
This type should be subtype of the template type of the body:
$$\centering
\begin{tabular}{c}
\begin{code}
{v:Int | v = n - 1} <: {v:Int | kp}
\end{code}
\end{tabular}
$$
The above subtype reduces to the following constraint:
$$
\texttt{v = n - 1} \Rightarrow \texttt{kp}
$$
(Step 3) Since the program is ``open'', i.e., there are no calls to @pred@,
we assign @kp@ true, meaning that any integer argument can be
passed, and use a theorem prover to find the strongest conjunction
of qualifiers in \qset\
that satisfies the subtyping constraints. 
The algorithm
infers that $v = n-1$ is the strongest solution for @kp@.
By substituting the solution for @kp@ into
the template for @pred@, the algorithm infers
$$\centering
\begin{tabular}{c}
\begin{code}
pred :: n:Int -> {v:Int | v = n-1}
\end{code}
\end{tabular}
$$

\mypara{Type Checking}
As one may notice the inferred type signature of @pred@ does not constrain 
the type of the argument.
This is correct, as @pred@'s definition does not constrain its argument.
One could give @pred@ a more precise type, say:
$$\centering
\begin{tabular}{c}
\begin{code}
pred :: n:{v:Int | v > 0} -> {v:Int | n - 1}
\end{code}
\end{tabular}
$$
The system can verify that this type holds, 
following a procedure similar to the one for type inference:

The first step can be skipped, since there exists 
a concrete type for @pred@.
The body of the function will be type-checked against the given signature.
%
In the second step, as before, 
we construct the type of the body to be 
@{v:Int | n - 1}@ and constrain 
this type to be a subtype of @pred@'s result, or
$$\centering
\begin{tabular}{c}
\begin{code}
{v:Int | v = n - 1} <: {v:Int | v = n - 1}
\end{code}
\end{tabular}
$$
This subtyping reduces to a trivial implication
$
\texttt{v = n - 1} \Rightarrow \texttt{v = n - 1}
$
that can be proven in the third step.

Given the above type signature 
if @pred@ is called with some positive integer value, say @2@,
then in the call site the constraint @v = 2 @$\Rightarrow$@ v >0@ will be generated, 
that can be statically verified.
%
However, if it is called with a non-positive value, 
say @0@, we will get the unsatisfied constraint
@v = 0 @$\Rightarrow$@ v > 0@, 
so the program will be unsafe.

\subsection{Applications of Liquid Types}
Liquid Types, as introduced in \cite{LiquidPLDI08}, used OCaml as target language
and were used to verify array bounds checking.
One year later~\cite{LiquidPLDI09}, they were extended with recursive and polymorphic refinements
to enable static verification of complex data structures; among which 
list sortedness or Binary Tree ordering.
%
Liquid Types were used to verify properties even in imperative languages.
Low-level Liquid Types~\cite{Rondon10} is a refinement type system for
C based on Liquid Types to verify memory safety properties, 
like the absence of array bounds violations
and null-dereferences.
Finally, Liquid Effects~\cite{Kawaguchi12},
is a type-and-effect system based on refinement types
which allows for fine-grained, low-level, shared memory multithreading while statically guaranteeing that a program is deterministic. 

\subsection{Formal Language}
We extend the core calculus $\lambda_C$ to $\lambda_L$, 
a calculus that supports liquid type checking.

The crucial difference between the previous systems, is that 
the refinement language 
can not contain arbitrary expressions, but 
is constrained
to conjunctions of the logical qualifiers, which form a finite set, 
as shown in Figure \ref{fig:liqsyntax}.

Static typing uses syntactic subtyping, as defined in Section \ref{subsec:formal}. 
In this setting,  
the subtyping relation is decidable
because the refinement language, 
and thus the implications created, refer to a decidable logic.
Finally, the \texttt{Valid} relation is evaluated using 
the Z3~\cite{z3} SMT solver.
\begin{figure}[ht!]
\centering
$$
\begin{array}{rrcl}
\emphbf{Predicates} \quad
  & p ::=
  & 	\text{true}
  \spmid q
  \spmid p \land p \ , \ q \in \qset^\star
  \\[0.05in] 
\end{array}
$$
\caption{\textbf{Syntax} from $\lambda_C$ to $\lambda_L$}
\label{fig:liqsyntax}
\end{figure}
\begin{figure}[ht!]
\medskip \judgementHead{Type Checking}{$\hastype{\Gamma}{e}{\tau}$}
$$\begin{array}{cc}
\inference
  {  \hastype{\Gamma}{e}{\tau_2} && \isSubType{\Gamma}{\tau_2}{\tau_1} 
  && \isWellFormed{\Gamma}{\tau_1}
  }
  {\hastype{\Gamma}{e}{\tau_1}}
  [\tsub]
\end{array}$$
\caption{\textbf{Static Semantics} from $\lambda_C$ to $\lambda_L$}
\label{fig:rules}
\end{figure}