blob: 6fb566391c8f8374ac7ad363075679c6c31ecc7f [file] [log] [blame]
\htmlhr
\chapterAndLabel{Aliasing Checker}{aliasing-checker}
The Aliasing Checker identifies expressions that definitely have no
aliases.
Two expressions are aliased when they have the same non-primitive value;
that is, they are references to the identical Java object
in the heap. Another way of saying this is that two expressions,
$\mathit{exprA}$ and $\mathit{exprB}$, are aliases of each other when
$\mathit{exprA} \<==> \mathit{exprB}$ at the same program point.
Assigning to a variable or field typically creates an alias. For example,
after the statement \<a = b;>, the variables \<a> and \<b> are aliased.
Knowing that an expression is not aliased permits more accurate reasoning
about how side effects modify the expression's value.
To run the Aliasing Checker, supply the
\code{-processor org.checkerframework.common.aliasing.AliasingChecker}
command-line option to javac.
However, a user rarely runs the Aliasing Checker directly.
This type system is mainly intended to be used together with other type systems.
For example, the SPARTA information flow type-checker
(Section~\ref{sparta-checker}) uses the Aliasing Checker to improve its
type refinement --- if an expression has no aliases, a more refined type
can often be inferred, otherwise the type-checker makes conservative
assumptions.
\sectionAndLabel{Aliasing annotations}{aliasing-annotations}
\begin{figure}
\includeimage{aliasing}{2cm}
\caption{Type hierarchy for the Aliasing type system.
These qualifiers are applicable to any reference (non-primitive) type.}
\label{fig-aliasing-hierarchy}
\end{figure}
There are two possible types for an expression:
\begin{description}
\item[\refqualclass{common/aliasing/qual}{MaybeAliased}]
is the type of an expression that might have an alias.
This is the default, so every unannotated type is
\code{@MaybeAliased}. (This includes the type of \code{null}.)
\item[\refqualclass{common/aliasing/qual}{Unique}]
is the type of an expression that has no aliases.
The \code{@Unique} annotation is only allowed at local variables, method
parameters, constructor results, and method returns.
A constructor's result should be annotated with \code{@Unique} only if the
constructor's body does not creates an alias to the constructed object.
\end{description}
There are also two annotations, which are currently trusted instead of verified,
that can be used on formal parameters (including
the receiver parameter, \<this>):
\begin{description}
\item[\refqualclass{common/aliasing/qual}{NonLeaked}]
identifies a formal parameter that is not leaked nor
returned by the method body.
For example, the formal parameter of the String copy constructor,
\code{String(String s)}, is \code{@NonLeaked} because the body of the method
only makes a copy of the parameter.
\item[\refqualclass{common/aliasing/qual}{LeakedToResult}]
is used when the parameter may be returned, but it is not
otherwise leaked.
For example, the receiver parameter of \code{StringBuffer.append(StringBuffer
this, String s)} is
\code{@LeakedToResult}, because the method returns the updated receiver.
\end{description}
\sectionAndLabel{Leaking contexts}{aliasing-leaking-contexts}
This section lists the expressions that create aliases. These are also
called ``leaking contexts''.
\begin{description}
\item[Assignments]
After an assignment, the left-hand side and the right-hand side are
typically aliased. (The only counterexample is when the right-hand side is
a fresh expression; see Section~\ref{aliasing-refinement}.)
\begin{Verbatim}
@Unique Object u = ...;
Object o = u; // (not.unique) type-checking error!
\end{Verbatim}
If this example type-checked, then \<u> and \<o> would be aliased.
For this example to type-check, either the \<@Unique> annotation on the
type of \<u>, or the \<o = u;> assignment, must be removed.
\item[Method calls and returns (pseudo-assignments)]
Passing an argument to a method is a ``pseudo-assignment'' because it effectively
assigns the argument to the formal parameter. Return statements are also
pseudo-assignments.
As with assignments, the left-hand side and right-hand side of
pseudo-assignments are typically aliased.
Here is an example for argument-passing:
\begin{Verbatim}
void mightDoAnything(Object o) { ... }
@Unique Object u = ...;
mightDoAnything(u); // type-checking error, because the callee may create an alias of the passed argument
\end{Verbatim}
Passing a non-aliased
reference to a method does not necessarily create an alias.
However, the body of the method might create an alias or leak the
reference. Thus, the Aliasing Checker always treats a method call as
creating aliases for each argument unless the corresponding formal
parameter is marked as
@\refqualclass{common/aliasing/qual}{NonLeaked} or
@\refqualclass{common/aliasing/qual}{LeakedToResult}.
Here is an example for a return statement:
\begin{Verbatim}
Object id(@Unique Object p) {
return p; // (not.unique) type-checking error!
}
\end{Verbatim}
If this code type-checked, then it would be possible for clients to write
code like this:
\begin{Verbatim}
@Unique Object u = ...;
Object o = id(u);
\end{Verbatim}
\noindent
after which there is an alias to \<u> even though it is declared as \<@Unique>.
However, it is permitted to write
\begin{Verbatim}
Object id(@LeakedToResult Object p) {
return p;
}
\end{Verbatim}
\noindent
after which the following code type-checks:
\begin{Verbatim}
@Unique Object u = ...;
id(u); // method call result is not used
Object o1 = ...;
Object o2 = id(o1); // argument is not @Unique
\end{Verbatim}
\item[Throws]
A thrown exception can be captured by a catch block, which creates an
alias of the thrown exception.
\begin{Verbatim}
void aliasInCatchBlock() {
@Unique Exception uex = new Exception();
try {
throw uex; // (not.unique) type-checking error!
} catch (Exception ex) {
// uex and ex refer to the same object here.
}
}
\end{Verbatim}
\item[Array initializers]
Array initializers assign the elements in the initializers to corresponding
indexes in the array, therefore expressions in an array initializer are leaked.
\begin{Verbatim}
void aliasInArrayInitializer() {
@Unique Object o = new Object();
Object[] ar = new Object[] { o }; // (not.unique) type-checking error!
// The expressions o and ar[0] are now aliased.
}
\end{Verbatim}
%Remember to add enhanced for statement if support to type variables is added.
\end{description}
\sectionAndLabel{Restrictions on where \<@Unique> may be written}{aliasing-unique-restrictions}
The \<@Unique> qualifier may not be written on locations such as fields,
array elements, and type parameters.
As an example of why \<@Unique> may not be written on a field's type,
consider the following code:
\begin{Verbatim}
class MyClass {
@Unique Object field;
void makesAlias() {
MyClass myClass2 = this;
// this.field is now an alias of myClass2.field
}
}
\end{Verbatim}
That code must not type-check, because \<field> is declared as \<@Unique>
but has an alias. The Aliasing Checker solves the problem by forbidding
the \<@Unique> qualifier on subcomponents of a structure, such as fields.
Other solutions might be possible; they would be more complicated but would
permit more code to type-check.
\<@Unique> may not be written on a type parameter for similar reasons.
The assignment
\begin{Verbatim}
List<@Unique Object> l1 = ...;
List<@Unique Object> l2 = l1;
\end{Verbatim}
\noindent
must be forbidden because it would alias \<l1.get(0)> with \<l2.get(0)>
even though both have type \<@Unique>. The Aliasing Checker forbids this
code by rejecting the type \code{List<@Unique Object>}.
\sectionAndLabel{Aliasing type refinement}{aliasing-refinement}
Type refinement enables a type checker to treat an expression as a subtype
of its declared type. For example, even if you declare a local variable as
\<@MaybeAliased> (or don't write anything, since \<@MaybeAliased> is the
default), sometimes the Aliasing Checker can determine that it is actually
\<@Unique>.
% This prevents the type checker from issuing false positive warnings.
For more details, see Section~\ref{type-refinement}.
The Aliasing Checker treats type refinement in the usual way,
except that at (pseudo-)assignments
the right-hand-side (RHS) may lose its type refinement, before the
left-hand-side (LHS) is type-refined.
The RHS always loses its type refinement (it is widened to
\code{@MaybeAliased}, and its declared type must have been
\code{@MaybeAliased}) except in the following cases:
\begin{itemize}
\item
The RHS is a fresh expression --- an expression that returns a different value
each time it is evaluated. In practice, this is only method/constructor calls
with \code{@Unique} return type. A variable/field is not fresh because it can
return the same value when evaluated twice.
\item
The LHS is a \code{@NonLeaked} formal parameter and the RHS is an argument in a
method call or constructor invocation.
\item
The LHS is a \code{@LeakedToResult} formal parameter, the RHS is an argument in
a method call or constructor invocation, and the method's return value is
discarded --- that is, the method call or constructor invocation is written
syntactically as a statement rather than as a part of a larger expression or
statement.
\end{itemize}
%(Notice that the last two rules above are restricted to pseudo-assignments.)
A consequence of the above rules is that most method calls are treated conservatively.
If a variable with declared type \code{@MaybeAliased} has been refined
to \code{@Unique} and is used as an argument of a method call, it usually loses its
\code{@Unique} refined type.
Figure~\ref{fig-aliasing-refinement-example} gives an example of the Aliasing Checker's
type refinement rules.
\begin{figure}
%BEGIN LATEX
\begin{smaller}
%END LATEX
\begin{Verbatim}
// Annotations on the StringBuffer class, used in the examples below.
// class StringBuffer {
// @Unique StringBuffer();
// StringBuffer append(@LeakedToResult StringBuffer this, @NonLeaked String s);
// }
void foo() {
StringBuffer sb = new StringBuffer(); // sb is refined to @Unique.
StringBuffer sb2 = sb; // sb loses its refinement.
// Both sb and sb2 have aliases and because of that have type @MaybeAliased.
}
void bar() {
StringBuffer sb = new StringBuffer(); // sb is refined to @Unique.
sb.append("someString");
// sb stays @Unique, as no aliases are created.
StringBuffer sb2 = sb.append("someString");
// sb is leaked and becomes @MaybeAliased.
// Both sb and sb2 have aliases and because of that have type @MaybeAliased.
}
\end{Verbatim}
%BEGIN LATEX
\end{smaller}
%END LATEX
\caption{Example of the Aliasing Checker's type refinement rules.}
\label{fig-aliasing-refinement-example}
\end{figure}
%% LocalWords: MaybeAliased NonLeaked LeakedToResult l1 l2 RHS LHS
%% LocalWords: subcomponents