diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2013-10-18 07:22:58 -0700 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2013-10-18 07:22:58 -0700 |
commit | 54707cb45018170e31eb188a9a694ab9b0728f71 (patch) | |
tree | fae843355f051d9aed9b223ecf18c28bee63ecd9 /test | |
parent | 5b2c4644a23ffbe1c45df40bf3511aee71eb0fe2 (diff) | |
parent | 210dbc7887bc42eed4154de65d0ff5f46ca5ee58 (diff) | |
download | scala-54707cb45018170e31eb188a9a694ab9b0728f71.tar.gz scala-54707cb45018170e31eb188a9a694ab9b0728f71.tar.bz2 scala-54707cb45018170e31eb188a9a694ab9b0728f71.zip |
Merge pull request #3030 from xeno-by/topic/fundep-views
SI-3346 implicit parameters can now guide implicit view inference
Diffstat (limited to 'test')
28 files changed, 313 insertions, 19 deletions
diff --git a/test/files/neg/divergent-implicit.check b/test/files/neg/divergent-implicit.check index 5f20df1b91..60d876409f 100644 --- a/test/files/neg/divergent-implicit.check +++ b/test/files/neg/divergent-implicit.check @@ -3,16 +3,14 @@ divergent-implicit.scala:4: error: type mismatch; required: String val x1: String = 1 ^ -divergent-implicit.scala:5: error: diverging implicit expansion for type Int => String -starting with method cast in object Test1 - val x2: String = cast[Int, String](1) - ^ -divergent-implicit.scala:14: error: diverging implicit expansion for type Test2.Baz => Test2.Bar -starting with method baz2bar in object Test2 +divergent-implicit.scala:14: error: type mismatch; + found : Test2.Foo + required: Test2.Bar val x: Bar = new Foo ^ -divergent-implicit.scala:15: error: diverging implicit expansion for type Test2.Foo => Test2.Bar -starting with method foo2bar in object Test2 +divergent-implicit.scala:15: error: type mismatch; + found : Test2.Baz + required: Test2.Bar val y: Bar = new Baz ^ -four errors found +three errors found diff --git a/test/files/neg/t3346b.check b/test/files/neg/t3346b.check new file mode 100644 index 0000000000..bcde6d90e4 --- /dev/null +++ b/test/files/neg/t3346b.check @@ -0,0 +1,4 @@ +t3346b.scala:14: error: could not find implicit value for evidence parameter of type TC[Any] + val y = foo(1) + ^ +one error found diff --git a/test/files/neg/t3346b.scala b/test/files/neg/t3346b.scala new file mode 100644 index 0000000000..8ea8970298 --- /dev/null +++ b/test/files/neg/t3346b.scala @@ -0,0 +1,15 @@ +import scala.language.implicitConversions + +trait T[X] +trait U[X] +trait TC[M[_]] + +object Test extends App { + def foo[M[_]: TC, A](ma: M[A]) = () + implicit val TCofT: TC[T] = new TC[T] {} + implicit def any2T[A](a: A): T[A] = new T[A] {} + implicit def any2U[A](a: A): U[A] = new U[A] {} + + val x = foo[T, Int](1) + val y = foo(1) +}
\ No newline at end of file diff --git a/test/files/neg/t3346c.check b/test/files/neg/t3346c.check new file mode 100644 index 0000000000..575379d009 --- /dev/null +++ b/test/files/neg/t3346c.check @@ -0,0 +1,4 @@ +t3346c.scala:60: error: value bar is not a member of Either[Int,String] + eii.bar + ^ +one error found diff --git a/test/files/neg/t3346c.scala b/test/files/neg/t3346c.scala new file mode 100644 index 0000000000..a5ac166b2d --- /dev/null +++ b/test/files/neg/t3346c.scala @@ -0,0 +1,61 @@ +object Test extends App { + // + // An attempt to workaround SI-2712, foiled by SI-3346 + // + trait TC[M[_]] + + type EitherInt[A] = Either[Int, A] + + implicit object EitherTC extends TC[EitherInt] + + def foo[M[_]: TC, A](ma: M[A]) = () + + val eii: Either[Int, String] = Right("") + + foo[EitherInt, String](eii) + + // This one needs SI-2712 Higher Order Unification + //foo(eii) // not inferred + + // A workaround is to provide a set of implicit conversions that take values + // based on type constructors of various shapes, and search for the + // type class instances. + // + // This is the approach taken by scalaz7. + + trait TCValue[M[_], A] { + implicit def self: M[A] + def M: TC[M] + + // instead of `foo(eii)`, we'll try `eii.foo` + def foo[M[_], A] = () + } + + + implicit def ToTCValue[M[_], A](ma: M[A])(implicit M0: TC[M]) = new TCValue[M, A] { + implicit val M = M0 + val self = ma + } + implicit def ToTCValueBin1[M[_, _], A, B](ma: M[A, B])(implicit M0: TC[({type λ[α]=M[A, α]})#λ]): TCValue[({type λ[α] = M[A, α]})#λ, B] = new TCValue[({type λ[α]=M[A, α]})#λ, B] { + implicit val M = M0 + val self = ma + } + implicit def ToTCValueBin2[M[_, _], A, B](ma: M[A, B])(implicit M0: TC[({type λ[α]=M[α, B]})#λ]): TCValue[({type λ[α]=M[α, B]})#λ, A] = new TCValue[({type λ[α]=M[α, B]})#λ, A] { + implicit val M = M0 + val self = ma + } + + + ToTCValueBin1(eii).foo + + // as expected, could not find implicit parameter + // ToTCValueBin2(eii).bar + + // error: implicit conversions are not applicable because they are ambiguous, both method ToTCValueBin1 ... and method ToTCValueBin2 + // annoying!! + // https://issues.scala-lang.org/browse/SI-3346 + // + // Works if we remove ToTCValueBin2 + // + eii.bar +} diff --git a/test/files/neg/t3346i.check b/test/files/neg/t3346i.check new file mode 100644 index 0000000000..cc17ab7ce4 --- /dev/null +++ b/test/files/neg/t3346i.check @@ -0,0 +1,7 @@ +t3346i.scala:28: error: value a is not a member of Test.A[T] + (new A).a + ^ +t3346i.scala:29: error: value a is not a member of Test.A[Nothing] + (new A[Nothing]).a + ^ +two errors found diff --git a/test/files/neg/t3346i.scala b/test/files/neg/t3346i.scala new file mode 100644 index 0000000000..9ad2544537 --- /dev/null +++ b/test/files/neg/t3346i.scala @@ -0,0 +1,30 @@ +import scala.language.implicitConversions + +// the classes involved +case class Z[U](a: U) +case class Intermediate[T, U](t: T, u: U) +class Implicit1[T](b: Implicit2[T]) +class Implicit2[T](c: Implicit3[T]) +class Implicit3[T](/* and so on */) + +object Test extends App { + // the base conversion + implicit def convertToZ[T](a: A[T])(implicit b: Implicit1[T]): Z[A[T]] = Z(a) + + // and the implicit chaining, don't you just love it? :D + // implicit1, with one alternative + implicit def implicit1[T <: Intermediate[_, _]](implicit b: Implicit2[T]) = new Implicit1[T](b) + // implicit2, with two alternatives + implicit def implicit2alt1[T <: Intermediate[_ <: String, _]](implicit c: Implicit3[T]) = new Implicit2[T](c) + implicit def implicit2alt2[T <: Intermediate[_ <: Double, _]](implicit c: Implicit3[T]) = new Implicit2[T](c) + // implicit3, with two alternatives + implicit def implicit3alt1[T <: Intermediate[_, _ <: Int]] = new Implicit3[T]() + implicit def implicit3alt2[T <: Intermediate[_ <: Double, _ <: AnyRef],X] = new Implicit3[T]() + + // and our targets + /** conversion here, with constraints */ + class A[T]() + + (new A).a + (new A[Nothing]).a +} diff --git a/test/files/neg/t5578.check b/test/files/neg/t5578.check index d803adb223..56123d2e0f 100644 --- a/test/files/neg/t5578.check +++ b/test/files/neg/t5578.check @@ -1,4 +1,7 @@ -t5578.scala:33: error: No Manifest available for T. +t5578.scala:33: error: type mismatch; + found : NumericOpsExp.this.Plus[T] + required: NumericOpsExp.this.Rep[T] + (which expands to) NumericOpsExp.this.Exp[T] def plus[T: Numeric](x: Rep[T], y: Rep[T]): Rep[T] = Plus[T](x,y) ^ one error found diff --git a/test/files/neg/t5845.check b/test/files/neg/t5845.check deleted file mode 100644 index 8c6100d6de..0000000000 --- a/test/files/neg/t5845.check +++ /dev/null @@ -1,7 +0,0 @@ -t5845.scala:9: error: value +++ is not a member of Int - println(5 +++ 5) - ^ -t5845.scala:15: error: value +++ is not a member of Int - println(5 +++ 5) - ^ -two errors found diff --git a/test/files/neg/t7519.check b/test/files/neg/t7519.check index 164d67f595..df54abaa3e 100644 --- a/test/files/neg/t7519.check +++ b/test/files/neg/t7519.check @@ -1,7 +1,11 @@ -t7519.scala:5: error: could not find implicit value for parameter nada: Nothing +t7519.scala:5: error: type mismatch; + found : Int(0) + required: String locally(0 : String) // was: "value conversion is not a member of C.this.C" ^ -t7519.scala:15: error: could not find implicit value for parameter nada: Nothing +t7519.scala:15: error: type mismatch; + found : Int(0) + required: String locally(0 : String) // was: "value conversion is not a member of U" ^ two errors found diff --git a/test/files/pos/t5845.check b/test/files/pos/t5845.check new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/files/pos/t5845.check diff --git a/test/files/neg/t5845.scala b/test/files/pos/t5845.scala index 823c722c14..823c722c14 100644 --- a/test/files/neg/t5845.scala +++ b/test/files/pos/t5845.scala diff --git a/test/files/run/t3346a.check b/test/files/run/t3346a.check new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/test/files/run/t3346a.check @@ -0,0 +1 @@ +1 diff --git a/test/files/run/t3346a.scala b/test/files/run/t3346a.scala new file mode 100644 index 0000000000..c0a90b011b --- /dev/null +++ b/test/files/run/t3346a.scala @@ -0,0 +1,11 @@ +import scala.language.implicitConversions + +object Test extends App { + class Rep[T](x : T) + + class SomeOps[T](x : Rep[T]) { def foo = 1 } + implicit def mkOps[X, T](x : X)(implicit conv: X => Rep[T]) : SomeOps[T] = new SomeOps(conv(x)) + + val a: Rep[Int] = new Rep(42) + println(a.foo) +}
\ No newline at end of file diff --git a/test/files/run/t3346b.check b/test/files/run/t3346b.check new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/files/run/t3346b.check diff --git a/test/files/run/t3346c.check b/test/files/run/t3346c.check new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/files/run/t3346c.check diff --git a/test/files/run/t3346d.check b/test/files/run/t3346d.check new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/files/run/t3346d.check diff --git a/test/files/run/t3346d.scala b/test/files/run/t3346d.scala new file mode 100644 index 0000000000..3f79896210 --- /dev/null +++ b/test/files/run/t3346d.scala @@ -0,0 +1,21 @@ +import scala.language.implicitConversions + +object Test extends App { + trait TARInt + + trait Basket[A,B] { + def iAmABasket = {} + } + + trait BasketFactory[A,B] { + def create(v: A): Basket[A,B] + } + + implicit val bf = new BasketFactory[Int,TARInt] { + def create(v: Int): Basket[Int,TARInt] = new Basket[Int, TARInt]{} + } + + implicit def i2[A,B](a: A)(implicit bf: BasketFactory[A,B]): Basket[A,B] = bf.create(a) + + 1.iAmABasket // <-- i2 conversion not applicable +}
\ No newline at end of file diff --git a/test/files/run/t3346e.check b/test/files/run/t3346e.check new file mode 100644 index 0000000000..71a57ffa70 --- /dev/null +++ b/test/files/run/t3346e.check @@ -0,0 +1,12 @@ +eqw +List(0, 2) +List(0, 2) +BitSet(0, 2) +Vector(113, 119, 101) +qwe +List(2, 0) +List(0!) +BitSet(0, 2) +qwe +List(2, 0) +qwe diff --git a/test/files/run/t3346e.scala b/test/files/run/t3346e.scala new file mode 100644 index 0000000000..ac0de564d4 --- /dev/null +++ b/test/files/run/t3346e.scala @@ -0,0 +1,81 @@ +import scala.language.implicitConversions +import scala.collection.generic.CanBuildFrom +import scala.math.Ordering +import collection.{TraversableLike, SeqLike} +import collection.immutable.BitSet + +class QuickSort[Coll](a: Coll) { + //should be able to sort only something with defined order (someting like a Seq) + def quickSort[T](implicit ev0: Coll => SeqLike[T, Coll], + cbf: CanBuildFrom[Coll, T, Coll], + n: Ordering[T]): Coll = { + quickSortAnything(ev0, cbf, n) + } + + //we can even sort a Set, if we really want to + def quickSortAnything[T](implicit ev0: Coll => TraversableLike[T, Coll], + cbf: CanBuildFrom[Coll, T, Coll], + n: Ordering[T]): Coll = { + import n._ + if (a.size < 2) { + a + } else { + // We pick the first value for the pivot. + val pivot = a.head + val (lower, tmp) = a.partition(_ < pivot) + val (upper, same) = tmp.partition(_ > pivot) + val b = cbf() + b.sizeHint(a.size) + b ++= new QuickSort(lower).quickSortAnything + b ++= same + b ++= new QuickSort(upper).quickSortAnything + b.result + } + } +} + +class FilterMap[Repr](a: Repr) { + def filterMap[A, B, That](f: A => Option[B])(implicit ev0: Repr => TraversableLike[A, Repr], + cbf: CanBuildFrom[Repr, B, That]): That = { + a.flatMap(e => f(e).toSeq) + } +} + +class FilterMapFixed[A, Repr <% TraversableLike[A, Repr]](a: Repr) { + def filterMap2[B, That](f: A => Option[B])(implicit cbf: CanBuildFrom[Repr, B, That]): That = { + a.flatMap(e => f(e).toSeq) + } +} + +object MyEnhancements { + implicit def toQS[Coll](a: Coll) = new QuickSort(a) + implicit def toFM[Coll](a: Coll) = new FilterMap(a) + implicit def toFM2[A, Repr <% TraversableLike[A, Repr]](a: Repr) = new FilterMapFixed(a) +} + +object Test extends App { + + import MyEnhancements._ + + println("qwe".quickSort) + println(Array(2, 0).quickSort.toList) + println(Seq(2, 0).quickSort) + //not very useful to sort a set, but just as a demonstration + println(BitSet(2, 0).quickSortAnything) + + //need to hint type inferencer, + //probably will be able to overcome after https://issues.scala-lang.org/browse/SI-4699 and + // related issues are fixed (by moving ev0 parameter from filterMap to toFM), see toFM2 + println("qwe".filterMap((c: Char) => Some(c.toInt))) + println("qwe".filterMap((c: Char) => Some(c))) + println(Array(2, 0).filterMap((c: Int) => Some(c.toInt)).toList) + println(Seq(2, 0).filterMap((c: Int) => if (c < 2) Some(c + "!") else None)) + def test(i:Int) = Option(i) + println(BitSet(2,0).filterMap(test)) + + println(toFM2("qwe").filterMap2(c => Some(c))) + println(toFM2(Array(2, 0)).filterMap2(c => Some(c.toInt)).toList) + //No implicit view available from java.lang.String => scala.collection.TraversableLike[A,java.lang.String]. :( + //Not anymore :) + println("qwe".filterMap2(c => Some(c))) +} diff --git a/test/files/run/t3346f.check b/test/files/run/t3346f.check new file mode 100644 index 0000000000..fd3c81a4d7 --- /dev/null +++ b/test/files/run/t3346f.check @@ -0,0 +1,2 @@ +5 +5 diff --git a/test/files/run/t3346f.scala b/test/files/run/t3346f.scala new file mode 100644 index 0000000000..4799ca2ca9 --- /dev/null +++ b/test/files/run/t3346f.scala @@ -0,0 +1,15 @@ +import scala.language.implicitConversions +import scala.language.reflectiveCalls + +object Test extends App { + trait Foo[A] + implicit def fooString: Foo[String] = null + implicit def value[A](implicit foo: Foo[A]) = 5 + + println(implicitly[Int]) + + implicit def conversion[A](x: Int)(implicit foo: Foo[A]) = new { + def aMethod = 5 + } + println(1.aMethod) +} diff --git a/test/files/run/t3346g.check b/test/files/run/t3346g.check new file mode 100644 index 0000000000..ce894825e0 --- /dev/null +++ b/test/files/run/t3346g.check @@ -0,0 +1 @@ +A(3,asdf) diff --git a/test/files/run/t3346g.scala b/test/files/run/t3346g.scala new file mode 100644 index 0000000000..d7c9d79c7f --- /dev/null +++ b/test/files/run/t3346g.scala @@ -0,0 +1,9 @@ +import scala.language.implicitConversions + +case class A(b: Int, c: String) + +object Test extends App { + implicit def s2i(s: String): Int = s.length + implicit def toA[T](t: T)(implicit f: T => Int): A = A(f(t), t.toString) + println("asdf".copy(b = 3)) +}
\ No newline at end of file diff --git a/test/files/run/t3346h.check b/test/files/run/t3346h.check new file mode 100644 index 0000000000..587be6b4c3 --- /dev/null +++ b/test/files/run/t3346h.check @@ -0,0 +1 @@ +x diff --git a/test/files/run/t3346h.scala b/test/files/run/t3346h.scala new file mode 100644 index 0000000000..97ebc9380c --- /dev/null +++ b/test/files/run/t3346h.scala @@ -0,0 +1,9 @@ +import scala.language.implicitConversions + +object Test extends App { + trait Fundep[T, U] { def u(t: T): U } + class C { def y = "x" } + implicit val FundepStringC = new Fundep[String, C]{ def u(t: String) = new C } + implicit def foo[T, U](x: T)(implicit y: Fundep[T, U]): U = y.u(x) + println("x".y) +}
\ No newline at end of file diff --git a/test/files/run/t3346j.check b/test/files/run/t3346j.check new file mode 100644 index 0000000000..59e8626fc5 --- /dev/null +++ b/test/files/run/t3346j.check @@ -0,0 +1 @@ +Int diff --git a/test/files/run/t3346j.scala b/test/files/run/t3346j.scala new file mode 100644 index 0000000000..98b5a870a7 --- /dev/null +++ b/test/files/run/t3346j.scala @@ -0,0 +1,11 @@ +import scala.language.implicitConversions +import scala.language.reflectiveCalls +import scala.reflect.runtime.universe._ + +object Test extends App { + class A[T] + class B[T] + implicit def foo[T: TypeTag](a: A[T])(implicit b: B[T]) = new { def baz = typeOf[T] } + implicit def bar[T <: Int]: B[T] = new B[T]() + println(new A[Int]().baz) +}
\ No newline at end of file |