title: Generic type parameters inference in method chaining
body: <p>After reading <a href="https://stackoverflow.com/questions/43869399/initialize-an-immutablemap-with-explicit-types">this question</a>, I've started to think about generic methods <strong>in Java 8</strong>. Specifically, what happens with generic type parameters when methods are chained. </p>
  
  <p>For this question, I will use some generic methods from Guava's <code>ImmutableMap</code>,  but my question is more general and can be applied to all chained generic methods.</p>
  
  <p>Consider <code>ImmutableMap.of</code> generic method, which has this signature:</p>
  
  <pre><code>public static &lt;K, V&gt; ImmutableMap&lt;K, V&gt; of(K k1, V v1)
  </code></pre>
  
  <p>If we use this generic method to declare a <code>Map</code>, the compiler infers the generic types correctly:</p>
  
  <pre><code>Map&lt;String, String&gt; map = ImmutableMap.of("a", "b");
  </code></pre>
  
  <p>I'm aware that from Java 8 onwards, the compiler inference mechanism has been improved, i.e. it infers the generic types of methods from the context, which in this case is an assignment. </p>
  
  <p>The context can also be a method call:</p>
  
  <pre><code>void someMethod(Map&lt;String, String&gt; map) { 
      // do something with map
  }
  
  someMethod(ImmutableMap.of("a", "b"));
  </code></pre>
  
  <p>In this case, the generic types of <code>ImmutableMap.of</code> are inferred from the generic types of the argument of <code>someMethod</code>, ie. <code>Map&lt;String, String&gt; map</code>.</p>
  
  <p>But when I attempt to use <code>ImmutableMap.builder()</code>and chain methods to build my map, I get a compilation error:</p>
  
  <pre><code>Map&lt;String, String&gt; map = ImmutableMap.builder()
      .put("a", "b")
      .build(); // error here: does not compile
  </code></pre>
  
  <p>The error is:</p>
  
  <pre><code>Error:(...) java: incompatible types: 
  ImmutableMap&lt;Object, Object&gt; cannot be converted to Map&lt;String, String&gt;
  </code></pre>
  
  <p>(I've removed the packages names from the error message for the sake of clarity).</p>
  
  <p>I understand the error and why it happens. The first method in the chain is <code>ImmutableMap.builder()</code> and the compiler has no context to infer the type parameters, so it fallbacks to <code>&lt;Object, Object&gt;</code>. Then, the <code>ImmutableMap.Builder.put</code> method is invoked with arguments <code>"a"</code> and <code>"b"</code> and finally the <code>ImmutableMap.Builder.build()</code> method is called, which returns an <code>ImmutableMap&lt;Object, Object&gt;</code>. This is why I'm receiving the incompatible types error: when I attempt to assign this <code>ImmutableMap&lt;Object, Object&gt;</code> instance to my <code>Map&lt;String, String&gt; map</code> variable, the compiler complains.</p>
  
  <p>I even know how to solve this error: I could either break the method chain into two lines, so that the compiler can now infer the generic type parameters:</p>
  
  <pre><code>ImmutableMap.Builder&lt;String, String&gt; builder = ImmutableMap.builder();
  Map&lt;String, String&gt; map = builder.put("a", "b").build();
  </code></pre>
  
  <p>Or I could explicitly provide the generic type parameters:</p>
  
  <pre><code>Map&lt;String, String&gt; map = ImmutableMap.&lt;String, String&gt;builder()
      .put("a", "b")
      .build();
  </code></pre>
  
  <p>So my question is not how to solve/workaround this, but why I do need to provide the generic type parameters explicitly when chaining generic methods. Or, in other words, why can't the compiler infer the generic type parameters in a method chain, especially when the method chain is at the right side of an assignment? If it were possible, would this break something else (I mean, related to the generics type system)?</p>
  
  <p><strong>EDIT</strong>:</p>
  
  <p>There's a <a href="https://stackoverflow.com/q/24794924/1876620">question asking the same</a>, however the only answer it has doesn't clearly explain why the compiler doesn't infer the generic type parameters in a method chain. All it has is a reference to a small paragraph in the <a href="https://jcp.org/aboutJava/communityprocess/final/jsr335/index.html" rel="nofollow noreferrer">JSR-000335 Lambda Expressions for the JavaTM Programming Language Final Release for Evaluation</a> (spec part D):</p>
  
  <blockquote>
    <p>There has been some interest in allowing inference to "chain": in a().b(), passing type information from the invocation of b to the invocation of a. This adds another dimension to the complexity of the inference algorithm, as partial information has to pass in both directions; it only works when the erasure of the return type of a() is fixed for all instantiations (e.g. List). This feature would not fit very well into the poly expression model, since the target type cannot be easily derived; but perhaps with additional enhancements it could be added in the future.</p>
  </blockquote>
  
  <p>So I think I might rephrase my original question as follows:</p>
  
  <ul>
  <li>What would these additional enhancements be?</li>
  <li>How is it that passing partial information in both directions would make the inference algorithm more complex?</li>
  <li>Why would this only work when the erasure of the return type of a() is fixed for all instantiations (e.g. List)? In fact, what does it mean that the erasure of the return type of a method is fixed for all instantiations?</li>
  <li>Why wouldn't this feature fit very well into the poly expression model? Actually, what is the poly expression model? And why couldn't the target type be easily derived in this case?</li>
  </ul>