Open xeno-by opened 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]
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.
@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.
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]
}
Any thoughts on this or should I close?
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:
User has code class A extends B with C
, where B & C are defined in library:
trait C extends M[Int] {}
trait B {}
This would mean that meh(new A): M[Int]
now, if library author for some reason decides to introduce a supertrait in B, he should be very careful about making it have type arguments, as it can break code that user had written code:
trait B extends M2[Double] {}
meh(new A): M2[Double]
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?
To quote Dmitry from https://github.com/milessabin/scala/commit/d91fda48ba0a2754beaeb0b719bed75b3dcce38e: