title: scala's type checker doesn't recognize types in abstract path-dependent classes scenario
body: <p>Let's define a trait with an abstract class</p>
  
  <pre><code>object Outer {
  
    trait X {
      type T
      val empty: T
    }
  </code></pre>
  
  <p>Now we can make an instance of it:</p>
  
  <pre><code>  val x = new X {
      type T = Int
      val empty = 42
    }
  </code></pre>
  
  <p>Scala now recognizes, that <code>x.empty</code> is an <code>Int</code>:</p>
  
  <pre><code>  def xEmptyIsInt = x.empty: Int
  </code></pre>
  
  <p>Now, let's define an other class</p>
  
  <pre><code>  case class Y(x: X) extends X {
      type T = x.T
      val empty = x.empty
    }
  </code></pre>
  
  <p>and make an instance of it</p>
  
  <pre><code>  val y = Y(x)
  </code></pre>
  
  <p>But now Scala, isn't able to infer that <code>y.empty</code> is of type <code>Int</code>. The following</p>
  
  <pre><code>  def yEmptyIsInt = y.empty: Int
  </code></pre>
  
  <p>now produces an error message:</p>
  
  <pre><code>error: type mismatch;
  found   : y.x.T
  required: Int
         y.empty : Int
  </code></pre>
  
  <p>Why is this the case? Is this a scala bug? </p>
  
  <p>We can mitigate this issue by introducing a parameters to the case class:</p>
  
  <pre><code>  case class Z[U](x: X { type T = U }) extends X {
      type T = U
      val empty = x.empty
    }
  </code></pre>
  
  <p>Then it works again</p>
  
  <pre><code>  val z = Z(x)
    def zEmptyIsInt: Int = z.empty
  </code></pre>
  
  <p>But we always have to mention all the types inside X at call-site. This ideally should be an implementation detail which leads to the following approach:</p>
  
  <pre><code>  case class A[U &lt;: X](z: U) extends X {
      type T = z.T
      val empty = z.empty
    }
  </code></pre>
  
  <p>This also mitigates the issue</p>
  
  <pre><code>  val a = A(x)
    def aEmptyIsInt: Int = a.empty
  
  }
  </code></pre>
  
  <p>So, to summarize, my questions are the following: Why does the simple case doesn't work? Is this a valid workaround? What other problems might come up when we follow one of the two workaround approaches? Is there a better approach? </p>