title: When is generic return value of function casted after type erasure?
body: <p><em>This question was inducted by <a href="https://stackoverflow.com/questions/34476905/java-casting-method-without-knowing-what-to-cast-to/34477143#34477143">this StackOverflow question about unsafe casts: Java Casting method without knowing what to cast to</a>. While answering the question I encountered this behaviour I couldn't explain based on purely the specification</em></p>
  
  <p>I found the following statement in The Java Tutorials at the
  Oracle docs:</p>
  
  <blockquote>
    <ul>
    <li>Insert type casts if necessary to preserve type safety.
    <a href="https://docs.oracle.com/javase/tutorial/java/generics/erasure.html" rel="nofollow noreferrer"><em>The Java Tutorials: Type Erasure</em></a></li>
    </ul>
  </blockquote>
  
  <p>It is not explained what <em>"if necessary"</em> means exactly, and
  I've found <strong>no mention about these casts</strong> in the <a href="https://docs.oracle.com/javase/specs/jls/se8/html/index.html" rel="nofollow noreferrer">Java Language
  Specification</a> at all, so I started to experiment.</p>
  
  <p>Let's look at the following piece of code:</p>
  
  <pre><code>// Java source
  public static &lt;T&gt; T identity(T x) {
      return x;
  }
  public static void main(String args[]) {
      String a = identity("foo");
      System.out.println(a.getClass().getName());
      // Prints 'java.lang.String'
  
      Object b = identity("foo");
      System.out.println(b.getClass().getName());
      // Prints 'java.lang.String'
  }
  </code></pre>
  
  <p>Compiled with <code>javac</code> and decompiled with <a href="http://jd.benow.ca/" rel="nofollow noreferrer">the Java Decompiler</a>:</p>
  
  <pre><code>// Decompiled code
  public static void main(String[] paramArrayOfString)
  {
      // The compiler inserted a cast to String to ensure type safety
      String str = (String)identity("foo");
      System.out.println(str.getClass().getName());
  
      // The compiler omitted the cast, as it is not needed
      // in terms of runtime type safety, but it actually could
      // do an additional check. Is it some kind of optimization
      // to decrease overhead? Where is this behaviour specified?
      Object localObject1 = identity("foo");
      System.out.println(localObject1.getClass().getName());
  }
  </code></pre>
  
  <p>I can see that there is a cast which ensures type safety in the first case,
  but in the second case it is omitted. It is
  fine of course, because I want to store the return value in an <code>Object</code>
  typed variable, so the cast is not strictly necessary as per type safety. However it leads to an interesting behaviour with unsafe casts:</p>
  
  <pre><code>public class Erasure {
      public static &lt;T&gt; T unsafeIdentity(Object x) {
          return (T) x;
      }
  
      public static void main(String args[]) {
          // I would expect c to be either an Integer after this
          // call, or a ClassCastException to be thrown when the
          // return value is not Integer
          Object c = Erasure.&lt;Integer&gt;unsafeIdentity("foo");
          System.out.println(c.getClass().getName());
          // but Prints 'java.lang.String'
      }
  }
  </code></pre>
  
  <p>Compiled and decompiled, I see no type cast to ensure correct return type at runtime:</p>
  
  <pre><code>// The type of the return value of unsafeIdentity is not checked,
  // just as in the second example.
  Object localObject2 = unsafeIdentity("foo");
  System.out.println(localObject2.getClass().getName());
  </code></pre>
  
  <p>This means that if a generic function <em>should</em> return an object of a given
  type, it is not guaranteed it <em>will</em> return that type ultimately. An
  application using the above code will fail at the first point where it tries
  to cast the return value to an <code>Integer</code> if it does so at all, so I feel like
  it breaks the <a href="https://en.wikipedia.org/wiki/Fail-fast" rel="nofollow noreferrer">fail-fast principle</a>.</p>
  
  <p><strong>What are the exact rules of the compiler inserting this cast during
  compilation that ensures type safety and where are those rules specified?</strong></p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>I see that the compiler will not dig into the code and try to prove that the generic code really returns what it should, but it could insert an assertation, or at least a type cast (which it already does in specific cases, as seen in the first example) to ensure correct return type, so the latter would throw a <code>ClassCastException</code>:</p>
  
  <pre><code>// It could compile to this, throwing ClassCastException:
  Object localObject2 = (Integer)unsafeIdentity("foo");
  </code></pre>