diff options
author | Martin Odersky <odersky@gmail.com> | 2014-05-13 17:03:36 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-05-30 14:34:33 +0200 |
commit | ed1d5f310951715d95873c56f64195ac3ee45817 (patch) | |
tree | 755803d8e6badeac510de960b63ecec8fd2d6916 /tests/pos/t2421_delitedsl.scala | |
parent | 7bc5cd18ee4f881f223e9a317e6c6a329942d5af (diff) | |
download | dotty-ed1d5f310951715d95873c56f64195ac3ee45817.tar.gz dotty-ed1d5f310951715d95873c56f64195ac3ee45817.tar.bz2 dotty-ed1d5f310951715d95873c56f64195ac3ee45817.zip |
Fix of pos/t2454
"_" type paraeters need to be given fresh names.
Diffstat (limited to 'tests/pos/t2421_delitedsl.scala')
-rw-r--r-- | tests/pos/t2421_delitedsl.scala | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/tests/pos/t2421_delitedsl.scala b/tests/pos/t2421_delitedsl.scala new file mode 100644 index 000000000..554702a03 --- /dev/null +++ b/tests/pos/t2421_delitedsl.scala @@ -0,0 +1,39 @@ +trait DeliteDSL { + abstract class <~<[-From, +To] extends (From => To) + implicit def trivial[A]: A <~< A = new (A <~< A) {def apply(x: A) = x} + + trait Forcible[T] + object Forcible { + def factory[T](f: T => Forcible[T]) = new (T <~< Forcible[T]){def apply(x: T) = f(x)} + } + + case class DeliteInt(x: Int) extends Forcible[Int] + + implicit val forcibleInt: DeliteDSL.this.<~<[Int,DeliteDSL.this.Forcible[Int]] = + Forcible.factory((x: Int) => DeliteInt(x)) + + import scala.collection.Traversable + class DeliteCollection[T](val xs: Traversable[T]) { + // must use existential in bound of P, instead of T itself, because we cannot both have: + // Test.x below: DeliteCollection[T=Int] -> P=DeliteInt <: Forcible[T=Int], as T=Int <~< P=DeliteInt + // Test.xAlready below: DeliteCollection[T=DeliteInt] -> P=DeliteInt <: Forcible[T=DeliteInt], as T=DeliteInt <~< P=DeliteInt + // this would required DeliteInt <: Forcible[Int] with Forcible[DeliteInt] + + def headProxy[P <: Forcible[_]](implicit w: T <~< P): P = xs.head + } + // If T is already a proxy (it is forcible), the compiler should use + // forcibleIdentity to deduce that P=T. If T is Int, the compiler + // should use intToForcible to deduce that P=DeliteInt. + // + // Without this feature, the user must write 'xs.proxyOfFirst[DeliteInt]', + // with the feature they can write 'xs.proxyOfFirst', which is shorter and + // avoids exposing internal DELITE types to the world. + + object Test { + val x = new DeliteCollection(List(1,2,3)).headProxy + // inferred: val x: Forcible[Int] = new DeliteCollection[Int](List.apply[Int](1, 2, 3)).headProxy[Forcible[Int]](forcibleInt); + + val xAlready = new DeliteCollection(List(DeliteInt(1),DeliteInt(2),DeliteInt(3))).headProxy + // inferred: val xAlready: DeliteInt = new DeliteCollection[DeliteInt](List.apply[DeliteInt](DeliteInt(1), DeliteInt(2), DeliteInt(3))).headProxy[DeliteInt](trivial[DeliteInt]); + } +} |