diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2007-04-06 09:39:53 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2007-04-06 09:39:53 +0000 |
commit | f96b6beefc08f56218ac68b37a4cecd757cb60ee (patch) | |
tree | 2001a44efae7ddd1699520d3855598ef13e30803 /test/files/pos | |
parent | 10a651a13c323366223160bfa1b4fe8a6e818d1d (diff) | |
download | scala-f96b6beefc08f56218ac68b37a4cecd757cb60ee.tar.gz scala-f96b6beefc08f56218ac68b37a4cecd757cb60ee.tar.bz2 scala-f96b6beefc08f56218ac68b37a4cecd757cb60ee.zip |
adding test files from tcpoly branch without hi...
adding test files from tcpoly branch without history -- much faster this way, sorry
Diffstat (limited to 'test/files/pos')
22 files changed, 533 insertions, 0 deletions
diff --git a/test/files/pos/ksbug1.scala b/test/files/pos/ksbug1.scala new file mode 100644 index 0000000000..b3e1631370 --- /dev/null +++ b/test/files/pos/ksbug1.scala @@ -0,0 +1,4 @@ +object test { + type z[a,b] = a => b + def f : z[int,int] = (i => i + 1) +}
\ No newline at end of file diff --git a/test/files/pos/nullary.scala b/test/files/pos/nullary.scala new file mode 100644 index 0000000000..22318d5143 --- /dev/null +++ b/test/files/pos/nullary.scala @@ -0,0 +1,20 @@ +abstract class NullaryTest[T, m[s]] { + def nullary: String = "a" + val x = nullary + + def nullary2: T + val x2 = nullary2 + + def nullary3: m[T] + val x3 = nullary3 +} + +class Concrete extends NullaryTest[Int, List] { + def nullary2 = 1 + def nullary3 = List(1,2,3) +} + +object test { + (new Concrete).nullary2 + (new Concrete).nullary3 +}
\ No newline at end of file diff --git a/test/files/pos/nullary_poly.scala b/test/files/pos/nullary_poly.scala new file mode 100644 index 0000000000..9e3f239b36 --- /dev/null +++ b/test/files/pos/nullary_poly.scala @@ -0,0 +1,10 @@ +// test polymorphic nullary method calls +class A { + // built-in + synchronized {} + + val x: String = "a".asInstanceOf[String] + + // user-defined: + def polyNullary[T]: List[T] = Nil +}
\ No newline at end of file diff --git a/test/files/pos/return_thistype.scala b/test/files/pos/return_thistype.scala new file mode 100644 index 0000000000..c0736c0ad9 --- /dev/null +++ b/test/files/pos/return_thistype.scala @@ -0,0 +1,8 @@ +// tests transformation of return type in typedTypeApply (see also tcpoly_gm.scala) +class As { + class A { + def foo: A.this.type = bar.asInstanceOf[A.this.type] + def foo2: this.type = bar.asInstanceOf[this.type] + def bar: A = null + } +} diff --git a/test/files/pos/tcpoly_boundedmonad.scala b/test/files/pos/tcpoly_boundedmonad.scala new file mode 100644 index 0000000000..ea19ae4c39 --- /dev/null +++ b/test/files/pos/tcpoly_boundedmonad.scala @@ -0,0 +1,19 @@ +trait Monad[T <: Bound[T], MyType[x <: Bound[x]], Bound[_]] { + def map[S <: Bound[S]](f: T => S): MyType[S] + + def flatMap[S <: RBound[S], RContainer[x <: RBound[x]], RBound[_], + Result[x <: RBound[x]] <: Monad[x, RContainer, RBound]] + (f: T => Result[S]): Result[S] + + def filter(p: T => Boolean): MyType[T] +} + +class Set[T <: Ordered[T]] extends Monad[T, Set, Ordered] { + def map[S <: Ordered[S]](f: T => S): Set[S] = error("TODO") + + def flatMap[S <: RBound[S], RContainer[x <: RBound[x]], RBound[_], + Result[x <: RBound[x]] <: Monad[x, RContainer, RBound]] + (f: T => Result[S]): Result[S] = error("TODO") + + def filter(p: T => Boolean): Set[T] = error("TODO") +}
\ No newline at end of file diff --git a/test/files/pos/tcpoly_bounds1.scala b/test/files/pos/tcpoly_bounds1.scala new file mode 100644 index 0000000000..d74d3c975b --- /dev/null +++ b/test/files/pos/tcpoly_bounds1.scala @@ -0,0 +1,14 @@ +class Foo[t[x]<: Pair[Int, x]] + +// +class MyPair[z](a: Int, b: z) extends Pair[Int, z](a,b) + +object foo extends Foo[MyPair] + + +trait Monad[m[x <: Bound[x]], Bound[x], a] // TODO: variances! +trait ListMonad[a] extends Monad[List, Any, a] + +trait MyOrdered[a] +trait MySet[x <: MyOrdered[x]] +trait SetMonad[a <: MyOrdered[a]] extends Monad[MySet, MyOrdered, a]
\ No newline at end of file diff --git a/test/files/pos/tcpoly_gm.scala b/test/files/pos/tcpoly_gm.scala new file mode 100644 index 0000000000..89b66cfba6 --- /dev/null +++ b/test/files/pos/tcpoly_gm.scala @@ -0,0 +1,14 @@ +trait Rep[a] { + def rep[m[x]]: m[a] // typedTypeApply must use asSeenFrom to adapt the return type + // since rep is called on x: Rep[t] + // a must become t +} + +case class ShowBin[b](app: b => String) + +object foo { + def showBin[t](x: Rep[t], y: t): String = { + val r: ShowBin[t] = x.rep[ShowBin] + r.app(y) + } +} diff --git a/test/files/pos/tcpoly_higherorder_bound_method.scala b/test/files/pos/tcpoly_higherorder_bound_method.scala new file mode 100644 index 0000000000..1e5cbf8092 --- /dev/null +++ b/test/files/pos/tcpoly_higherorder_bound_method.scala @@ -0,0 +1,3 @@ +trait SkolemisationOfHigherOrderBoundInMethod { + def method[A, N[X <: A], M[X <: N[A]]]: unit +}
\ No newline at end of file diff --git a/test/files/pos/tcpoly_late_method_params.scala b/test/files/pos/tcpoly_late_method_params.scala new file mode 100644 index 0000000000..2af0664618 --- /dev/null +++ b/test/files/pos/tcpoly_late_method_params.scala @@ -0,0 +1,5 @@ +trait Foo { + def flatMap[RT <: RBound[RT], RBound[_], Result[x <: RBound[x]]]: Result[RT] +// bounds for RT& = >: scala.this.Nothing <: RBound&[RT&] + // bounds for x = >: scala.this.Nothing <: RBound&[x] +}
\ No newline at end of file diff --git a/test/files/pos/tcpoly_method.scala b/test/files/pos/tcpoly_method.scala new file mode 100644 index 0000000000..34dde904c3 --- /dev/null +++ b/test/files/pos/tcpoly_method.scala @@ -0,0 +1,6 @@ +trait Iterable[m[+x], +t] { + def flatMap[resColl[+x] <: Iterable[resColl, x], s](f: t => resColl[s]): resColl[s] + + def foo[a[x]] = "a" + val x = foo[List] +}
\ No newline at end of file diff --git a/test/files/pos/tcpoly_overloaded.scala b/test/files/pos/tcpoly_overloaded.scala new file mode 100644 index 0000000000..47cb68a8bb --- /dev/null +++ b/test/files/pos/tcpoly_overloaded.scala @@ -0,0 +1,25 @@ +trait Monad[T <: Bound[T], MyType[x <: Bound[x]], Bound[_]] { + def flatMap[S <: RBound[S], RContainer[x <: RBound[x]], RBound[_], + Result[x <: RBound[x]] <: Monad[x, RContainer, RBound]] + (f: T => Result[S]): Result[S] + def flatMap[S <: RBound[S], RContainer[x <: RBound[x]], RBound[_], + Result[x <: RBound[x]] <: Monad[x, RContainer, RBound]] + (f: T => Result[S], foo: String): Result[S] + def flatMap[S <: Bound[S]] + (f: T => MyType[S], foo: Int): MyType[S] +} + +trait Test { + def moo: MList[Int] + class MList[T](el: T) extends Monad[T, List, Any] { + def flatMap[S <: RBound[S], RContainer[x <: RBound[x]], RBound[_], + Result[x <: RBound[x]] <: Monad[x, RContainer, RBound]] + (f: T => Result[S]): Result[S] = error("foo") + def flatMap[S <: RBound[S], RContainer[x <: RBound[x]], RBound[_], + Result[x <: RBound[x]] <: Monad[x, RContainer, RBound]] + (f: T => Result[S], foo: String): Result[S] = error("foo") + def flatMap[S] + (f: T => List[S], foo: Int): List[S] = error("foo") + } + val l: MList[String] = moo.flatMap[String, List, Any, MList]((x: Int) => new MList("String")) +}
\ No newline at end of file diff --git a/test/files/pos/tcpoly_param_scoping.scala b/test/files/pos/tcpoly_param_scoping.scala new file mode 100644 index 0000000000..1019fdfaf2 --- /dev/null +++ b/test/files/pos/tcpoly_param_scoping.scala @@ -0,0 +1,8 @@ +trait FOO[B, m[A <: B]] +trait FOO2[A <: B, B] +trait FOO3[m[A <: B], B] + +class Test { + def foo[a[x]] = "a" +} +//trait Idiom[idi[x]] { def foo: idi[Int]}
\ No newline at end of file diff --git a/test/files/pos/tcpoly_poly.scala b/test/files/pos/tcpoly_poly.scala new file mode 100644 index 0000000000..1ba04e29df --- /dev/null +++ b/test/files/pos/tcpoly_poly.scala @@ -0,0 +1,3 @@ +class Monad[m[x]] + +object ml extends Monad[List] diff --git a/test/files/pos/tcpoly_return_overriding.scala b/test/files/pos/tcpoly_return_overriding.scala new file mode 100644 index 0000000000..cc7dd55cec --- /dev/null +++ b/test/files/pos/tcpoly_return_overriding.scala @@ -0,0 +1,13 @@ +trait Generic[g[x]] { + def unit: g[Unit] +} + +trait Rep[t] { + def rep[m[x]](implicit gen: Generic[m]): m[t] +} + +// testing that the return type is also transformed when checking overriding +// + that substitution (of types&symbols) preserves isHigherKinded when replacing a higher-kinded type with another one +object foo extends Rep[Unit] { + def rep[g[x]](implicit gen: Generic[g]): g[Unit]= gen.unit +}
\ No newline at end of file diff --git a/test/files/pos/tcpoly_seq.scala b/test/files/pos/tcpoly_seq.scala new file mode 100644 index 0000000000..85563488fd --- /dev/null +++ b/test/files/pos/tcpoly_seq.scala @@ -0,0 +1,175 @@ +package examples.tcpoly.collection; + +trait HOSeq { + // an internal interface that encapsulates the accumulation of elements (of type elT) to produce + // a structure of type coll[elT] -- different kinds of collections should provide different implicit + // values implementing this interface, in order to provide more performant ways of building that structure + trait Accumulator[+coll[x], elT] { + def += (el: elT): Unit + def result: coll[elT] + } + + + // Iterable abstracts over the type of its structure as well as its elements (see PolyP's Bifunctor) + // m[x] is intentionally unbounded: fold can then be defined nicely + // variance: if we write m[+x] instead of +m[+x], x is an invariant position because its enclosing type + // is an invariant position -- should probably rule that out? + trait Iterable[+m[+x], +t] { + //def unit[a](orig: a): m[a] + def elements: Iterator[t] + + // construct an empty accumulator that will produce the same structure as this iterable, with elements of type t + def accumulator[t]: Accumulator[m, t] + + def filter(p: t => Boolean): m[t] = { + val buf = accumulator[t] + val elems = elements + while (elems.hasNext) { val x = elems.next; if (p(x)) buf += x } + buf.result + } + + def map[s](f: t => s): m[s] = { + val buf = accumulator[s] + val elems = elements + while (elems.hasNext) buf += f(elems.next) + buf.result + } + + // flatMap is a more specialized map, it only works if the mapped function produces Iterable values, + // which are then added to the result one by one + // the compiler should be able to find the right accumulator (implicit buf) to build the result + // to get concat, resColl = SingletonIterable, f = unit for SingletonIterable + def flatMap[resColl[+x] <: Iterable[resColl, x], s](f: t => resColl[s])(implicit buf: Accumulator[resColl, s]): resColl[s] = { + // TODO: would a viewbound for resColl[x] be better? + // -- 2nd-order type params are not yet in scope in view bound + val elems = elements + while (elems.hasNext) { + val elemss: Iterator[s] = f(elems.next).elements + while (elemss.hasNext) buf += elemss.next + } + buf.result + } + } + + final class ListBuffer[A] { + private var start: List[A] = Nil + private var last: ::[A] = _ + private var exported: boolean = false + + /** Appends a single element to this buffer. + * + * @param x the element to append. + */ + def += (x: A): unit = { + if (exported) copy + if (start.isEmpty) { + last = new HOSeq.this.:: (x, Nil) + start = last + } else { + val last1 = last + last = new HOSeq.this.:: (x, null) // hack: ::'s tail will actually be last + //last1.tl = last + } + } + + /** Converts this buffer to a list + */ + def toList: List[A] = { + exported = !start.isEmpty + start + } + + /** Clears the buffer contents. + */ + def clear: unit = { + start = Nil + exported = false + } + + /** Copy contents of this buffer */ + private def copy = { + var cursor = start + val limit = last.tail + clear + while (cursor ne limit) { + this += cursor.head + cursor = cursor.tail + } + } + } + + implicit def listAccumulator[elT]: Accumulator[List, elT] = new Accumulator[List, elT] { + private[this] val buff = new ListBuffer[elT] + def += (el: elT): Unit = buff += el + def result: List[elT] = buff.toList + } + + trait List[+t] extends Iterable[List, t] { + def head: t + def tail: List[t] + def isEmpty: Boolean + def elements: Iterator[t] = new Iterator[t] { + var these = List.this + def hasNext: Boolean = !these.isEmpty + def next: t = + if (!hasNext) + throw new NoSuchElementException("next on empty Iterator") + else { + val result = these.head; these = these.tail; result + } + } + // construct an empty accumulator that will produce the same structure as this iterable, with elements of type t + def accumulator[t]: Accumulator[List, t] = listAccumulator[t] + } + + // TODO: the var tl approach does not seem to work because subtyping isn't fully working yet + final case class ::[+b](hd: b, private val tl: List[b]) extends List[b] { + def head = hd + def tail = if(tl==null) this else tl // hack + override def isEmpty: boolean = false + } + + case object Nil extends List[Nothing] { + def isEmpty = true + def head: Nothing = + throw new NoSuchElementException("head of empty list") + def tail: List[Nothing] = + throw new NoSuchElementException("tail of empty list") + } +} + + + +// misc signatures collected from mailing list / library code: + /*override def flatMap[B](f: A => Iterable[B]): Set[B] + final override def flatMap[b](f: Any => Iterable[b]): Array[b] + def flatMap[b](f: a => Parser[b]) = new Parser[b] + override def flatMap[b](f: a => Iterable[b]): List[b] + + + MapResult[K] <: Seq[K] + FilterResult <: Seq[T] + Concat <: Seq[T] + Subseq <: Seq[T] + + + def map[K](f: T=>K): MapResult[K] + def filter(f: T=>Boolean): FilterResult + def subseq(from: int, to: int): Subseq + def flatMap[S <: Seq[K], K](f: T => S): S#Concat // legal? + def concat(others: Seq[T]): Concat + */ + +/*trait Iterator[t] { + // @post hasAdvanced implies hasNext + // model def hasAdvanced: Boolean + + def hasNext: Boolean // pure + + // @pre hasAdvanced + def current: t // pure + + // @pre hasNext + // @post hasAdvanced + def advance: Unit +}*/
\ No newline at end of file diff --git a/test/files/pos/tcpoly_seq_typealias.scala b/test/files/pos/tcpoly_seq_typealias.scala new file mode 100644 index 0000000000..0498c3b2f6 --- /dev/null +++ b/test/files/pos/tcpoly_seq_typealias.scala @@ -0,0 +1,143 @@ +package examples.tcpoly.collection; + +trait HOSeq { + // an internal interface that encapsulates the accumulation of elements (of type elT) to produce + // a structure of type coll[elT] -- different kinds of collections should provide different implicit + // values implementing this interface, in order to provide more performant ways of building that structure + trait Accumulator[+coll[x], elT] { + def += (el: elT): Unit + def result: coll[elT] + } + + + // Iterable abstracts over the type of its structure as well as its elements (see PolyP's Bifunctor) + // m[x] is intentionally unbounded: fold can then be defined nicely + // variance: if we write m[+x] instead of +m[+x], x is an invariant position because its enclosing type + // is an invariant position -- should probably rule that out? + trait Iterable[+t] { + type m[+x] + + //def unit[a](orig: a): m[a] + def elements: Iterator[t] + + // construct an empty accumulator that will produce the same structure as this iterable, with elements of type t + def accumulator[t]: Accumulator[m, t] + + def filter(p: t => Boolean): m[t] = { + val buf = accumulator[t] + val elems = elements + while (elems.hasNext) { val x = elems.next; if (p(x)) buf += x } + buf.result + } + + def map[s](f: t => s): m[s] = { + val buf = accumulator[s] + val elems = elements + while (elems.hasNext) buf += f(elems.next) + buf.result + } + + // flatMap is a more specialized map, it only works if the mapped function produces Iterable values, + // which are then added to the result one by one + // the compiler should be able to find the right accumulator (implicit buf) to build the result + // to get concat, resColl = SingletonIterable, f = unit for SingletonIterable + def flatMap[resColl[+x] <: Iterable[x], s](f: t => resColl[s])(implicit buf: Accumulator[resColl, s]): resColl[s] = { + // TODO: would a viewbound for resColl[x] be better? + // -- 2nd-order type params are not yet in scope in view bound + val elems = elements + while (elems.hasNext) { + val elemss: Iterator[s] = f(elems.next).elements + while (elemss.hasNext) buf += elemss.next + } + buf.result + } + } + + final class ListBuffer[A] { + private var start: List[A] = Nil + private var last: ::[A] = _ + private var exported: boolean = false + + /** Appends a single element to this buffer. + * + * @param x the element to append. + */ + def += (x: A): unit = { + if (exported) copy + if (start.isEmpty) { + last = new HOSeq.this.:: (x, Nil) + start = last + } else { + val last1 = last + last = new HOSeq.this.:: (x, null) // hack: ::'s tail will actually be last + //last1.tl = last + } + } + + /** Converts this buffer to a list + */ + def toList: List[A] = { + exported = !start.isEmpty + start + } + + /** Clears the buffer contents. + */ + def clear: unit = { + start = Nil + exported = false + } + + /** Copy contents of this buffer */ + private def copy = { + var cursor = start + val limit = last.tail + clear + while (cursor ne limit) { + this += cursor.head + cursor = cursor.tail + } + } + } + + implicit def listAccumulator[elT]: Accumulator[List, elT] = new Accumulator[List, elT] { + private[this] val buff = new ListBuffer[elT] + def += (el: elT): Unit = buff += el + def result: List[elT] = buff.toList + } + + trait List[+t] extends Iterable[t] { + type m[+x] = List[x] + + def head: t + def tail: List[t] + def isEmpty: Boolean + def elements: Iterator[t] = new Iterator[t] { + var these = List.this + def hasNext: Boolean = !these.isEmpty + def next: t = + if (!hasNext) + throw new NoSuchElementException("next on empty Iterator") + else { + val result = these.head; these = these.tail; result + } + } + // construct an empty accumulator that will produce the same structure as this iterable, with elements of type t + def accumulator[t]: Accumulator[List, t] = listAccumulator[t] + } + + // TODO: the var tl approach does not seem to work because subtyping isn't fully working yet + final case class ::[+b](hd: b, private val tl: List[b]) extends List[b] { + def head = hd + def tail = if(tl==null) this else tl // hack + override def isEmpty: boolean = false + } + + case object Nil extends List[Nothing] { + def isEmpty = true + def head: Nothing = + throw new NoSuchElementException("head of empty list") + def tail: List[Nothing] = + throw new NoSuchElementException("tail of empty list") + } +}
\ No newline at end of file diff --git a/test/files/pos/tcpoly_subst.scala b/test/files/pos/tcpoly_subst.scala new file mode 100644 index 0000000000..af474585e9 --- /dev/null +++ b/test/files/pos/tcpoly_subst.scala @@ -0,0 +1,4 @@ +object test { + def make[m[x], b]: m[b] = error("foo") + val lst: List[Int] = make[List, Int] +}
\ No newline at end of file diff --git a/test/files/pos/tcpoly_typesub.scala b/test/files/pos/tcpoly_typesub.scala new file mode 100644 index 0000000000..bb29d88bd9 --- /dev/null +++ b/test/files/pos/tcpoly_typesub.scala @@ -0,0 +1,14 @@ +// contributed by Lauri Alanko +trait TypeSub { + type l + type u + def castSub[f[+x]](fl : f[l]) : f[u] + def castSuper[f[-x]](fu : f[u]) : f[l] = { + type c[+y] = f[y] => f[l] + castSub[c]{ fl : f[l] => fl }(fu) + } + def castValue[t](lt : l with t) : u with t = { + type c[+y] = y with t + castSub[c](lt) + } +}
\ No newline at end of file diff --git a/test/files/pos/tcpoly_variance.scala b/test/files/pos/tcpoly_variance.scala new file mode 100644 index 0000000000..9e034ef97e --- /dev/null +++ b/test/files/pos/tcpoly_variance.scala @@ -0,0 +1,7 @@ +class A[m[+x]] { + def str: m[Object] = error("foo") +} + +class B[m[+x]] extends A[m] { + override def str: m[String] = error("foo") +}
\ No newline at end of file diff --git a/test/files/pos/tcpoly_wildcards.scala b/test/files/pos/tcpoly_wildcards.scala new file mode 100644 index 0000000000..eed0e6f685 --- /dev/null +++ b/test/files/pos/tcpoly_wildcards.scala @@ -0,0 +1,3 @@ +trait test[b[_,_]] { + def moo[a[_, _]] = error("a") +}
\ No newline at end of file diff --git a/test/files/pos/typealias_dubious.scala b/test/files/pos/typealias_dubious.scala new file mode 100644 index 0000000000..98df5c1290 --- /dev/null +++ b/test/files/pos/typealias_dubious.scala @@ -0,0 +1,15 @@ +class MailBox { + //class Message + type Message = AnyRef +} + +abstract class Actor { + private val in = new MailBox + + def send(msg: in.Message) = error("foo") + + def unstable: Actor = error("foo") + + def dubiousSend(msg: MailBox#Message) = + unstable.send(msg) // in.Message becomes unstable.Message, but that's ok since Message is a concrete type member +}
\ No newline at end of file diff --git a/test/files/pos/typealiases.scala b/test/files/pos/typealiases.scala new file mode 100644 index 0000000000..c32a3e3a78 --- /dev/null +++ b/test/files/pos/typealiases.scala @@ -0,0 +1,20 @@ +package foo + +trait Test[T] { + type Check[T] = Array[T] => Unit; + type MyPair[S] = Pair[T, S] + + val pair1: Pair[T, Int] + val pair: MyPair[Int] = pair1 + + def check(xs: Array[T], c: Check[T]) = c(xs) + def check2[S](xs: Array[S], c: Check[S]) = c(xs) +} + +object main extends Test[Int] { + val pair1 = (1,1) + + implicit def topair(x: Int): Pair[Int, Int] = (x,x) + val pair2: MyPair[Int] = 1 + val x: short = 1 +}
\ No newline at end of file |