summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2007-04-06 09:39:53 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2007-04-06 09:39:53 +0000
commitf96b6beefc08f56218ac68b37a4cecd757cb60ee (patch)
tree2001a44efae7ddd1699520d3855598ef13e30803
parent10a651a13c323366223160bfa1b4fe8a6e818d1d (diff)
downloadscala-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
-rw-r--r--test/files/neg/higherkind_novalue.check7
-rw-r--r--test/files/neg/higherkind_novalue.scala4
-rw-r--r--test/files/neg/tcpoly_bounds.check4
-rw-r--r--test/files/neg/tcpoly_bounds.scala3
-rw-r--r--test/files/neg/tcpoly_typealias.check13
-rw-r--r--test/files/neg/tcpoly_typealias.scala47
-rw-r--r--test/files/neg/tcpoly_variance.check5
-rw-r--r--test/files/neg/tcpoly_variance.scala7
-rw-r--r--test/files/neg/tcpoly_variance_enforce.check45
-rw-r--r--test/files/neg/tcpoly_variance_enforce.scala42
-rw-r--r--test/files/neg/wellkinded_app.check4
-rw-r--r--test/files/neg/wellkinded_app.scala4
-rw-r--r--test/files/neg/wellkinded_app2.check4
-rw-r--r--test/files/neg/wellkinded_app2.scala4
-rw-r--r--test/files/neg/wellkinded_bounds.check4
-rw-r--r--test/files/neg/wellkinded_bounds.scala3
-rw-r--r--test/files/neg/wellkinded_wrongarity.check4
-rw-r--r--test/files/neg/wellkinded_wrongarity.scala5
-rw-r--r--test/files/neg/wellkinded_wrongarity2.check4
-rw-r--r--test/files/neg/wellkinded_wrongarity2.scala4
-rw-r--r--test/files/pos/ksbug1.scala4
-rw-r--r--test/files/pos/nullary.scala20
-rw-r--r--test/files/pos/nullary_poly.scala10
-rw-r--r--test/files/pos/return_thistype.scala8
-rw-r--r--test/files/pos/tcpoly_boundedmonad.scala19
-rw-r--r--test/files/pos/tcpoly_bounds1.scala14
-rw-r--r--test/files/pos/tcpoly_gm.scala14
-rw-r--r--test/files/pos/tcpoly_higherorder_bound_method.scala3
-rw-r--r--test/files/pos/tcpoly_late_method_params.scala5
-rw-r--r--test/files/pos/tcpoly_method.scala6
-rw-r--r--test/files/pos/tcpoly_overloaded.scala25
-rw-r--r--test/files/pos/tcpoly_param_scoping.scala8
-rw-r--r--test/files/pos/tcpoly_poly.scala3
-rw-r--r--test/files/pos/tcpoly_return_overriding.scala13
-rw-r--r--test/files/pos/tcpoly_seq.scala175
-rw-r--r--test/files/pos/tcpoly_seq_typealias.scala143
-rw-r--r--test/files/pos/tcpoly_subst.scala4
-rw-r--r--test/files/pos/tcpoly_typesub.scala14
-rw-r--r--test/files/pos/tcpoly_variance.scala7
-rw-r--r--test/files/pos/tcpoly_wildcards.scala3
-rw-r--r--test/files/pos/typealias_dubious.scala15
-rw-r--r--test/files/pos/typealiases.scala20
-rw-r--r--test/files/run/tcpoly_monads.check1
-rw-r--r--test/files/run/tcpoly_monads.scala42
-rw-r--r--test/files/run/tcpoly_overriding.check1
-rw-r--r--test/files/run/tcpoly_overriding.scala16
-rw-r--r--test/files/run/tcpoly_parseridioms.check1
-rw-r--r--test/files/run/tcpoly_parseridioms.scala109
-rw-r--r--test/pending/neg/tcpoly_variance_enforce_getter_setter.scala12
49 files changed, 932 insertions, 0 deletions
diff --git a/test/files/neg/higherkind_novalue.check b/test/files/neg/higherkind_novalue.check
new file mode 100644
index 0000000000..932f7876b1
--- /dev/null
+++ b/test/files/neg/higherkind_novalue.check
@@ -0,0 +1,7 @@
+higherkind_novalue.scala:2: error: type m takes type parameters
+ val x: m // type of kind *->* doesn't classify a value, but a val/def/... can only contain/return a value
+ ^
+higherkind_novalue.scala:3: error: type m takes type parameters
+ def y: m
+ ^
+two errors found
diff --git a/test/files/neg/higherkind_novalue.scala b/test/files/neg/higherkind_novalue.scala
new file mode 100644
index 0000000000..c2e117b60e
--- /dev/null
+++ b/test/files/neg/higherkind_novalue.scala
@@ -0,0 +1,4 @@
+abstract class HigherKind[m[s]] {
+ val x: m // type of kind *->* doesn't classify a value, but a val/def/... can only contain/return a value
+ def y: m
+} \ No newline at end of file
diff --git a/test/files/neg/tcpoly_bounds.check b/test/files/neg/tcpoly_bounds.check
new file mode 100644
index 0000000000..03e22f9fbc
--- /dev/null
+++ b/test/files/neg/tcpoly_bounds.check
@@ -0,0 +1,4 @@
+tcpoly_bounds.scala:3: error: type arguments [scala.List] do not conform to class A's type parameter bounds [m<: [x]>: scala.Nothing <: scala.Option[x]]
+object b extends A[List]
+ ^
+one error found
diff --git a/test/files/neg/tcpoly_bounds.scala b/test/files/neg/tcpoly_bounds.scala
new file mode 100644
index 0000000000..ae1f410fac
--- /dev/null
+++ b/test/files/neg/tcpoly_bounds.scala
@@ -0,0 +1,3 @@
+class A[m[x] <: Option[x]]
+object a extends A[Some]
+object b extends A[List] \ No newline at end of file
diff --git a/test/files/neg/tcpoly_typealias.check b/test/files/neg/tcpoly_typealias.check
new file mode 100644
index 0000000000..56912c49b7
--- /dev/null
+++ b/test/files/neg/tcpoly_typealias.check
@@ -0,0 +1,13 @@
+tcpoly_typealias.scala:37: error: The kind of type m does not conform to the expected kind of type m<: [+x]>: scala.Nothing <: scala.Any in trait A.
+BInv.this.m's type parameters do not match type m's expected parameters: type x (in trait BInv) is invariant, but type x (in trait A) is declared covariant
+ type m[x] = FooCov[x] // error: invariant x in alias def
+ ^
+tcpoly_typealias.scala:41: error: The kind of type m does not conform to the expected kind of type m<: [+x]>: scala.Nothing <: scala.Any in trait A.
+BCon.this.m's type parameters do not match type m's expected parameters: type x (in trait BCon) is contravariant, but type x (in trait A) is declared covariant
+ type m[-x] = FooCon[x] // error: contravariant x
+ ^
+tcpoly_typealias.scala:45: error: The kind of type m does not conform to the expected kind of type m<: [+x]>: scala.Nothing <: scala.Any in trait A.
+BBound.this.m's type parameters do not match type m's expected parameters: type x (in trait BBound)'s bounds >: scala.Nothing <: scala.Predef.String are stricter than type x (in trait A)'s declared bounds >: scala.Nothing <: scala.Any
+ type m[+x <: String] = FooBound[x] // error: x with stricter bound
+ ^
+three errors found
diff --git a/test/files/neg/tcpoly_typealias.scala b/test/files/neg/tcpoly_typealias.scala
new file mode 100644
index 0000000000..6c7f80cc0b
--- /dev/null
+++ b/test/files/neg/tcpoly_typealias.scala
@@ -0,0 +1,47 @@
+trait A {
+ type m[+x]
+}
+
+trait A2 {
+ type m[+x <: String]
+}
+
+trait A3 {
+ type m[x]
+}
+
+trait FooCov[+x]
+trait FooCon[-x]
+trait FooBound[+x <: String]
+
+trait BOk1 extends A {
+ type m[+x] = FooCov[x]
+}
+
+trait BOk2 extends A2 {
+ type m[+x <: String] = FooBound[x]
+}
+
+trait BOk3 extends A2 {
+ type m[+x] = FooCov[x] // weaker bound
+}
+
+trait BOk4 extends A3 {
+ type m[+x] = FooCov[x] // weaker variance
+}
+
+// there are two aspects to check:
+ // does type alias signature (not considering RHS) correspond to abstract type member in super class
+ // does RHS correspond to the type alias sig
+trait BInv extends A{
+ type m[x] = FooCov[x] // error: invariant x in alias def
+}
+
+trait BCon extends A{
+ type m[-x] = FooCon[x] // error: contravariant x
+}
+
+trait BBound extends A{
+ type m[+x <: String] = FooBound[x] // error: x with stricter bound
+}
+
diff --git a/test/files/neg/tcpoly_variance.check b/test/files/neg/tcpoly_variance.check
new file mode 100644
index 0000000000..5fd104d607
--- /dev/null
+++ b/test/files/neg/tcpoly_variance.check
@@ -0,0 +1,5 @@
+tcpoly_variance.scala:6: error: error overriding method str in class A of type => m[java.lang.Object];
+ method str has incompatible type => m[scala.Predef.String]
+ override def str: m[String] = error("foo") // since x in m[x] is invariant, ! m[String] <: m[Object]
+ ^
+one error found
diff --git a/test/files/neg/tcpoly_variance.scala b/test/files/neg/tcpoly_variance.scala
new file mode 100644
index 0000000000..8122938113
--- /dev/null
+++ b/test/files/neg/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") // since x in m[x] is invariant, ! m[String] <: m[Object]
+} \ No newline at end of file
diff --git a/test/files/neg/tcpoly_variance_enforce.check b/test/files/neg/tcpoly_variance_enforce.check
new file mode 100644
index 0000000000..c66440434b
--- /dev/null
+++ b/test/files/neg/tcpoly_variance_enforce.check
@@ -0,0 +1,45 @@
+tcpoly_variance_enforce.scala:15: error: the kinds of the type arguments (FooInvar) do not conform to the expected kinds of the type parameters (type m) in trait coll.
+FooInvar's type parameters do not match type m's expected parameters: type x (in class FooInvar) is invariant, but type x is declared covariant
+object fcollinv extends coll[FooInvar] // error
+ ^
+tcpoly_variance_enforce.scala:16: error: the kinds of the type arguments (FooContra) do not conform to the expected kinds of the type parameters (type m) in trait coll.
+FooContra's type parameters do not match type m's expected parameters: type x (in class FooContra) is contravariant, but type x is declared covariant
+object fcollcon extends coll[FooContra] // error
+ ^
+tcpoly_variance_enforce.scala:17: error: the kinds of the type arguments (FooString) do not conform to the expected kinds of the type parameters (type m) in trait coll.
+FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: scala.Nothing <: scala.Predef.String are stricter than type x's declared bounds >: scala.Nothing <: scala.Any
+object fcollwb extends coll[FooString] // error
+ ^
+tcpoly_variance_enforce.scala:19: error: the kinds of the type arguments (FooCov) do not conform to the expected kinds of the type parameters (type m) in trait coll2.
+FooCov's type parameters do not match type m's expected parameters: type x (in class FooCov) is covariant, but type x is declared contravariant
+object fcoll2ok extends coll2[FooCov] // error
+ ^
+tcpoly_variance_enforce.scala:20: error: the kinds of the type arguments (FooInvar) do not conform to the expected kinds of the type parameters (type m) in trait coll2.
+FooInvar's type parameters do not match type m's expected parameters: type x (in class FooInvar) is invariant, but type x is declared contravariant
+object fcoll2inv extends coll2[FooInvar] // error
+ ^
+tcpoly_variance_enforce.scala:22: error: the kinds of the type arguments (FooString) do not conform to the expected kinds of the type parameters (type m) in trait coll2.
+FooString's type parameters do not match type m's expected parameters: type x (in class FooString) is covariant, but type x is declared contravarianttype x (in class FooString)'s bounds >: scala.Nothing <: scala.Predef.String are stricter than type x's declared bounds >: scala.Nothing <: scala.Any
+object fcoll2wb extends coll2[FooString] // error
+ ^
+tcpoly_variance_enforce.scala:27: error: the kinds of the type arguments (FooString) do not conform to the expected kinds of the type parameters (type m) in trait coll3.
+FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: scala.Nothing <: scala.Predef.String are stricter than type x's declared bounds >: scala.Nothing <: scala.Any
+object fcoll3wb extends coll3[FooString] // error
+ ^
+tcpoly_variance_enforce.scala:30: error: the kinds of the type arguments (FooString,scala.Int) do not conform to the expected kinds of the type parameters (type m,type y) in trait coll4.
+FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: scala.Nothing <: scala.Predef.String are stricter than type x's declared bounds >: scala.Nothing <: y
+object fcoll4_1 extends coll4[FooString, Int] // error
+ ^
+tcpoly_variance_enforce.scala:31: error: the kinds of the type arguments (FooString,scala.Any) do not conform to the expected kinds of the type parameters (type m,type y) in trait coll4.
+FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: scala.Nothing <: scala.Predef.String are stricter than type x's declared bounds >: scala.Nothing <: y
+object fcoll4_2 extends coll4[FooString, Any] // error
+ ^
+tcpoly_variance_enforce.scala:37: error: the kinds of the type arguments (FooInvar) do not conform to the expected kinds of the type parameters (type m) in trait coll.
+FooInvar's type parameters do not match type m's expected parameters: type x (in class FooInvar) is invariant, but type x is declared covariant
+ def x: coll[FooInvar] = error("foo") // error
+ ^
+tcpoly_variance_enforce.scala:38: error: the kinds of the type arguments (FooContra) do not conform to the expected kinds of the type parameters (type m) in trait coll.
+FooContra's type parameters do not match type m's expected parameters: type x (in class FooContra) is contravariant, but type x is declared covariant
+ def y: coll[FooContra] = error("foo") // error
+ ^
+11 errors found
diff --git a/test/files/neg/tcpoly_variance_enforce.scala b/test/files/neg/tcpoly_variance_enforce.scala
new file mode 100644
index 0000000000..e2fea37fff
--- /dev/null
+++ b/test/files/neg/tcpoly_variance_enforce.scala
@@ -0,0 +1,42 @@
+trait coll[m[+x]]
+
+trait coll2[m[-x]]
+
+trait coll3[m[x]]
+
+trait coll4[m[x <: y], y]
+
+class FooInvar[x]
+class FooContra[-x]
+class FooCov[+x]
+class FooString[+x <: String]
+
+object fcollok extends coll[FooCov]
+object fcollinv extends coll[FooInvar] // error
+object fcollcon extends coll[FooContra] // error
+object fcollwb extends coll[FooString] // error
+
+object fcoll2ok extends coll2[FooCov] // error
+object fcoll2inv extends coll2[FooInvar] // error
+object fcoll2con extends coll2[FooContra]
+object fcoll2wb extends coll2[FooString] // error
+
+object fcoll3ok extends coll3[FooCov]
+object fcoll3inv extends coll3[FooInvar]
+object fcoll3con extends coll3[FooContra]
+object fcoll3wb extends coll3[FooString] // error
+
+object fcoll4ok extends coll4[FooString, String]
+object fcoll4_1 extends coll4[FooString, Int] // error
+object fcoll4_2 extends coll4[FooString, Any] // error
+
+
+object test {
+ var ok: coll[FooCov] = _
+
+ def x: coll[FooInvar] = error("foo") // error
+ def y: coll[FooContra] = error("foo") // error
+}
+
+
+// TODO: need test for rank N with N >: 2 \ No newline at end of file
diff --git a/test/files/neg/wellkinded_app.check b/test/files/neg/wellkinded_app.check
new file mode 100644
index 0000000000..d57a0e4b56
--- /dev/null
+++ b/test/files/neg/wellkinded_app.check
@@ -0,0 +1,4 @@
+wellkinded_app.scala:3: error: x does not take type parameters
+ type t = x[x]
+ ^
+one error found
diff --git a/test/files/neg/wellkinded_app.scala b/test/files/neg/wellkinded_app.scala
new file mode 100644
index 0000000000..7fa3f95a98
--- /dev/null
+++ b/test/files/neg/wellkinded_app.scala
@@ -0,0 +1,4 @@
+// test well-kindedness checks
+class WellKinded[x] {
+ type t = x[x]
+}
diff --git a/test/files/neg/wellkinded_app2.check b/test/files/neg/wellkinded_app2.check
new file mode 100644
index 0000000000..20a177ea59
--- /dev/null
+++ b/test/files/neg/wellkinded_app2.check
@@ -0,0 +1,4 @@
+wellkinded_app2.scala:3: error: s does not take type parameters
+ val foo: s[Int]
+ ^
+one error found
diff --git a/test/files/neg/wellkinded_app2.scala b/test/files/neg/wellkinded_app2.scala
new file mode 100644
index 0000000000..5b73611964
--- /dev/null
+++ b/test/files/neg/wellkinded_app2.scala
@@ -0,0 +1,4 @@
+// test well-kindedness checks
+class WellKinded[s <: Throwable] {
+ val foo: s[Int]
+} \ No newline at end of file
diff --git a/test/files/neg/wellkinded_bounds.check b/test/files/neg/wellkinded_bounds.check
new file mode 100644
index 0000000000..9099934c68
--- /dev/null
+++ b/test/files/neg/wellkinded_bounds.check
@@ -0,0 +1,4 @@
+wellkinded_bounds.scala:2: error: class List takes type parameters
+class WellKindedWrongSyntax[s <: List] { // must be s[x] <: List[x]
+ ^
+one error found
diff --git a/test/files/neg/wellkinded_bounds.scala b/test/files/neg/wellkinded_bounds.scala
new file mode 100644
index 0000000000..7b80ce1cf7
--- /dev/null
+++ b/test/files/neg/wellkinded_bounds.scala
@@ -0,0 +1,3 @@
+// test well-kindedness checks -- syntax error
+class WellKindedWrongSyntax[s <: List] { // must be s[x] <: List[x]
+} \ No newline at end of file
diff --git a/test/files/neg/wellkinded_wrongarity.check b/test/files/neg/wellkinded_wrongarity.check
new file mode 100644
index 0000000000..548b5e40bb
--- /dev/null
+++ b/test/files/neg/wellkinded_wrongarity.check
@@ -0,0 +1,4 @@
+wellkinded_wrongarity.scala:5: error: type Pair takes two type parameters, expected: one
+object mp extends Monad[Pair]
+ ^
+one error found
diff --git a/test/files/neg/wellkinded_wrongarity.scala b/test/files/neg/wellkinded_wrongarity.scala
new file mode 100644
index 0000000000..39f8b7a2c3
--- /dev/null
+++ b/test/files/neg/wellkinded_wrongarity.scala
@@ -0,0 +1,5 @@
+// test well-kindedness checks -- arity error
+
+class Monad[m[x]]
+
+object mp extends Monad[Pair] \ No newline at end of file
diff --git a/test/files/neg/wellkinded_wrongarity2.check b/test/files/neg/wellkinded_wrongarity2.check
new file mode 100644
index 0000000000..353d2368a1
--- /dev/null
+++ b/test/files/neg/wellkinded_wrongarity2.check
@@ -0,0 +1,4 @@
+wellkinded_wrongarity2.scala:4: error: type String takes no type parameters, expected: one
+object ms extends Monad[String]
+ ^
+one error found
diff --git a/test/files/neg/wellkinded_wrongarity2.scala b/test/files/neg/wellkinded_wrongarity2.scala
new file mode 100644
index 0000000000..ee9d771aaa
--- /dev/null
+++ b/test/files/neg/wellkinded_wrongarity2.scala
@@ -0,0 +1,4 @@
+// test well-kindedness checks
+class Monad[m[x]]
+
+object ms extends Monad[String] \ No newline at end of file
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
diff --git a/test/files/run/tcpoly_monads.check b/test/files/run/tcpoly_monads.check
new file mode 100644
index 0000000000..d81cc0710e
--- /dev/null
+++ b/test/files/run/tcpoly_monads.check
@@ -0,0 +1 @@
+42
diff --git a/test/files/run/tcpoly_monads.scala b/test/files/run/tcpoly_monads.scala
new file mode 100644
index 0000000000..0ee160803a
--- /dev/null
+++ b/test/files/run/tcpoly_monads.scala
@@ -0,0 +1,42 @@
+trait Monads {
+ /**
+ * class Monad m where
+ * (>>=) :: m a -> (a -> m b) -> m b
+ * return :: a -> m a
+ *
+ * MonadTC encodes the above Haskell type class,
+ * an instance of MonadTC corresponds to a method dictionary.
+ * (see http://lampwww.epfl.ch/~odersky/talks/wg2.8-boston06.pdf)
+ *
+ * Note that the identity (`this') of the method dictionary does not really correspond
+ * to the instance of m[x] (`self') that is `wrapped': e.g., unit does not use `self' (which
+ * corresponds to the argument of the implicit conversion that encodes an instance of this type class)
+ */
+ trait MonadTC[m[x], a] {
+ def unit[a](orig: a): m[a]
+
+ // >>='s first argument comes from the implicit definition constructing this "method dictionary"
+ def >>=[b](fun: a => m[b]): m[b]
+ }
+}
+
+/**
+ * instance Monad Maybe where
+ * (Just x) >>= k = k x
+ * Nothing >>= _ = Nothing
+ */
+trait OptionMonad extends Monads {
+ // this implicit method encodes the Monad type class instance for Option
+ implicit def OptionInstOfMonad[a](self: Option[a]): MonadTC[Option, a]
+ = new MonadTC[Option, a] {
+ def unit[a](orig: a) = Some(orig)
+ def >>=[b](fun: a => Option[b]): Option[b] = self match {
+ case Some(x) => fun(x)
+ case None => None
+ }
+ }
+}
+
+object Test extends OptionMonad with Application {
+ Console.println((Some("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") >>= (x => Some(x.length))).get)
+} \ No newline at end of file
diff --git a/test/files/run/tcpoly_overriding.check b/test/files/run/tcpoly_overriding.check
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/test/files/run/tcpoly_overriding.check
@@ -0,0 +1 @@
+1
diff --git a/test/files/run/tcpoly_overriding.scala b/test/files/run/tcpoly_overriding.scala
new file mode 100644
index 0000000000..970e16c71f
--- /dev/null
+++ b/test/files/run/tcpoly_overriding.scala
@@ -0,0 +1,16 @@
+abstract class A[t[x]] {
+ def b: t[Int]
+}
+
+class B extends A[List] {
+ // underlying functionality being tested is overriding, but bugs manifest itself during erasure
+ // erasure should generate two methods: one that returns an Object (to implement the method in A)
+ // one that is as close as possible to the original method and thus returns a List
+ // the problem only manifests itself here -- but it's really a problem with overriding
+ // the link between this method and the method in A isn't seen
+ def b: List[Int] = List(1)
+}
+
+object Test extends Application {
+ Console.println((new B).b(0))
+} \ No newline at end of file
diff --git a/test/files/run/tcpoly_parseridioms.check b/test/files/run/tcpoly_parseridioms.check
new file mode 100644
index 0000000000..5fff2efb15
--- /dev/null
+++ b/test/files/run/tcpoly_parseridioms.check
@@ -0,0 +1 @@
+Success(List(),Plus(1,2))
diff --git a/test/files/run/tcpoly_parseridioms.scala b/test/files/run/tcpoly_parseridioms.scala
new file mode 100644
index 0000000000..e163ea2ce8
--- /dev/null
+++ b/test/files/run/tcpoly_parseridioms.scala
@@ -0,0 +1,109 @@
+trait Parsers {
+ type Input=List[char]
+
+ sealed class ParseResult[+t](val next: Input)
+ case class Success[+t](override val next: Input, result: t) extends ParseResult[t](next)
+ case class Failure(override val next: Input, msg: String) extends ParseResult[Nothing](next)
+
+ abstract class Parser[+t] {
+ def apply(in: Input): ParseResult[t]
+ }
+
+ // sequence
+ def sq[T, U](a: => Parser[T], b: => Parser[U]): Parser[Pair[T, U]] = new Parser[Pair[T, U]] {
+ def apply(in: Input): ParseResult[Pair[T, U]] = a(in) match {
+ case Success(next, x) => b(next) match {
+ case Success(next2, y) => Success(next2, Pair(x,y))
+ case Failure(_, msg) => Failure(in, msg)
+ }
+ case Failure(_, msg) => Failure(in, msg)
+ }
+ }
+
+ // ordered choice
+ def or[T, U <: T](a: => Parser[T], b: => Parser[U]): Parser[T] = new Parser[T] {
+ def apply(in: Input): ParseResult[T] = a(in) match {
+ case Success(next, x) => Success(next, x)
+ case Failure(_, _) => b(in) match {
+ case Success(next, y) => Success(next, y)
+ case Failure(_, msg) => Failure(in, msg)
+ }
+ }
+ }
+
+ // lifting
+ def lift[T, U](f: T => U)(a: => Parser[T]): Parser[U] = new Parser[U] {
+ def apply(in: Input): ParseResult[U] = a(in) match {
+ case Success(n, x) => Success(n, f(x))
+ case Failure(n, msg) => Failure(n, msg)
+ }
+ }
+
+ def accept[T](c: Char, r: T): Parser[T] = new Parser[T] {
+ def apply(in: Input) = in match {
+ case c2 :: n if c2 == c => Success(n, r)
+ case n => Failure(n, "expected "+c+" at the head of "+n)
+ }
+ }
+
+ def apply_++[s, tt](fun: Parser[s => tt], arg: Parser[s]): Parser[tt] = lift[Pair[s=>tt, s], tt]({case Pair(f, a) => f(a)})(sq(fun, arg))
+
+ def success[u](v: u): Parser[u] = new Parser[u] {
+ def apply(in: Input) = Success(in, v)
+ }
+
+}
+
+trait Idioms {
+ trait Idiom[idi[x]] {
+ def liftedApply[s, t](fun: idi[s => t])(arg: idi[s]): idi[t]
+ def pure[a](x: a): idi[a]
+ def pureMethod[a](name: String, x: a): idi[a] = pure(x) // hack for Mirrors: allow passing of method names
+ }
+
+ class IdiomaticTarget[idi[x], idiom <: Idiom[idi], s](i: idiom, tgt: s) {
+ def dot [t](fun: s => t, name: String) = new IdiomaticApp2[idi, idiom, t](i, i.liftedApply(i.pureMethod(name, fun))(i.pure(tgt)))
+ } // TODO: `.` --> java.lang.ClassFormatError: Illegal method name "." in class Idioms$IdiomaticTarget
+
+ class IdiomaticFunction[idi[x], idiom <: Idiom[idi], s, t](i: idiom, fun: s => t) {
+ def `(` (a: idi[s]) = new IdiomaticApp[idi, idiom, t](i, i.liftedApply(i.pure(fun))(a))
+ }
+
+ class IdiomaticApp[idi[x], idiom <: Idiom[idi], x](i: idiom, a: idi[x]) {
+ // where x <: s=>t -- TODO can this be expressed without generalised constraints?
+ def `,` [s, t](b: idi[s]) = new IdiomaticApp[idi, idiom, t](i, i.liftedApply(a.asInstanceOf[idi[s=>t]])(b))
+
+ def `)` : idi[x] = a
+ }
+
+ class IdiomaticApp2[idi[x], idiom <: Idiom[idi], x](i: idiom, a: idi[x]) extends IdiomaticApp[idi, idiom, x](i, a) {
+ def `(` [s, t](b: idi[s]) = `,`[s,t](b)
+ }
+}
+
+trait ParserIdioms extends Parsers with Idioms {
+ object ParserIdiom extends Idiom[Parser] {
+ def liftedApply[s, t](fun: Parser[s => t])(arg: Parser[s]): Parser[t] = apply_++(fun, arg)
+ def pure[a](x: a): Parser[a] = success(x)
+ }
+
+ implicit def parserIdiomFun[s, t](fun: s=>t): IdiomaticFunction[Parser, ParserIdiom.type, s, t] =
+ new IdiomaticFunction[Parser, ParserIdiom.type, s, t](ParserIdiom, fun)
+ implicit def parserIdiomTgt[s](tgt: s): IdiomaticTarget[Parser, ParserIdiom.type, s] =
+ new IdiomaticTarget[Parser, ParserIdiom.type, s](ParserIdiom, tgt)
+
+ trait Expr
+ case class Plus(a: Int, b: Int) extends Expr
+
+ def num = or(accept('0', 0), or(accept('1', 1),accept('2', 2)))
+
+ // TODO: how can parserIdiom(curry2(_)) be omitted?
+ def expr: Parser[Expr] = parserIdiomFun(curry2(Plus)) `(` num `,` num `)`
+
+ implicit def curry2[s,t,u](fun: (s, t)=>u)(a: s)(b: t) = fun(a, b)
+ implicit def curry3[r,s,t,u](fun: (r,s, t)=>u)(a: r)(b: s)(c: t) = fun(a, b, c)
+}
+
+object Test extends ParserIdioms with Application {
+ Console.println(expr(List.fromString("12")))
+}
diff --git a/test/pending/neg/tcpoly_variance_enforce_getter_setter.scala b/test/pending/neg/tcpoly_variance_enforce_getter_setter.scala
new file mode 100644
index 0000000000..7888b9e2a1
--- /dev/null
+++ b/test/pending/neg/tcpoly_variance_enforce_getter_setter.scala
@@ -0,0 +1,12 @@
+trait coll[+m[+x]]
+
+class FooInvar[x]
+class FooContra[-x]
+class FooCov[+x]
+
+object test {
+ var ok: coll[FooCov] = _
+
+ var x: coll[FooInvar] = _ // TODO: error should be reported only once instead of separately for getter and setter
+ var y: coll[FooContra] = _
+} \ No newline at end of file