title: How does erasure work in Kotlin?
body: <p>In Kotlin, the following code compiles:</p>
  
  <pre><code>class Foo {
      fun bar(foo: List&lt;String&gt;): String {
          return ""
      }
  
      fun bar(foo: List&lt;Int&gt;): Int {
          return 2;
      }
  }
  </code></pre>
  
  <p>This code, however, does not: </p>
  
  <pre><code>class Foo {
      fun bar(foo: List&lt;String&gt;): String {
          return ""
      }
  
      fun bar(foo: List&lt;Int&gt;): String {
          return "2";
      }
  }
  </code></pre>
  
  <p>Compiling this will cause the following error:</p>
  
  <pre><code>Error:(8, 5) Kotlin: Platform declaration clash: The following declarations have the same JVM signature (foo(Ljava/util/List;)Ljava/lang/String;):
      fun foo(layout: List&lt;Int&gt;): String
      fun foo(layout: List&lt;String&gt;): String
  </code></pre>
  
  <p>In Java, neither example will compile: </p>
  
  <pre><code>class Foo {
      String bar(List&lt;Integer&gt; foo) {
          return "";
      }
  
      Integer bar(List&lt;String&gt; foo) {
          return 2;
      }
  }
  
  class Foo {
      String bar(List&lt;Integer&gt; foo) {
          return "";
      }
  
      String bar(List&lt;String&gt; foo) {
          return "2";
      }
  }
  </code></pre>
  
  <p>Unsurprisingly, both of the prior snippets generate the familiar compiler error:</p>
  
  <pre><code>Error:(13, 12) java: name clash: bar(java.util.List&lt;java.lang.String&gt;) and bar(java.util.List&lt;java.lang.Integer&gt;) have the same erasure
  </code></pre>
  
  <p>What surprises me is that the first Kotlin example works at all, and second, if it works, why does the second Kotlin example fail? Does Kotlin consider a method's return type as part of its signature? Furthermore, why do method signatures in Kotlin respect the full parameter type, in contrast with Java?</p>