<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <article-id pub-id-type="doi">10.5281/zenodo.16836767</article-id>
      <title-group>
        <article-title>Global Type Inference for Java using ASP</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Andreas Stadelmeier</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Martin Plümicke</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>Duale Hochschule Baden-Württemberg</institution>
          ,
          <addr-line>Stuttgart</addr-line>
          ,
          <country country="DE">Germany</country>
        </aff>
      </contrib-group>
      <pub-date>
        <year>2025</year>
      </pub-date>
      <abstract>
        <p>Global type inference for Java is able to compute correct types for an input program which has no type annotations at all, but turns out to be NP-hard. Former implementations of the algorithm therefore struggled with bad runtime performance. In this original paper, we translate the type inference algorithm for Featherweight Generic Java to an Answer Set Program. Answer Set Programming (ASP) promises to solve complex computational search problems as long as they are finite domain. This paper shows that it is possible to implement global type inference for Featherweight Generic Java (FGJ) as an ASP program. Afterwards we compared the ASP implementation with our own implementation in Java showing promising results. Another advantage is that the algorithm's specification can be mapped directly to ASP code, which reduces the likelihood of errors in the implementation.</p>
      </abstract>
      <kwd-group>
        <kwd>eol&gt;type inference</kwd>
        <kwd>java</kwd>
        <kwd>programming languages</kwd>
        <kwd>answer set programming</kwd>
      </kwd-group>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>1. Global Type Inference</title>
      <p>//</p>
      <p>A possible input for our algorithm is shown in Figure 1. Here the method untypedMethod is missing
its argument type for var and its return type. Global type inference works in two steps. First we
generate a set of subtype constraints, which are later unified resulting in a type solution consisting
of type unifiers  . Every missing type is replaced by a type placeholder. In this example the type
placeholder var is a placeholder for the type of the var variable. The ret placeholder represents the
return type of the untypedMethod method. Also shown as a comment behind the respective method
call. There are two types of type constraints:
• A subtype constraint such as var ⋖ C1 indicates that the unification algorithm must determine a
type substitution for var that is a subtype of C1. One possible solution would be  (var ) = C1.</p>
      <p>.</p>
      <p>• A equals constraint var = C1, which results in  (ret ) = C1.</p>
      <p>
        Our type inference algorithms for Java are described in a formal manner in [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ],[
        <xref ref-type="bibr" rid="ref2">2</xref>
        ]. The first prototype
implementation put the focus on a correct implementation rather than fast execution times. Depending
on the input, it currently takes up to several minutes or even days to compute all or even one possible
type solution. To make them usable in practice, we now focus on decreasing the runtime to a feasible
level.
      </p>
    </sec>
    <sec id="sec-2">
      <title>2. Motivation</title>
      <p>The nature of the global type inference algorithm causes the search space of the unification algorithm to
increase exponentially with every ambiguous method call. Java allows overloaded methods, causing our
type inference algorithm to create so-called Or-Constraints. This happens if multiple classes implement
a method with the same name and the same amount of parameters. Given the input program in Figure 1,
we do not know, which method self is meant for the method call var.self(), because there is no
type annotation for var.</p>
      <p>. .</p>
      <p>An Or-Constraint like {var ⋖ C1, ret = C1.} || {var ⋖ C2, ret = C2} means that either the constraint
set {var ⋖ C1, ret =. C1} or {var ⋖ C2, ret = C2} has to be satisfied. If we set the type of var to C1,
then the return type of the method will be C1 as well. If we set it to C2, then the return type will also
be C2. Since two distinct possibilities exist, an Or-Constraint with both variants is required.
untypedMethod(var){</p>
      <p>return var.self().self().self().self();
}</p>
      <p>
        If we chain multiple overloaded method calls together, we end up with multiple Or-Constraints.
The type unification algorithm Unify only sees the supplied constraints and has to potentially try all
combinations of them. This is proven in [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ] and is the reason why type inference for Featherweight
      </p>
      <sec id="sec-2-1">
        <title>Generic Java is NP-hard.</title>
        <p>Let’s have a look at the following alternation of our example shown in Figure 2. Now there are four
chained method calls leading to four Or-Constraints:
{var ⋖ C1, r1 =. C1} || {var ⋖ C2, r1 =. C2}
{r1 ⋖ C1, r2 =. C1} || {r1 ⋖ C2, r2 =. C2}
{r2 ⋖ C1, r3 =. C1} || {r2 ⋖ C2, r3 =. C2}</p>
        <p>. .</p>
        <p>{r3 ⋖ C1, ret = C1} || {r3 ⋖ C2, ret = C2}</p>
        <p>
          The placeholder r1 stands for the return type of the first call to self and r2 for the return type of
the second call and so on. It is obvious that this constraint set only has two solutions. The variable var
and the return type of the method as well as all intermediate placeholders r1 − r3 get either the type
C1 or C2. A first prototype implementation of the Unify algorithm [
          <xref ref-type="bibr" rid="ref3">3</xref>
          ] simply created the cartesian
product of all Or-Constraints, 16 possibilities in this example, and iteratively tried all of them. This
leads to a exponential runtime increase with every added overloaded method call. Even though the
current algorithm is equipped with various optimizations as presented in [
          <xref ref-type="bibr" rid="ref4 ref5">4, 5</xref>
          ] there are still runtime
issues when dealing with many Or-Constraints.
        </p>
        <p>Our global type inference algorithm should construct type solutions in real time. Then, it can
efectively be used as a Java compiler which can deal with large inputs of untyped Java code. Another
use case scenario is as an editor plugin which helps a Java programmer by enabling him to write
untyped Java code and letting our tool insert the missing type statements. For both applications, a short
execution time is vital.</p>
        <p>
          Answer Set programming promises to solve complex search problems in a highly optimized way.
The idea in this paper is to implement the algorithm presented in [
          <xref ref-type="bibr" rid="ref2">2</xref>
          ] as an ASP program and see how
well it handles our type unification problem.
        </p>
      </sec>
    </sec>
    <sec id="sec-3">
      <title>3. Existing Type Unification Algorithm</title>
      <p>The original global type inference algorithm used by the Java-TX1 project proceeds in two phases:
(1) generate a set of subtype constraints, and (2) unify them to obtain a substitution  mapping type
placeholders to types.</p>
      <p>
        This type unification for Java has been studied in several works. Plümicke [
        <xref ref-type="bibr" rid="ref6">6</xref>
        ] presented the basic
ideas and an initial algorithm for GJ [
        <xref ref-type="bibr" rid="ref7">7</xref>
        ], which assumed invariant type parameters without wildcards.
Later extensions added wildcards [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ] and implemented a restricted form [
        <xref ref-type="bibr" rid="ref3 ref8">8, 3</xref>
        ] where bounds were
either Object or another type parameter. The work in [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ] generalized this so that type parameters can
have arbitrary bounds.
      </p>
      <p>Type unification is the process of finding substitutions for type variables so that two given type terms
become compatible under a specified compatibility relation. Formally, given two type terms  1 and  2,
the type unification problem is to find a substitution  mapping type placeholders to type terms such
that:</p>
      <p>( 1) ≤ *  ( 2).
where ≤ * is the transitive closure of the Java subtype relation.</p>
    </sec>
    <sec id="sec-4">
      <title>4. ASP Implementation</title>
      <p>
        Our ASP implementation realizes the algorithm of [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ], meaning that Featherweight Generic Java serves
as our basis, with a type system featuring invariant generics, no wildcards, and no F-bounded type
parameters. The implementation replaces the unification step of the type inference algorithm. So the
input is a set of constraints  and the output is a set of unifiers  .
      </p>
      <p>
        Answer Set Programming has a declarative way of formulating search problems. In ASP you encode
the problem as a set of logical rules and facts and let an ASP solver (like clingo2) compute one or
more stable models (also called answer sets). A stable model is a self-justifying, minimal3, and internally
consistent interpretation of the program [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ].
      </p>
      <p>Translated to our algorithm, this means that the input set of constraints  are the facts and the
implication rules shown in Figure 5 are the logic rules. Thus, a stable model must be a constraint
set that satisfies all the rules, contains the input set of constraints, and is minimal (see definition 1).
Furthermore, the rules of our algorithm Ω are formulated in a way that each input set of constraints 
either ends in a fail condition — meaning there is no possible solution — or leads to a stable model 
that contains correct unifiers of the form  (a) = G for every type placeholder a in the input constraints.</p>
      <sec id="sec-4-1">
        <title>We prove those statements in chapter 5.</title>
        <p>1https://www.dhbw-stuttgart.de/horb/forschung-transfer/forschungsschwerpunkte/typsysteme-fuer-objektorientierte-pro
grammiersprachen/</p>
      </sec>
      <sec id="sec-4-2">
        <title>2https://potassco.org/clingo/</title>
      </sec>
      <sec id="sec-4-3">
        <title>3all rules are satisfied and no proper subset of it satisfies the same conditions</title>
        <p>::=
T, S ::=
N ::=
G ::=
P ::=
.</p>
        <p>T ⋖ T | T = T
a | N
C&lt;P&gt;
C&lt;G&gt;
a | G</p>
        <sec id="sec-4-3-1">
          <title>Constraint</title>
        </sec>
        <sec id="sec-4-3-2">
          <title>Type placeholder or Type</title>
        </sec>
        <sec id="sec-4-3-3">
          <title>Class Type containing type placeholders</title>
        </sec>
        <sec id="sec-4-3-4">
          <title>Class Type not containing type placeholders</title>
        </sec>
        <sec id="sec-4-3-5">
          <title>Well-Formed Parameter</title>
          <p>G are types that contain no type placeholders. A type P is either a type placeholder or a type not
containing type placeholders at all. The reason for those definitions is that they restrict type placeholder
to only appear in the uppermost level of a type parameter list.</p>
          <p>Definition 1 (Stable Model). A stable model (or answer set) of an input set  is a set of constraints 
with  ⊆  that:
• Satisfies all the rules
• Is complete: If the premise of any rule in Ω is satisfied by elements of , then the conclusion of that
rule must also be included in .</p>
          <p>• Is minimal (no unnecessary atoms)</p>
          <p>All extends relations in the input program have to satisfy the WF-Class rule. This restriction is
necessary because our algorithm only supports type placeholders in the uppermost layer of a type
parameter list. WF-Class rule ensures that supertypes generated by the Super rule are well-formed. For
example the class definition class Matrix&lt;A&gt; extends List&lt;List&lt;A&gt;&gt; is not supported by our
algorithm Ω. If an input  contains a constraint Matrix&lt;a&gt; ⋖ b, then the Super rule would require for
.
a b = List&lt;List&lt;a&gt;&gt; constraint where the type List&lt;List&lt;a&gt;&gt; is not well-formed according to
the rules in Figure 4 and therefore not supported by our algorithm.</p>
        </sec>
        <sec id="sec-4-3-6">
          <title>WF-Constraints</title>
          <p>S1, S2, T1, T2 ok
.
 = {S1 = S2, T1 ⋖ T2}
 ok</p>
        </sec>
        <sec id="sec-4-3-7">
          <title>WF-Type</title>
          <p>C&lt;P&gt; ok
WF-Var
a ok</p>
        </sec>
        <sec id="sec-4-3-8">
          <title>WF-Class</title>
          <p>for any a :</p>
          <p>([X/a]N) ok
class C&lt;X&gt; ▷ N ok
4.1. Unification Algorithm
All the implication rules depicted in this chapter can be translated to ASP statements as described in
chapter 6. The whole algorithm is depicted in Figure 5</p>
          <p>We need the Solution-Requirement rule to force at least one type solution for every type placeholder
in the input constraints (see example 4.1).</p>
          <p>Example 4.1: Solution-Requirement
a ⋖ List&lt;x &gt;, a ⋖ List&lt;String&gt;. We want our program to create a unifier for a which requires at
least one constraint of the form a =. . . .. Solution-Requirement forces the ASP solver to choose
one of the following possibilities:
a ⋖ List&lt;x &gt;, a ⋖ List&lt;String&gt;
a =. List&lt;x &gt; a =. List&lt;String&gt;
In this case, it does not matter which one gets chosen as they will both lead to the same result. Let’s
take the a =. List&lt;x &gt; for example. Then we end up with a constraint List&lt;x &gt; ⋖ List&lt;String&gt;
Unify:</p>
        </sec>
        <sec id="sec-4-3-9">
          <title>S-Refl</title>
          <p>T &lt;: T</p>
        </sec>
        <sec id="sec-4-3-10">
          <title>S-Trans</title>
          <p>T1 &lt;: T2 T2 &lt;: T3
T1 &lt;: T3</p>
        </sec>
        <sec id="sec-4-3-11">
          <title>S-Class</title>
          <p>class C&lt;X&gt; ▷ N
C&lt;T&gt; &lt;: [T/X]N
Sau=b.stT-1L</p>
          <p>a ⋖ T2
T1 ⋖ T2
Sau=b.stT-1R</p>
          <p>T2 ⋖ a
T2 ⋖ T1
Sau=b.stG-Param .</p>
          <p>T = C&lt;P1 . . . , a, . . . Pn&gt;
.</p>
          <p>T = C&lt;P1, . . . G, . . . Pn&gt;
Sau=b.stG-Param-Left</p>
          <p>C&lt;P1 . . . , a, . . . Pn&gt; ⋖ b
C&lt;P1, . . . G, . . . Pn&gt; ⋖ b
Reduce .</p>
          <p>C&lt;P1 . . . Pn&gt; = C&lt;P′1 . . . P′n&gt;
P =. P′</p>
        </sec>
        <sec id="sec-4-3-12">
          <title>S-Object</title>
          <p>a ⋖ Object</p>
        </sec>
        <sec id="sec-4-3-13">
          <title>Super</title>
          <p>N ⋖ a
Solution:
Fail Conditions:
Soalu=.tioGn
 (a) = G</p>
        </sec>
        <sec id="sec-4-3-14">
          <title>Fail-Subtype</title>
          <p>C&lt; . . . &gt; ⋖ D&lt; . . . &gt;
Anti Circle Conditions:
Bau=i.ldC&lt; . . . , b, . . . &gt;
a → b</p>
        </sec>
        <sec id="sec-4-3-15">
          <title>Connect</title>
          <p>a → b b → c
a → c</p>
          <p>Sau=b.stT-1Equala =. T2
.</p>
          <p>T1 = T2</p>
        </sec>
        <sec id="sec-4-3-16">
          <title>Swap</title>
          <p>.</p>
          <p>T1 = T2</p>
          <p>.</p>
          <p>T2 = T1
Sau=b.stG-Param-Right
b ⋖ C&lt;T1 . . . , a, . . . Tn&gt;
b ⋖ C&lt;P1, . . . G, . . . Pn&gt;</p>
        </sec>
        <sec id="sec-4-3-17">
          <title>Adapt</title>
          <p>N ⋖ C&lt;P1 . . . Pn&gt; N &lt;: C&lt;P′1 . . . P′n&gt;
. .</p>
          <p>P1 = P′1 . . . P = P′</p>
          <p>N &lt;: N1, . . . , N &lt;: N
for one  ∈ {1, . . . , } :</p>
          <p>N1, . . . , N ok
a =. N</p>
        </sec>
        <sec id="sec-4-3-18">
          <title>Solution-Requirement</title>
          <p>a ⋖ N1, . . . , a ⋖ N
there must exist at least one :</p>
        </sec>
        <sec id="sec-4-3-19">
          <title>Fail-Equals</title>
          <p>.</p>
          <p>C&lt; . . . &gt; = D&lt; . . . &gt;
a =. N
C ̸= D
∅</p>
        </sec>
        <sec id="sec-4-3-20">
          <title>Fail-Circle</title>
          <p>a → a
fail
due to Subst-L. Adapt creates a List&lt;x &gt; =. List&lt;String&gt; constraint and from there we get
. . .
x = String by Reduce. Together with a = List&lt;x &gt; this leads to a = List&lt;String&gt; (by</p>
        </sec>
      </sec>
      <sec id="sec-4-4">
        <title>Subst-Param), which is a correct solution for the given constraints.</title>
        <p>
          4.2. Diferences to the Featherweight Generic Java Type Unification
The ASP unify algorithm Ω presented here is a toned down version of the algorithm presented in
[
          <xref ref-type="bibr" rid="ref2">2</xref>
          ]. The main idea of our ASP prototype is to measure runtime performance especially in relation to
Or-Constraints. When it comes to those core concepts, the ASP algorithm has the same capabilities as
the Type Inference algorithm for Generic Featherweight Java. Though unlike the original algorithm,
we do not create Generic Type Variables. Instead, every type variable is directly assigned a concrete
type. The prototype is not complete in the sense that it cannot find solutions that require polymorphic
methods. However, it still finds all solutions that are possible without involving polymorphism.
        </p>
        <p>
          The Scala prototype of the Unify algorithm, provided with [
          <xref ref-type="bibr" rid="ref2">2</xref>
          ], solves the problem through successive
constraint-set transformations. For example if a constraint a =. N is found, all occurences of a are
replaced by N via substitution.
        </p>
        <p>Our ASP implementation on the other hand does not use any state and therefore cannot change an
existing constraint set. All possible substitutions are laid out by the grounding process. Afterwards
all incorrect solutions are ruled out. This allows for a more declarative programming style, where we
specify the type rules and let ASP Figure out a solution for itself.</p>
      </sec>
    </sec>
    <sec id="sec-5">
      <title>5. Proofs</title>
      <p>Given a set of constraints  and our algorithm Ω as input, the ASP solver attempts to find the smallest
possible set of constraints  . This set contains the input constraints  and satisfies all implication
rules shown in Figure 5. The constraint set  is also called a stable model (see Definition 1). We proved
two key properties of  : soundness and completeness.</p>
      <p>Soundness All produced typings respect the original constraints; the algorithm never returns an
incorrect assignment.</p>
      <p>Completeness If a solution exists, the procedure finds one, as long as the input set does not contain
circles (Def. 2)
See the Full Paper for a detailed version of the proofs.</p>
      <p>Definition 2 (Circular Constraint). A set of constraints a =. N where ∀N ∈ N : fv(N) ̸= ∅ and a contains
all type placeholders used in N (meaning a = fv(N)) is called a circle.</p>
    </sec>
    <sec id="sec-6">
      <title>6. ASP Encoding</title>
      <p>Note: See the Full Paper for the complete program including an example input
ASP statements consist of a head and a body separated by a implication operator ":-": head :- body.
This statement is interpreted as an implication rule. If the premises in the body are satisfied, the facts
stated in the head are deducted. The implication rules defined in Figure 5 are formulated in a way that
can be translated to an ASP program. This chapter explains how to code our algorithm Ω in ASP. At
ifrst, we give a ASP representation for each syntax element used in Figure 3:</p>
      <sec id="sec-6-1">
        <title>For further clarification we will present some examples:</title>
        <p>C&lt;Object&gt; =⇒ type("C", params(Object, null))</p>
        <p>a ⋖ b =⇒ subcons(tph("a"), tph("b"))</p>
        <p>List&lt;a&gt; =⇒ type("List", params(tph("a")))</p>
        <p>In addition to the constraint set , our algorithm requires the class inheritance information of all
classes that appear in the constraints. This information is essential for evaluating subtype relationships
and is encoded in the form of ASP rules. Specifically, for every class declaration in the Java type system
of the form class C&lt;X&gt; extends D&lt;X&gt; we generate a corresponding ASP rule:</p>
      </sec>
      <sec id="sec-6-2">
        <title>Listing 1: Extends Relation as ASP rule</title>
        <p>subtype(type("C", params(X)), type("D", params(X)))</p>
        <p>:- subtype(type("C", params(X))).</p>
        <p>These rules capture the inheritance hierarchy and serve as a static input to the algorithm, just like the
constraint set . Thus, the complete input to our algorithm consists of:
• The set of type constraints 
• The set of ASP rules encoding all relevant extends relations</p>
        <p>This inheritance information is especially relevant for the Super and Adapt rules, both of which
contain premises of the form N &lt;: D&lt; . . . &gt;. For example, when the input set contains a constraint like
a ⋖ N, the algorithm must determine the supertypes of N in order to apply the Super rule. This is exactly
where the encoded inheritance rules come into play. The following example 6.1 illustrates this process
in practice.</p>
      </sec>
      <sec id="sec-6-3">
        <title>This deduces the fact: from the input constraint</title>
        <p>Example 6.1: Creating Supertypes</p>
      </sec>
      <sec id="sec-6-4">
        <title>Assume two classes Vector and List are declared such that</title>
        <p>and let the constraint set be
We need a helper rule in our ASP program that looks like this:
subtype(type(A, P)) :- subcons(type(A, P), _).</p>
        <p>class Vector&lt;X&gt; extends List&lt;X&gt;,
 = { Vector&lt;String&gt; ⋖ a }.
subtype(type("Vector", params(type("String", null)))).
subcons(type("Vector", params(type("String", null))),
tph("a")).</p>
      </sec>
      <sec id="sec-6-5">
        <title>Now, the rule from Listing 1 generates the corresponding supertype:</title>
        <p>subtype(type("Vector", params(type("String", null))),
type("List", params(type("String", null)))).</p>
      </sec>
      <sec id="sec-6-6">
        <title>This reflects the subtyping relationship</title>
        <p>Vector&lt;String&gt; &lt;: List&lt;String&gt;.</p>
        <p>With this information, the Super rule (see Listing 2) can select a valid supertype for a. In this case,
it yields the ASP fact:
equalcons(tph("a"),</p>
        <p>type("List", params(type("String", null)))).
which corresponds to the constraint
a =. List&lt;String&gt;.</p>
      </sec>
      <sec id="sec-6-7">
        <title>Listing 2: Super-Rule</title>
        <p>{equalcons(tph(A), type(D,DP)): subtype(type(C,CP), type(D,DP))}=1
:- subcons(type(C, CP), tph(A)).</p>
      </sec>
      <sec id="sec-6-8">
        <title>The vital part is the generation of the Cartesian product of the Or-Constraints.</title>
        <p>subcons(A,B); orCons(C,D) :- orCons(subcons(A,B), subcons(C,D)).
The operator ";" tells ASP to consider either the left or the right side. By supplying multiple
OrConstraints this way, the ASP interpreter will consider all combinations, the Cartesian product of the</p>
      </sec>
      <sec id="sec-6-9">
        <title>Or-Constraints.</title>
        <p>The rules implying a failure ∅ are translated by leaving the head of the ASP statement empty. If the
body of such rules is satisfied, the algorithm considers the deduction as incorrect. See an example in</p>
      </sec>
      <sec id="sec-6-10">
        <title>Listing 3 that shows an ASP encoding of the Fail-Equals rule.</title>
      </sec>
      <sec id="sec-6-11">
        <title>Listing 3: Fail-Equals rule in ASP</title>
        <p>:- equalcons(type(A, _), type(B, _)), A != B.</p>
      </sec>
    </sec>
    <sec id="sec-7">
      <title>7. Benchmark</title>
      <p>To evaluate the performance and practical applicability of our ASP implementation of the Unify algorithm
for FGJ, we conducted two benchmarks:
1. Massive Or-Constraints: Tests Unify’s ability to create and handle Cartesian products of big</p>
      <sec id="sec-7-1">
        <title>Or-Constraints.</title>
        <p>2. Matrix Example: Typical benchmark used to test Java-TX type inference, where the Unify
algorithm has to consider many possible variations of supertypes of the class Matrix.</p>
        <p>Even though import statements in standard Java are purely syntactic and used only to avoid writing
fully qualified class names, the current Java-TX implementation uses them to limit the search space for
missing type annotations. The algorithm only considers “imported” types. This makes Java-TX type
inference unsuitable for typical Java development, where users expect to reuse classes without needing
to import them in advance. In contrast, our ASP-based Unify algorithm aims to lift this restriction
by considering the entire standard Java library as potential type candidates. To demonstrate this, we
introduce the following benchmark program shown in Listing 4:</p>
        <p>Listing 4: Benchmark
public class ThreeAdds {
void addTest(a, b, c, d){
a.add(b);
b.add(c);
c.add(d);
d.add(a);
}</p>
        <p>}</p>
        <p>The addTest declaration in Listing 4 is missing type annotations for its parameters a,b,c,d. We
want our ASP implementation of the Unify algorithm to calculate all possible typings for the missing
type annotations. Therefore, we have to first generate a set of constraints representing the input
problem. The method addTest has three calls a.add(...), which leads to three large Or-Constraints.
We use the Open-JDK standard library of the version 21, which contains nearly twenty thousand
classes, including inner classes. They have 200 diferent add methods all together. This leads to four
Or-Constraints with 200 possibilities, meaning a Cartesian product with 1.6 billion elements. clingo
ifnds a solution in under half a second.</p>
        <p>Listing 5: Solution for Benchmark 4
public class ThreeAdds {
void addTest(javax.naming.directory.Attribute a,
java.util.concurrent.DelayQueue b,
The program in Listing 4 admits an unexpectedly large number of valid type solutions, as many add
methods in the Java standard library accept Object as an argument. One such solution is shown in
Listing 5 and compiles under OpenJDK 17. We assume clingo spends most time in grounding, since
ifnding a single valid typing is trivial once all possibilities are enumerated.</p>
        <p>
          The second benchmark, the Matrix example shown in Listing 6, is also used by the Java-TX project
as a functionality demo and stress test. The grayed-out types in the method header are to be inferred
by our algorithm, including those omitted via Java’s var keyword [
          <xref ref-type="bibr" rid="ref10">10</xref>
          ]. Multiple valid solutions exist
beyond Matrix mul(Matrix m), since supertypes of Matrix and even wildcard types are permissible.
For instance, Vector&lt;Vector&lt;?extendsInteger&gt;&gt; is a valid parameter type for m. Which makes
this benchmark especially hard for the original Unify algorithm, because adding wildcards enables a lot
of new typing possibilities and increases the search space. Our prototype Unify implementation does
not yet support wildcards, making direct comparison to the original Java-TX implementation (in Java)
imperfect. Nevertheless, while Java-TX often needs minutes to enumerate all solutions, our ASP-based
approach finds them in milliseconds.
        </p>
      </sec>
      <sec id="sec-7-2">
        <title>Listing 6: Matrix Benchmark</title>
        <p>class Matrix extends Vector&lt;Vector&lt;Integer&gt;&gt; {
Matrix mul(Matrix m) {
var ret = new Matrix();
var i = 0;
while(i &lt; size()) {
var v1 = this.elementAt(i);
var v2 = new Vector&lt;Integer&gt;();
var j = 0;
while(j &lt; v1.size()) {
var erg = 0;
var k = 0;
while(k &lt; v1.size()) {
erg = erg + v1.elementAt(k)</p>
        <p>* m.elementAt(k).elementAt(j);
k++; }
v2.addElement(new Integer(erg));
j++; }
ret.addElement(v2);
i++; }
return ret; } }</p>
      </sec>
    </sec>
    <sec id="sec-8">
      <title>8. Outcome, Conclusion, and Future Work</title>
      <p>ASP handles Or-Constraints eficiently. We evaluated our ASP-based unification algorithm on an
extended version of the constraints from Figure 2, increasing the complexity by adding stacked method
calls. Even with ten such calls, clingo succeeded in under 50 ms, whereas the current Java
implementation4 required several seconds for the same input.</p>
      <sec id="sec-8-1">
        <title>4https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore</title>
        <p>
          It is important to note that this benchmark avoids wildcard types to ensure a fair comparison, as the
Java implementation supports them, whereas the ASP version does not. In this first study on applying
ASP to Java type inference, wildcard types were deliberately omitted. Including wildcards makes subtype
checking in Java Turing complete [
          <xref ref-type="bibr" rid="ref11">11</xref>
          ], which can pose challenges for clingo’s grounding process [
          <xref ref-type="bibr" rid="ref12">12</xref>
          ].
Future work could investigate grounding-free ASP solvers [
          <xref ref-type="bibr" rid="ref13">13</xref>
          ] to overcome these challenges and enable
full wildcard support.
        </p>
      </sec>
    </sec>
    <sec id="sec-9">
      <title>Declaration on Generative AI</title>
      <p>In preparation of this work, the authors used AI-based tools for spell and grammar checking. All ideas
and results presented are our own and we take full responsibility for the accuracy and integrity of the
publication.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          [1]
          <string-name>
            <given-names>M.</given-names>
            <surname>Plümicke</surname>
          </string-name>
          ,
          <article-title>Java type unification with wildcards</article-title>
          , in: D.
          <string-name>
            <surname>Seipel</surname>
            ,
            <given-names>M.</given-names>
          </string-name>
          <string-name>
            <surname>Hanus</surname>
            ,
            <given-names>A</given-names>
          </string-name>
          . Wolf (Eds.),
          <source>Applications of Declarative Programming and Knowledge Management, 17th International Conference, INAP 2007, and 21st Workshop on Logic Programming</source>
          ,
          <source>WLP</source>
          <year>2007</year>
          , Würzburg, Germany, October 4-
          <issue>6</issue>
          ,
          <year>2007</year>
          , Revised Selected Papers, volume
          <volume>5437</volume>
          of Lecture Notes in Computer Science, Springer,
          <year>2007</year>
          , pp.
          <fpage>223</fpage>
          -
          <lpage>240</lpage>
          . doi:
          <volume>10</volume>
          .1007/978-3-
          <fpage>642</fpage>
          -00675-3\_
          <fpage>15</fpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          [2]
          <string-name>
            <given-names>A.</given-names>
            <surname>Stadelmeier</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Plümicke</surname>
          </string-name>
          ,
          <string-name>
            <given-names>P.</given-names>
            <surname>Thiemann</surname>
          </string-name>
          ,
          <article-title>Global type inference for featherweight generic java</article-title>
          ,
          <source>CoRR abs/2205</source>
          .08768 (
          <year>2022</year>
          ). URL: https://doi.org/10.48550/arXiv.2205.08768. doi:
          <volume>10</volume>
          .48550/arX iv.
          <volume>2205</volume>
          .08768. arXiv:
          <volume>2205</volume>
          .
          <fpage>08768</fpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          [3]
          <string-name>
            <given-names>F.</given-names>
            <surname>Steurer</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Plümicke</surname>
          </string-name>
          ,
          <article-title>Erweiterung und Neuimplementierung der Java Typunifikation</article-title>
          , in: J.
          <string-name>
            <surname>Knoop</surname>
            ,
            <given-names>M.</given-names>
          </string-name>
          <string-name>
            <surname>Stefen</surname>
          </string-name>
          , B. T. y Widemann (Eds.),
          <source>Proceedings of the 35th Annual Meeting of the GI Working Group Programming Languages and Computing Concepts</source>
          ,
          <source>number 482 in Research Report, Faculty of Mathematics and Natural Sciences</source>
          , University of Oslo,
          <year>2018</year>
          , pp.
          <fpage>134</fpage>
          -
          <lpage>149</lpage>
          .
          <source>ISBN 978-82-7368-447-9</source>
          , (in German).
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          [4]
          <string-name>
            <given-names>M.</given-names>
            <surname>Plümicke</surname>
          </string-name>
          ,
          <article-title>Optimization of the Java type unification</article-title>
          , in: J.
          <string-name>
            <surname>Knoop</surname>
            ,
            <given-names>M.</given-names>
          </string-name>
          <string-name>
            <surname>Stefen</surname>
          </string-name>
          , B. T. y Widemann (Eds.),
          <source>Proceedings of the 35th Annual Meeting of the GI Working Group Programming Languages and Computing Concepts</source>
          ,
          <source>number 482 in Research Report, Faculty of Mathematics and Natural Sciences</source>
          , UNIVERSITY OF OSLO,
          <year>2018</year>
          , pp.
          <fpage>3</fpage>
          -
          <lpage>12</lpage>
          . ISBN 978-82-7368-447-9.
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          [5]
          <string-name>
            <given-names>M.</given-names>
            <surname>Plümicke</surname>
          </string-name>
          ,
          <article-title>Optimization of the Java Type Unification</article-title>
          , in: S. Schwarz, M. Wenzel (Eds.),
          <source>Proceedings of the 37th Workshop on (Constraint) Logic Programming (WLP</source>
          <year>2023</year>
          ),
          <year>2023</year>
          . URL: https://dbs.informatik.uni-halle.de/wlp2023/WLP2023_Pl%
          <article-title>C3%BCmicke_Optimization%20of%20 the%20Java%20Type%20Unification</article-title>
          .pdf.
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          [6]
          <string-name>
            <given-names>M.</given-names>
            <surname>Plümicke</surname>
          </string-name>
          , Type Unification in Generic-Java, in: M.
          <string-name>
            <surname>Kohlhase</surname>
          </string-name>
          (Ed.),
          <source>Proceedings of 18th International Workshop on Unification (UNIF'04)</source>
          , Cork,
          <year>2004</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          [7]
          <string-name>
            <given-names>G.</given-names>
            <surname>Bracha</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Odersky</surname>
          </string-name>
          ,
          <string-name>
            <given-names>D.</given-names>
            <surname>Stoutamire</surname>
          </string-name>
          , P. Wadler,
          <article-title>GJ: Extending the Java Programming Language with type parameters</article-title>
          ,
          <year>1998</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          [8]
          <string-name>
            <given-names>F.</given-names>
            <surname>Steurer</surname>
          </string-name>
          ,
          <article-title>Implementierung eines Typunifikationsalgorithmus für Java 8</article-title>
          ,
          <string-name>
            <given-names>DHBW</given-names>
            <surname>Stuttgart</surname>
          </string-name>
          , Campus Horb, Studienarbeit,
          <year>2016</year>
          . (in German).
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          [9]
          <string-name>
            <given-names>P.</given-names>
            <surname>Ferraris</surname>
          </string-name>
          , V. Lifschitz,
          <article-title>Mathematical foundations of answer set programming</article-title>
          .,
          <source>in: We will show them!(1)</source>
          ,
          <year>2005</year>
          , pp.
          <fpage>615</fpage>
          -
          <lpage>664</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          [10]
          <string-name>
            <given-names>B.</given-names>
            <surname>Goetz</surname>
          </string-name>
          , Jep 286:
          <article-title>Local-variable type inference</article-title>
          , https://openjdk.org/jeps/286,
          <year>2018</year>
          . Accessed:
          <fpage>2025</fpage>
          -07-26.
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          [11]
          <string-name>
            <given-names>R.</given-names>
            <surname>Grigore</surname>
          </string-name>
          ,
          <article-title>Java generics are turing complete</article-title>
          ,
          <source>ACM SIGPLAN Notices</source>
          <volume>52</volume>
          (
          <year>2017</year>
          )
          <fpage>73</fpage>
          -
          <lpage>85</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          [12]
          <string-name>
            <given-names>B.</given-names>
            <surname>Kaufmann</surname>
          </string-name>
          ,
          <string-name>
            <given-names>N.</given-names>
            <surname>Leone</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            <surname>Perri</surname>
          </string-name>
          , T. Schaub,
          <article-title>Grounding and solving in answer set programming</article-title>
          ,
          <source>AI</source>
          magazine
          <volume>37</volume>
          (
          <year>2016</year>
          )
          <fpage>25</fpage>
          -
          <lpage>32</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          [13]
          <string-name>
            <given-names>J. Arias</given-names>
            <surname>Herrero</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M. Carro</given-names>
            <surname>Liñares</surname>
          </string-name>
          ,
          <string-name>
            <given-names>Z.</given-names>
            <surname>Chen</surname>
          </string-name>
          , G. Gupta,
          <article-title>Constraint answer set programming without grounding and its applications (</article-title>
          <year>2019</year>
          ).
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>