milessabin / si2712fix-demo

This repository contains a minimal SBT project for experimenting with a fix for SI-2712
19 stars 3 forks source link

How does the fix work with inheritance? #3

Open xeno-by opened 8 years ago

xeno-by commented 8 years ago

To quote Dmitry from https://github.com/milessabin/scala/commit/d91fda48ba0a2754beaeb0b719bed75b3dcce38e:

trait A[T1, T2] { }
trait B[T1, T2] { }
class C extends A[T, Long] with B[T, Double] { }

object Test {
  def meh[M[_], A](x: M[A]): M[A] = x
  meh(new C) //  <----------------------- what's return type here? is it A or B or A with B?
}
milessabin commented 8 years ago

Whatever the current actual behaviour is, I think it should be consistent with the behaviour for,

trait A[T]
trait B[T]
class C[T] extends A[T] with B[T]
milessabin commented 8 years ago

I think we're doing the right thing here,

object Test {
  trait A[T1, T2] { }
  trait B[T1, T2] { }
  class C[T] extends A[T, Long] with B[T, Double]
  class CB extends A[Boolean, Long] with B[Boolean, Double]

  trait A2[T]
  trait B2[T]
  class C2[T] extends A2[T] with B2[T]
  class CB2 extends A2[Boolean] with B2[Boolean]

  def meh[M[_], A](x: M[A]): M[A] = x

  meh(new C[Boolean]): C[Boolean]
  meh(new CB): A[Boolean, Long]
  meh(new C2[Boolean]): C2[Boolean]
  meh(new CB2): A2[Boolean]
}

The results are consistent between the two cases, and the second case behaves the same as vanilla 2.11.8.

DarkDimius commented 8 years ago

@milessabin, in your examples, you're driving the type inference by expected type, providing one more discriminator. I'm not sure if this implementation would always infer the same type in absence of such a discriminator.

milessabin commented 8 years ago

Sorry, that was meant to be illustrative. We get the same result even without the expected type,

object Test {
  trait A[T1, T2] { } 
  trait B[T1, T2] { } 
  class C[T] extends A[T, Long] with B[T, Double]
  class CB extends A[Boolean, Long] with B[Boolean, Double]

  trait A2[T]
  trait B2[T]
  class C2[T] extends A2[T] with B2[T]
  class CB2 extends A2[Boolean] with B2[Boolean]

  def meh[M[_], A](x: M[A]): M[A] = x 

  val m0 = meh(new C[Boolean])
  m0: C[Boolean]
  val m1 = meh(new CB) 
  m1: A[Boolean, Long]
  val m2 = meh(new C2[Boolean])
  m2: C2[Boolean]
  val m3 = meh(new CB2)
  m3: A2[Boolean]
}
milessabin commented 8 years ago

Any thoughts on this or should I close?

DarkDimius commented 8 years ago

Feel free to close, though I have a fear that such approach may create a lot of problems long term. It seems that with this PR, the full linearisation would have one more way of being important. One of possible issues:

milessabin commented 8 years ago

I take your point, however this behavior is consistent the current behaviour of Scala 2.11/12. For example, with vanilla (ie. not including my patch) Scala 2.11.8,

scala> :paste
// Entering paste mode (ctrl-D to finish)

trait A[T]
trait B[T]
class C extends A[Boolean] with B[Boolean]

// Exiting paste mode, now interpreting.

defined trait A
defined trait B
defined class C

scala> def meh[M[_], A](x: M[A]): M[A] = x
warning: there was one feature warning; re-run with -feature for details
meh: [M[_], A](x: M[A])M[A]

scala> meh(new C)
res0: A[Boolean] = C@38cccef

For better or worse linearization order shows through in Scala 2. I don't think it would be reasonable to expect this fix to address that ... that's what Dotty is for, no?