%TODO: % -Explain { % A a; % B b; % } % class Pair extends SuperPair{ % A a; % B b; % X choose(X a, X b){ return b; } % String m(List> a, List> b){ % return choose(choose(a,b).value.a,b.value.b); % } % } % \end{verbatim} \begin{figure}%[tp] \begin{subfigure}[t]{\linewidth} \begin{lstlisting}[style=fgj] class List { List add(A v) { ... } } class Example { m(l, la, lb){ return l .add(la.add(1)) .add(lb.add("str")); } } \end{lstlisting} \caption{Java method with missing return type} \label{fig:nested-list-example-typeless} \end{subfigure} ~ % \begin{subfigure}[t]{\linewidth} % \begin{lstlisting}[style=tfgj] % class List { % List add(A v) { ... } % } % class Example { % m(l, la, lb){ % return let r2 : (*@$\wctype{\wildcard{X}{\type{Object}}{\bot}}{List}{\rwildcard{X}}$@*) = { % let r1 : (*@$\wctype{\wildcard{X}{\type{Object}}{\bot}}{List}{\rwildcard{X}}$@*) = l in { % let p1 : (*@$\exptype{List}{\type{Integer}}$@*) = { % let xa = la in xa.add(1) % } in x1.add(p1) % } in { % let p2 = { % let xb = lb in xb.add("str") % } in x2.add(p2) % }; % } % } % \end{lstlisting} % \caption{Featherweight Java Representation} % \label{fig:nested-list-example-let} % \end{subfigure} % ~ \begin{subfigure}[t]{\linewidth} \begin{lstlisting}[style=tfgj] class List { List add(A v) { ... } } class Example { m(List> l, List la, List lb){ return l .add(la.add(1)) .add(lb.add("str")); } } \end{lstlisting} \caption{Java Representation} \label{fig:nested-list-example-typed} \end{subfigure} %\caption{Example code} %\label{fig:intro-example-code} \end{figure} %TODO % The goal is to proof soundness in respect to the type rules introduced by \cite{aModelForJavaWithWildcards} % and \cite{WildcardsNeedWitnessProtection}. \begin{figure}%[tp] \begin{subfigure}[t]{0.49\linewidth} \begin{lstlisting}[style=fgj] genList() { if( ... ) { return new List(); } else { return new List(); } } \end{lstlisting} \caption{Java method with missing return type} \label{fig:intro-example-typeless} \end{subfigure} ~ \begin{subfigure}[t]{0.49\linewidth} \begin{lstlisting}[style=tfgj] List genList() { if( ... ) { return new List(); } else { return new List(); } } \end{lstlisting} \caption{Correct type} \label{fig:intro-example-typed} \end{subfigure} %\caption{Example code} %\label{fig:intro-example-code} \end{figure} % \subsection{Wildcards} % Java subtyping involving generics is invariant. % For example \texttt{List} is not a subtype of \texttt{List}. % %Wildcards introduce variance by allowing \texttt{List} to be a subtype of \texttt{List}. % \texttt{List} is not a valid return type for the method \texttt{genList}. % The type inference algorithm has to find the correct type involving wildcards (\texttt{List}). \subsection{Java Wildcards} Wildcards are expressed by a \texttt{?} in Java and can be used as type parameters. Wildcards add variance to Java type parameters. Generally Java has invariant subtyping for polymorphic types. A \texttt{List} is not a subtype of \texttt{List} for example even though it seems intuitive with \texttt{String} being a subtype of \texttt{Object}. Wildcards can be formalized as existential types \cite{WildFJ}. \texttt{List} and \texttt{List} are both wildcard types denoted in our syntax by $\wctype{\wildcard{X}{\type{Object}}{\bot}}{List}{\rwildcard{X}}$ and $\wctype{\wildcard{X}{\type{Object}}{\type{String}}}{List}{\rwildcard{X}}$. The syntax used here allows for wildcard parameters to have a name, an uppper and lower bound at the same time, and a type they are bound to. In this case the name is $\rwildcard{X}$ and it's bound to the the type \texttt{List}. Those properties are needed to formalize capture conversion. Polymorphic method calls need to be wraped in a process which \textit{opens} existential types \cite{addingWildcardsToJava}. In Java this is done implicitly in a process called capture conversion. One problem is the divergence between denotable and expressable types in Java \cite{semanticWildcardModel}. A wildcard in the Java syntax has no name and is bound to its enclosing type. $\exptype{List}{\exptype{List}{\type{?}}}$ equates to $\exptype{List}{\wctype{\rwildcard{X}}{List}{\rwildcard{X}}}$. During type checking \emph{intermediate types} %like $\wctype{\rwildcard{X}}{List}{\exptype{List}{\rwildcard{X}}}$ %or $\wctype{\rwildcard{X}}{Pair}{\rwildcard{X}, \rwildcard{X}}$ can emerge, which have no equivalent in the Java syntax. %Our type inference algorithm uses existential types internally but spawns type solutions compatible with Java. Example: % This program is not typable with the Type Inference algorithm from Plümicke \begin{verbatim} class List extends Object {...} class List2D extends List> {...} void shuffle(List> list) {...} List> l = ...; List2D l2d = ...; shuffle(l); // Error shuffle(l2d); // Valid \end{verbatim} Java is using local type inference to allow method invocations which are not describable with regular Java types. The \texttt{shuffle} method in this case is invoked with the type $\wctype{\rwildcard{X}}{List2D}{\rwildcard{X}}$ which is a subtype of $\wctype{\rwildcard{X}}{List}{\exptype{List}{\rwildcard{X}}}$. After capture conversion \texttt{l2d'} has the type $\exptype{List}{\exptype{List}{\rwildcard{X}}}$ and \texttt{shuffle} can be invoked with the type parameter $\rwildcard{X}$: \begin{lstlisting}[style=letfj] let l2d' : (*@$\wctype{\rwildcard{X}}{List}{\exptype{List}{\rwildcard{X}}}$@*) = l2d in shuffle(l2d') \end{lstlisting} The respective constraints are: \begin{constraintset} \begin{center} $ \begin{array}{l} \wctype{\rwildcard{X}}{List2D}{\rwildcard{X}} \lessdotCC \exptype{List}{\exptype{List}{\wtv{x}}} \\ \hline \wctype{\rwildcard{X}}{List}{\exptype{List}{\rwildcard{X}}} \lessdotCC \exptype{List}{\exptype{List}{\wtv{x}}} \\ \hline \textit{Capture Conversion:}\ \exptype{List}{\exptype{List}{\rwildcard{X}}} \lessdot \exptype{List}{\exptype{List}{\wtv{x}}} \\ \hline \textit{Solution:} \wtv{x} \doteq \rwildcard{X} \implies \exptype{List}{\exptype{List}{\rwildcard{X}}} \lessdot \exptype{List}{\exptype{List}{\rwildcard{X}}} \end{array} $ \end{center} \end{constraintset} \texttt{l} however has the type $\exptype{List}{\wctype{\rwildcard{X}}{List}{\rwildcard{X}}}$. The method call \texttt{shuffle(l)} is not correct, because there is no solution for the subtype constraint: $\exptype{List}{\wctype{\rwildcard{X}}{List}{\rwildcard{X}}} \lessdotCC \exptype{List}{\exptype{List}{\wtv{x}}}$ % $\exptype{List}{String} <: \wctype{\wildcard{X}{\bot}{\type{Object}}}{List}{\rwildcard{X}}$ % means \texttt{List} is a subtype of \texttt{List}. \subsection{Global Type Inference} % A global type inference algorithm works on an input with no type annotations at all. % \begin{verbatim} % m(l) { % return l.add(l); % } % \end{verbatim} % $\tv{l} \lessdotCC \exptype{List}{\wtv{x}}, \tv{l} \lessdotCC \wtv{x}$ \begin{description} \item[input] \tifj{} program \item[output] type solution \item[postcondition] the type solution applied to the input must yield a valid \letfj{} program \end{description} The input to our type inference algorithm is a modified version of the \letfj{}\cite{WildcardsNeedWitnessProtection} calculus (see chapter \ref{sec:tifj}). First \fjtype{} generates constraints and afterwards \unify{} computes a solution for the given constraint set. Constraints consist out of subtype constraints $(\type{T} \lessdot \type{T})$ and capture constraints $(\type{T} \lessdotCC \type{T})$. \textit{Note:} a type $\type{T}$ can also be a type placeholders $\ntv{a}$ or a wildcard type placeholder $\wtv{a}$. A subtype constraint is satisfied if the left side is a subtype of the right side according to the rules in figure \ref{fig:subtyping}. \textit{Example:} $\exptype{List}{\ntv{a}} \lessdot \exptype{List}{\type{String}}$ is fulfilled by replacing type placeholder $\ntv{a}$ with the type $\type{String}$. Subtype constraints and type placeholders act the same as the ones used in \emph{Type Inference for Featherweight Generic Java} \cite{TIforFGJ}. The novel capture constraints and wildcard placeholders are needed for method invocations involving wildcards. %show input and a correct letFJ representation Even in a full typed program local type inference can be necessary. %TODO: first show local type inference and explain lessdotCC constraints. then show example with global TI Let's start with an example where all types are already given: \begin{lstlisting}[style=tfgj, caption=Valid Java program, label=lst:addExample] List add(List l, A v) List l = ...; add(l, "String"); \end{lstlisting} \begin{lstlisting}[style=letfj, caption=\letfj{} representation of \texttt{add(l, "String")}, label=lst:addExampleLet] let l2 : (*@$\wctype{\wildcard{X}{\type{Object}}{\type{String}}}{List}{\rwildcard{X}}$@*) = l in add(l2, "String"); \end{lstlisting} In \letfj{} there is no local type inference and all type parameters for a method call are mandatory. If wildcards are involved the so called capture conversion has to be done manually via let statements. A let statement \emph{opens} an existential type. In the body of the let statement the \textit{capture type} $\wctype{\wildcard{X}{\type{Object}}{\type{String}}}{List}{\rwildcard{X}}$ becomes $\exptype{List}{\rwildcard{X}}$ and the wildcard $\wildcard{X}{\type{Object}}{\type{String}}$ is free and can be used as a type parameter to \texttt{add(...)}. %This is a valid Java program where the type parameters for the polymorphic method \texttt{add} %are determined by local type inference. Our type inference algorithm has to add let statements if necessary, including the capture types. Lets have a look at the constraints generated by \fjtype{} for the example in listing \ref{lst:addExample}: \begin{constraintset} \begin{center} $\begin{array}{c} \wctype{\wildcard{X}{\type{Object}}{\type{String}}}{List}{\rwildcard{X}} \lessdotCC \exptype{List}{\wtv{a}}, \, \type{String} \lessdotCC \wtv{a} \\ \hline \textit{Capture Conversion:}\ \exptype{List}{\rwildcard{X}} \lessdot \exptype{List}{\wtv{a}}, \, \type{String} \lessdot \wtv{a} \\ \hline \textit{Solution:}\ \wtv{a} \doteq \rwildcard{X} \implies \exptype{List}{\rwildcard{X}} \lessdot \exptype{List}{\rwildcard{X}}, \, \type{String} \lessdot \rwildcard{X} \end{array} $ \end{center} \end{constraintset} %Why do we need the lessdotCC constraints here? The type of \texttt{l} can be capture converted by a let statement if needed (see listing \ref{lst:addExampleLet}). Therefore we assign the constraint $\wctype{\wildcard{X}{\type{Object}}{\type{String}}}{List}{\rwildcard{X}} \lessdotCC \exptype{List}{\wtv{a}}$ which allows \unify{} to do a capture conversion to $\exptype{List}{\rwildcard{X}} \lessdot \exptype{List}{\wtv{a}}$. \textit{Note:} The constraint $\type{String} \lessdot \rwildcard{X}$ is satisfied because $\rwildcard{X}$ has $\type{String}$ as lower bound. % No capture conversion for methods in the same class: % Given two methods without type annotations like % \begin{verbatim} % // m :: () -> r % m() = new List() :? new List(); % // id :: (a) -> a % id(a) = a % \end{verbatim} % and a method call \texttt{id(m())} would lead to the constraints: % $\exptype{List}{\type{String}} \lessdot \ntv{r}, % \exptype{List}{\type{Integer}} \lessdot \ntv{r}, % \ntv{r} \lessdotCC \ntv{a}$ % In this example capture conversion is not applicable, % because the \texttt{id} method is not polymorphic. % The type solution provided by \unify{} for this constraint set is: % $\sigma(\ntv{r}) = \wctype{\rwildcard{X}}{List}{\rwildcard{X}}, % \sigma(\ntv{a}) = \wctype{\rwildcard{X}}{List}{\rwildcard{X}}$ % \begin{verbatim} % List m() = new List() :? new List(); % List id(List a) = a % \end{verbatim} The following example has the \texttt{id} method already typed and the method \texttt{m} extended by a recursive call \texttt{id(m())}: \begin{verbatim} List id(List a) = a m() = new List() :? new List() :? id(m()); \end{verbatim} Now the constraints make use of a $\lessdotCC$ constraint: $\exptype{List}{\type{String}} \lessdot \ntv{r}, \exptype{List}{\type{Integer}} \lessdot \ntv{r}, \ntv{r} \lessdotCC \exptype{List}{\wtv{a}}$ After substituting $\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$ for $\ntv{r}$ like in the example before we get the constraint $\wctype{\rwildcard{X}}{List}{\rwildcard{X}} \lessdotCC \exptype{List}{\wtv{a}}$. Due to the $\lessdotCC$ \unify{} is allowed to perform a capture conversion yielding $\exptype{List}{\rwildcard{X}} \lessdot \exptype{List}{\wtv{a}}$. \textit{Note:} The wildcard placeholder $\wtv{a}$ is allowed to hold free variables whereas a normal placeholder like $\ntv{r}$ is never assigned a type containing free variables. Therefore \unify{} sets $\wtv{a} \doteq \rwildcard{X}$, completing the constraint set and resulting in the type solution: \begin{verbatim} List m() = new List() :? new List() :? id(m()); \end{verbatim} \subsection{Challenges}\label{challenges} %TODO: Wildcard subtyping is infinite see \cite{TamingWildcards} The introduction of wildcards adds additional challenges. % we cannot replace every type variable with a wildcard Type variables can also be used as type parameters, for example $\exptype{List}{String} \lessdot \exptype{List}{\tv{a}}$. A problem arises when replacing type variables with wildcards. % Wildcards are not reflexive. % ( on the equals property ), every wildcard has to be capture converted when leaving its scope % do not substitute free type variables Lets have a look at two examples: \begin{itemize} \item \begin{example} \label{intro-example1} The first one is a valid Java program. The type \texttt{List} is \textit{capture converted} to a fresh type variable $\rwildcard{X}$ which is used as the generic method parameter \texttt{A}. Java uses capture conversion to replace the generic \texttt{A} by a capture converted version of the \texttt{? super String} wildcard. Knowing that the type \texttt{String} is a subtype of any type the wildcard \texttt{? super String} can inherit it is safe to pass \texttt{"String"} for the first parameter of the function. \begin{verbatim} List add(List l, A v) {} List list = ...; add("String", list); \end{verbatim} \end{example} \item \begin{example}\label{intro-example2} This example displays an incorrect Java program. The method call to \texttt{concat} with two wildcard lists is unsound. Each list could be of a different kind and therefore the \texttt{concat} cannot succeed. \begin{verbatim} List concat(List l1, List l2) { ... } List list = ... ; concat(list, list); \end{verbatim} % $\wctype{\wildcard{X}{\type{Object}}{\bot}}{List}{\rwildcard{X}} \lessdot \exptype{List}{\wtv{a}}, \\ % \wctype{\wildcard{X}{\type{Object}}{\bot}}{List}{\rwildcard{X}} \lessdot \exptype{List}{\wtv{a}}$ \end{example} % \item % \unify{} morphs a constraint set into a correct type solution % gradually assigning types to type placeholders during that process. % Solved constraints are removed and never considered again. % In the following example \unify{} solves the constraint generated by the expression % \texttt{l.add(l.head())} first, which results in $\ntv{l} \lessdot \exptype{List}{\wtv{a}}$. % \begin{verbatim} % anyList() = new List() :? new List() % add(anyList(), anyList().head()); % \end{verbatim} % The type for \texttt{l} can be any kind of list, but it has to be a invariant one. % Assigning a \texttt{List} for \texttt{l} is unsound, because the type list hiding behind % \texttt{List} could be a different one for the \texttt{add} call than the \texttt{head} method call. % An additional constraint $\wctype{\rwildcard{X}}{List}{\rwildcard{X}} \lessdot \exptype{List}{\wtv{a}}$ % is solved by removing the wildcard $\rwildcard{X}$ if possible. \end{itemize} The \unify{} algorithm only sees the constraints with no information about the program they originated from. The main challenge was to find an algorithm which computes $\sigma(\wtv{a}) = \rwildcard{X}$ for example \ref{intro-example1} but not for example \ref{intro-example2}. \subsection{Capture Conversion} The input to our type inference algorithm does not contain let statements. Those are added after computing a type solution. Let statements act as capture conversion and only have to be applied in method calls involving wildcard types. \begin{figure} \begin{minipage}{0.45\textwidth} \begin{lstlisting}[style=fgj] List clone(List l); example(p){ return clone(p); } \end{lstlisting} \end{minipage}% \hfill \begin{minipage}{0.5\textwidth} \begin{lstlisting}[style=tfgj] (*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*) example((*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*) p){ return let x : (*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*) = p in clone(x) : (*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*); } \end{lstlisting} \end{minipage} \caption{Type inference adding capture conversion}\label{fig:addingLetExample} \end{figure} Figure \ref{fig:addingLetExample} shows a let statement getting added to the typed output. The method \texttt{clone} cannot be called with the type $\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$. After a capture conversion \texttt{x} has the type $\exptype{List}{\rwildcard{X}}$ with $\rwildcard{X}$ being a free variable. Afterwards we have to find a supertype of $\exptype{List}{\rwildcard{X}}$, which does not contain free variables ($\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$ in this case). During the constraint generation step most types are not known yet and are represented by a type placeholder. During a methodcall like the one in the \texttt{example} method in figure \ref{fig:ccExample} the type of the parameter \texttt{p} is not known yet. The type \texttt{List} would be one possibility as a parameter type for \texttt{p}. To make wildcards work for our type inference algorithm \unify{} has to apply capture conversions if necessary. The type placeholder $\tv{r}$ is the return type of the \texttt{example} method. One possible type solution is $\tv{p} \doteq \tv{r} \doteq \wctype{\rwildcard{X}}{List}{\rwildcard{X}}$, which leads to: \begin{verbatim} List example(List p){ return clone(p); } \end{verbatim} But by substituting $\tv{p} \doteq \wctype{\rwildcard{X}}{List}{\rwildcard{X}}$ in the constraint $\tv{p} \lessdotCC \exptype{List}{\wtv{x}}$ leads to $\wctype{\rwildcard{X}}{List}{\rwildcard{X}} \lessdotCC \exptype{List}{\wtv{x}}$. To make this typing possible we have to introduce a capture conversion via a let statement: $\texttt{return}\ (\texttt{let}\ \texttt{x} : \wctype{\rwildcard{X}}{List}{\rwildcard{X}} = \texttt{p}\ \texttt{in} \ \texttt{clone}\generics{\rwildcard{X}}(x) : \wctype{\rwildcard{X}}{List}{\rwildcard{X}})$ Inside the let statement the variable \texttt{x} has the type $\exptype{List}{\rwildcard{X}}$ This spawns additional problems. \begin{figure} \begin{minipage}{0.45\textwidth} \begin{verbatim} List clone(List l){...} example(p){ return clone(p); } \end{verbatim} \end{minipage}% \hfill \begin{minipage}{0.35\textwidth} \begin{constraintset} \textbf{Constraints:}\\ $ \tv{p} \lessdotCC \exptype{List}{\wtv{x}}, \\ \tv{p} \lessdot \tv{r}, \\ \tv{p} \lessdot \type{Object}, \tv{r} \lessdot \type{Object} $ \end{constraintset} \end{minipage} \caption{Type inference example}\label{fig:ccExample} \end{figure} In addition with free variables this leads to unwanted behaviour. Take the constraint $\wctype{\rwildcard{X}}{List}{\rwildcard{X}} \lessdot \exptype{List}{\wtv{a}}$ for example. After a capture conversion from $\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$ to $\exptype{List}{\rwildcard{Y}}$ and a substitution $\wtv{a} \doteq \rwildcard{Y}$ we get $\exptype{List}{\rwildcard{Y}} \lessdot \exptype{List}{\rwildcard{Y}}$. Which is correct if we apply capture conversion to the left side: $\exptype{List}{\rwildcard{X}} <: \exptype{List}{\rwildcard{X}}$ If the input constraints did not intend for this constraint to undergo a capture conversion then \unify{} would produce an invalid type solution due to: $\wctype{\rwildcard{X}}{List}{\rwildcard{X}} \nless: \exptype{List}{\rwildcard{X}}$ The reason for this is the \texttt{S-Exists} rule's premise $\text{dom}(\Delta') \cap \text{fv}(\exptype{List}{\rwildcard{X}}) = \emptyset$. Additionally free variables are not allowed to leave the scope of a capture conversion introduced by a let statement. %TODO we combat both of this with wildcard type placeholders (? flag) Type placeholders which are not flagged as possible free variables ($\wtv{a}$) can never hold a free variable or a type containing free variables. Constraint generation places these standard place holders at method return types and parameter types. \begin{lstlisting}[style=fgj] List clone(List l); (*@$\red{\tv{r}}$@*) example((*@$\red{\tv{p}}$@*) p){ return clone(p); } \end{lstlisting} This prevents type solutions that contain free variables in parameter and return types. When calling a method which already has a type annotation we have to consider adding a capture conversion in form of a let statement. The constraint $\tv{p} \lessdot \exptype{List}{\wtv{x}}$ signals the \unify{} algorithm that here a capture conversion is possible. $\sigma(\tv{p}) = \wctype{\rwildcard{X}}{List}{\rwildcard{X}}, \sigma(\tv{r}) = \wctype{\rwildcard{X}}{List}{\rwildcard{X}}, $ is a possible solution. But only when adding a capture conversion: \begin{lstlisting}[style=fgj] List clone(List l); (*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*) example((*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*) p){ return let x : (*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*) = p in clone(x) : (*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*); } \end{lstlisting} Capture constraints cannot be stored in a set. $\wtv{a} \lessdotCC \wtv{b}$ is not the same as $\wtv{a} \lessdotCC \wtv{b}$. Both constraints will end up the same after a substitution for both placeholders $\tv{a}$ and $\tv{b}$. But afterwards a capture conversion is applied, which can generate different types on the left sides. \begin{itemize} \item $\text{CC}(\wctype{\rwildcard{X}}{List}{\rwildcard{X}}) \implies \exptype{List}{\rwildcard{Y}}$ \item $\text{CC}(\wctype{\rwildcard{X}}{List}{\rwildcard{X}}) \implies \exptype{List}{\rwildcard{Z}}$ \end{itemize}