title: Scala: Case class unapply vs a manual implementation and type erasure
body: <p>I'm trying to understand what Scala does with Case Classes that makes them somehow immune to type erasure warnings.</p>
  <p>Let's say we have the following, simple class structure. It's basically an <code>Either</code>:</p>
  <pre class="lang-scala prettyprint-override"><code>abstract class BlackOrWhite[A, B]
  
  case class Black[A,B]( val left: A ) extends BlackOrWhite[A,B]
  
  case class White[A,B]( val right: B ) extends BlackOrWhite[A,B]
  </code></pre>
  <p>And you're trying to use it like this:</p>
  <pre class="lang-scala prettyprint-override"><code>object Main extends App {
  
      def echo[A,B] ( input: BlackOrWhite[A,B] ) = input match {
          case Black(left) =&gt; println( &quot;Black: &quot; + left )
          case White(right) =&gt; println( &quot;White: &quot; + right )
      }
  
      echo( Black[String, Int]( &quot;String!&quot; ) )
      echo( White[String, Int]( 1234 ) )
  }
  </code></pre>
  <p>Everything compiles and runs without any problems. However, when I try implementing the <code>unapply</code> method myself, the compiler throws a warning. I used the following class structure with the same <code>Main</code> class above:</p>
  <pre class="lang-scala prettyprint-override"><code>abstract class BlackOrWhite[A, B]
  
  case class Black[A,B]( val left: A ) extends BlackOrWhite[A,B]
  
  object White {
  
      def apply[A,B]( right: B ): White[A,B] = new White[A,B](right)
  
      def unapply[B]( value: White[_,B] ): Option[B] = Some( value.right )
  
  }
  
  class White[A,B]( val right: B ) extends BlackOrWhite[A,B]
  </code></pre>
  <p>Compiling that with the <code>-unchecked</code> flag issues the following warning:</p>
  <pre><code>[info] Compiling 1 Scala source to target/scala-2.9.1.final/classes...
  [warn] src/main/scala/Test.scala:41: non variable type-argument B in type pattern main.scala.White[_, B] is unchecked since it is eliminated by erasure
  [warn]         case White(right) =&gt; println( &quot;White: &quot; + right )
  [warn]                   ^
  [warn] one warning found
  [info] Running main.scala.Main
  </code></pre>
  <p>Now, I understand type erasure and I've tried to get around the warning with <code>Manifests</code> (to no avail so far), but what is the difference between the two implementations? Are case classes doing something that I need to add in? Can this be circumvented with <code>Manifests</code>?</p>
  <p>I even tried running the case class implementation through the scala compiler with the <code>-Xprint:typer</code> flag turned on, but the <code>unapply</code> method looks pretty much like I expected:</p>
  <pre><code>case &lt;synthetic&gt; def unapply[A &gt;: Nothing &lt;: Any, B &gt;: Nothing &lt;: Any](x$0: $iw.$iw.White[A,B]): Option[B] = if (x$0.==(null))
      scala.this.None
  else
      scala.Some.apply[B](x$0.right);
  </code></pre>