diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/neg/i2001.scala | 6 | ||||
-rw-r--r-- | tests/neg/i2033.scala | 21 | ||||
-rw-r--r-- | tests/pos/inferOverloaded.scala | 41 | ||||
-rw-r--r-- | tests/run/hmap.scala | 97 | ||||
-rw-r--r-- | tests/run/lazy-implicit-lists.check | 4 | ||||
-rw-r--r-- | tests/run/lazy-implicit-lists.scala | 87 | ||||
-rw-r--r-- | tests/run/lazy-implicit-nums.check | 1 | ||||
-rw-r--r-- | tests/run/lazy-implicit-nums.scala | 58 |
8 files changed, 315 insertions, 0 deletions
diff --git a/tests/neg/i2001.scala b/tests/neg/i2001.scala new file mode 100644 index 000000000..82518890c --- /dev/null +++ b/tests/neg/i2001.scala @@ -0,0 +1,6 @@ +class A { + def odd(x: Int) = if (x == 0) false else !even(x-1) + def even(x: Int) = if (x == 0) true else !odd(x-1) // error: overloaded or recursive method needs result type + + lazy val x = x // error: recursive value needs type +} diff --git a/tests/neg/i2033.scala b/tests/neg/i2033.scala new file mode 100644 index 000000000..b28a0d99e --- /dev/null +++ b/tests/neg/i2033.scala @@ -0,0 +1,21 @@ +import java.io._ +import collection._ +object Test { + def check(obj: AnyRef): Unit = { + val bos = new ByteArrayOutputStream() + val out = new ObjectOutputStream(println) // error + val arr = bos toByteArray () + val in = (()) + val deser = () + val lhs = mutable LinkedHashSet () + check(lhs) + } +} + +// minimization +object Test2 { + class ObjectOutputStream(out: String) { + def this() = this("") + } + val out = new ObjectOutputStream(println) // error +} diff --git a/tests/pos/inferOverloaded.scala b/tests/pos/inferOverloaded.scala new file mode 100644 index 000000000..e7179a04a --- /dev/null +++ b/tests/pos/inferOverloaded.scala @@ -0,0 +1,41 @@ +class MySeq[T] { + def map1[U](f: T => U): MySeq[U] = new MySeq[U] + def map2[U](f: T => U): MySeq[U] = new MySeq[U] +} + +class MyMap[A, B] extends MySeq[(A, B)] { + def map1[C](f: (A, B) => C): MySeq[C] = new MySeq[C] + def map1[C, D](f: (A, B) => (C, D)): MyMap[C, D] = new MyMap[C, D] + def map1[C, D](f: ((A, B)) => (C, D)): MyMap[C, D] = new MyMap[C, D] + + def foo(f: Function2[Int, Int, Int]): Unit = () + def foo[R](pf: PartialFunction[(A, B), R]): MySeq[R] = new MySeq[R] +} + +object Test { + val m = new MyMap[Int, String] + + // This one already worked because it is not overloaded: + m.map2 { case (k, v) => k - 1 } + + // These already worked because preSelectOverloaded eliminated the non-applicable overload: + m.map1(t => t._1) + m.map1((kInFunction, vInFunction) => kInFunction - 1) + val r1 = m.map1(t => (t._1, 42.0)) + val r1t: MyMap[Int, Double] = r1 + + // These worked because the argument types are known for overload resolution: + m.map1({ case (k, v) => k - 1 }: PartialFunction[(Int, String), Int]) + m.map2({ case (k, v) => k - 1 }: PartialFunction[(Int, String), Int]) + + // These ones did not work before: + m.map1 { case (k, v) => k } + val r = m.map1 { case (k, v) => (k, k*10) } + val rt: MyMap[Int, Int] = r + m.foo { case (k, v) => k - 1 } + + // Used to be ambiguous but overload resolution now favors PartialFunction + def h[R](pf: Function2[Int, String, R]): Unit = () + def h[R](pf: PartialFunction[(Double, Double), R]): Unit = () + h { case (a: Double, b: Double) => 42: Int } +} diff --git a/tests/run/hmap.scala b/tests/run/hmap.scala new file mode 100644 index 000000000..d84419ce1 --- /dev/null +++ b/tests/run/hmap.scala @@ -0,0 +1,97 @@ +trait Tuple +case class TCons[H, T <: Tuple](h: H, t: T) extends Tuple +final case object TNil extends Tuple + +// Type level natural numbers ------------------------------------------------- + +sealed trait Nat +sealed trait Succ[P <: Nat] extends Nat +sealed trait Zero extends Nat + +// Accessor type class to compute the N'th element of an Tuple L -------------- + +trait At[L <: Tuple, N <: Nat, Out] { + def apply(l: L): Out +} + +object At { + implicit def caseZero[H, T <: Tuple]: At[H TCons T, Zero, H] = + new At[H TCons T, Zero, H] { + def apply(l: H TCons T): H = { + val (h TCons _) = l + h + } + } + + implicit def caseN[H, T <: Tuple, N <: Nat, O] + (implicit a: At[T, N, O]): At[H TCons T, Succ[N], O] = + new At[H TCons T, Succ[N], O] { + def apply(l: H TCons T): O = { + val (_ TCons t) = l + a(t) + } + } +} + +// An HMap is an Tuple with HEntry elements. We are reusing Tuple for it's nice syntax + +final case class HEntry[K, V](value: V) + +// Accessor type class to compute the element of type K in a HMap L ----------- + +trait PhantomGet[K, M <: Tuple, I <: Nat] // extends PhantomAny + +object PhantomGet { + implicit def getHead[K, V, T <: Tuple] + : PhantomGet[K, HEntry[K, V] TCons T, Zero] = null + + implicit def getTail[K, H, T <: Tuple, I <: Nat] + (implicit t: PhantomGet[K, T, I]) + : PhantomGet[K, H TCons T, Succ[I]] = null +} + +// Syntax --------------------------------------------------------------------- + +object syntax { + object hmap { + implicit class HmapGet[M <: Tuple](m: M) { + def get[K, V, I <: Nat](k: K) + (implicit + g: PhantomGet[k.type, M, I], + a: At[M, I, HEntry[k.type, V]] + ): V = a(m).value + } + + def --[K, V](key: K, value: V) = HEntry[key.type, V](value) + } +} + +object Test { + def main(args: Array[String]): Unit = { + import syntax.hmap._ + + val map1 = + TCons(HEntry[K = "name"]("foo"), + TCons(HEntry[K = "genre"](true), + TCons(HEntry[K = "moneyz"](123), + TCons(HEntry[K = "cat"]("bar"), + (TNil: TNil.type))))) + + assert(map1.get("name") == "foo") + assert(map1.get("genre") == true) + assert(map1.get("moneyz") == 123) + assert(map1.get("cat") == "bar") + + val map2 = + TCons(--("name" , "foo"), + TCons(--("genre" , true), + TCons(--("moneyz", 123), + TCons(--("cat" , "bar"), + TNil)))) + + assert(map2.get("name") == "foo") + assert(map2.get("genre") == true) + assert(map2.get("moneyz") == 123) + assert(map2.get("cat") == "bar") + } +} diff --git a/tests/run/lazy-implicit-lists.check b/tests/run/lazy-implicit-lists.check new file mode 100644 index 000000000..60e3225b1 --- /dev/null +++ b/tests/run/lazy-implicit-lists.check @@ -0,0 +1,4 @@ +List() +List(1, 2, 3) +List() +List(1, 2, 3) diff --git a/tests/run/lazy-implicit-lists.scala b/tests/run/lazy-implicit-lists.scala new file mode 100644 index 000000000..72099d0b2 --- /dev/null +++ b/tests/run/lazy-implicit-lists.scala @@ -0,0 +1,87 @@ +trait L +case class C(hd: Int, tl: L) extends L +case object N extends L + +trait Sum[+S1, +S2] +case class Fst[+F](x: F) extends Sum[F, Nothing] +case class Snd[+S](x: S) extends Sum[Nothing, S] + +case class Prod[+P1, +P2](fst: P1, snd: P2) + +trait shaped[SH1, SH2] { + def toShape(x: SH1): SH2 + def fromShape(x: SH2): SH1 +} + +object Test { + + type LShape = Sum[Prod[Int, L], Unit] + + implicit def LShape: L `shaped` LShape = + new (L `shaped` LShape) { + def toShape(xs: L) = xs match { + case C(x, xs1) => Fst(Prod(x, xs1)) + case N => Snd(()) + } + def fromShape(sh: LShape) = sh match { + case Fst(Prod(x, xs1)) => C(x, xs1) + case Snd(()) => N + } + } + + trait Listable[T] { + def toList(x: T): List[Int] + } + + implicit def ShapedListable[T, U](implicit + ev1: T shaped U, + ev2: Listable[U] + ): Listable[T] = + new Listable[T] { + def toList(x: T) = ev2.toList(ev1.toShape(x)) + } + + implicit def SumListable[T, U](implicit + ev1: => Listable[T], + ev2: => Listable[U] + ): Listable[Sum[T, U]] = + new Listable[Sum[T, U]] { + def toList(s: Sum[T, U]) = s match { + case Fst(x) => ev1.toList(x) + case Snd(x) => ev2.toList(x) + } + } + + implicit def ProdListable[T, U](implicit + ev1: Listable[T], + ev2: Listable[U] + ): Listable[Prod[T, U]] = + new Listable[Prod[T, U]] { + def toList(p: Prod[T, U]) = ev1.toList(p.fst) ++ ev2.toList(p.snd) + } + + implicit def IntListable: Listable[Int] = + new Listable[Int] { + def toList(n: Int) = n :: Nil + } + + + implicit def UnitListable: Listable[Unit] = + new Listable[Unit] { + def toList(u: Unit) = Nil + } + + def toList[T, U >: T](x: T)(implicit ev1: Listable[U]) = ev1.toList(x) + + def main(args: Array[String]) = { + locally { // with specialized Listable + implicit lazy val LListable: Listable[L] = ShapedListable + println(toList(N)) + println(toList(C(1, C(2, C(3, N))))) + } + locally { // without specialized Listable + println(toList(N)) + println(toList(C(1, C(2, C(3, N))))) + } + } +} diff --git a/tests/run/lazy-implicit-nums.check b/tests/run/lazy-implicit-nums.check new file mode 100644 index 000000000..00750edc0 --- /dev/null +++ b/tests/run/lazy-implicit-nums.check @@ -0,0 +1 @@ +3 diff --git a/tests/run/lazy-implicit-nums.scala b/tests/run/lazy-implicit-nums.scala new file mode 100644 index 000000000..967472735 --- /dev/null +++ b/tests/run/lazy-implicit-nums.scala @@ -0,0 +1,58 @@ +trait Nat +case class S(x: Nat) extends Nat +case class Z() extends Nat + +trait Sum[+S1, +S2] +case class Fst[+F](x: F) extends Sum[F, Nothing] +case class Snd[+S](x: S) extends Sum[Nothing, S] + +trait shaped[SH1, SH2] { + def toShape(x: SH1): SH2 + def fromShape(x: SH2): SH1 +} + +object Test { + + type NatShape = Sum[Nat, Z] + + implicit def natShape: Nat `shaped` NatShape = + new (Nat `shaped` NatShape) { + def toShape(n: Nat) = n match { + case S(m) => Fst(m) + case Z() => Snd(Z()) + } + def fromShape(s: NatShape) = s match { + case Fst(n) => S(n) + case Snd(_) => Z() + } + } + + trait Countable[T] { + def count(x: T): Int + } + + implicit def ShapedCountable[T, U](implicit + ev1: T shaped U, + ev2: Countable[U] + ): Countable[T] = + new Countable[T] { + def count(x: T) = ev2.count(ev1.toShape(x)) + } + + implicit def SumCountable[T, U](implicit + ev1: => Countable[T] + ): Countable[Sum[T, U]] = + new Countable[Sum[T, U]] { + def count(s: Sum[T, U]) = s match { + case Fst(x) => ev1.count(x) + 1 + case Snd(_) => 0 + } + } + + def count[T, U >: T](x: T)(implicit ev1: Countable[U]) = ev1.count(x) + + def main(args: Array[String]) = { + println( + count(S(S(S(Z()))))) + } +} |