aboutsummaryrefslogtreecommitdiff
path: root/tests/pos
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-03-12 15:06:17 +0100
committerTobias Schlatter <tobias@meisch.ch>2014-03-20 20:25:05 +0100
commita4516eac1be98830c99ea48e9baedf022dfcb9f7 (patch)
tree8e0e62943160fb948bf338ace7b01bd0990ad2bc /tests/pos
parent5b687fbee23060fbed285f090e3592f2b8cb6beb (diff)
downloaddotty-a4516eac1be98830c99ea48e9baedf022dfcb9f7.tar.gz
dotty-a4516eac1be98830c99ea48e9baedf022dfcb9f7.tar.bz2
dotty-a4516eac1be98830c99ea48e9baedf022dfcb9f7.zip
Hygienic desugaring
Made desugaring hygienic. Trees that are derived from some other tree are no longer stored as simple untyped Ident trees, but as TypeTrees that know how to derive their types from some other type. Test cases in pos: hygiene.scala, t0054.scala and t0085.scala. The comment in hygiene.scala points to the difficulties we are facing. In particular, we need type trees that can rebind some references of a source type to local occurrences with the same name. t0054.scala is similar to hygiene.scala. t0085.scala is trickier, but also related. Essentially the problem there is that we have a class that inherits its outer class. In this case it is important to resolve an identifier in the right context. The identifier added to the copy method of a case class must be resolved outside the class (just like the same identifier in the constructor of that case class).
Diffstat (limited to 'tests/pos')
-rw-r--r--tests/pos/A.scala8
-rw-r--r--tests/pos/hygiene.scala28
-rw-r--r--tests/pos/t0017.scala21
-rw-r--r--tests/pos/t0020.scala8
-rw-r--r--tests/pos/t0029.scala3
-rw-r--r--tests/pos/t0030.scala9
-rw-r--r--tests/pos/t0031.scala29
-rw-r--r--tests/pos/t0032.scala17
-rw-r--r--tests/pos/t0036.scala8
-rw-r--r--tests/pos/t0039.scala6
-rw-r--r--tests/pos/t0049.scala3
-rw-r--r--tests/pos/t0053.scala7
-rw-r--r--tests/pos/t0055.scala6
-rw-r--r--tests/pos/t0061.scala10
-rw-r--r--tests/pos/t0064.scala6
-rw-r--r--tests/pos/t0066.scala7
-rw-r--r--tests/pos/t0068.scala6
-rw-r--r--tests/pos/t0069.scala10
-rw-r--r--tests/pos/t0076.scala9
-rw-r--r--tests/pos/t0081.scala4
-rw-r--r--tests/pos/t0082.scala18
-rw-r--r--tests/pos/t0085.scala8
-rw-r--r--tests/pos/t0091.scala6
-rw-r--r--tests/pos/t0093.scala4
-rw-r--r--tests/pos/t0095.scala15
25 files changed, 256 insertions, 0 deletions
diff --git a/tests/pos/A.scala b/tests/pos/A.scala
new file mode 100644
index 000000000..fc50379d8
--- /dev/null
+++ b/tests/pos/A.scala
@@ -0,0 +1,8 @@
+trait A extends java.lang.Object {}
+
+object test {
+
+ def x: A = x;
+
+}
+
diff --git a/tests/pos/hygiene.scala b/tests/pos/hygiene.scala
new file mode 100644
index 000000000..25f234959
--- /dev/null
+++ b/tests/pos/hygiene.scala
@@ -0,0 +1,28 @@
+// Illustrates a failure with hygiene.
+
+object hygiene {
+
+ class D[T]
+
+ case class C[T](x: D[T])
+// gives
+// 7: error: wrong number of type arguments for hygiene.C.D, should be 0
+// 7: error: constructor C in class C does not take type parameters
+//
+// The second error message is straightforward to fix using a refTypeTree for C in
+// desugar.classDef.classTypeRef, but the first one is much harder.
+
+
+ object C {
+
+ class C
+
+// class D
+
+ }
+
+ val c = C.apply(new D)
+
+ c.x
+
+}
diff --git a/tests/pos/t0017.scala b/tests/pos/t0017.scala
new file mode 100644
index 000000000..d2bcda08d
--- /dev/null
+++ b/tests/pos/t0017.scala
@@ -0,0 +1,21 @@
+class Quantity {
+ def getValue = 0;
+ def connect(c: Constraint) = c.newValue;
+}
+
+abstract class Constraint(q: Quantity) {
+ def newValue: Unit;
+ q connect this
+}
+
+class Adder(q: Quantity) extends Constraint(q) {
+ def newValue = Console.println(q.getValue);
+}
+
+object Main {
+ def main(args: Array[String]): Unit = {
+ val x = new Quantity;
+ new Adder(x);
+ ()
+ }
+}
diff --git a/tests/pos/t0020.scala b/tests/pos/t0020.scala
new file mode 100644
index 000000000..4f1e5b173
--- /dev/null
+++ b/tests/pos/t0020.scala
@@ -0,0 +1,8 @@
+object Exceptions {
+
+ class CubeException(s: String) extends RuntimeException(s);
+
+ def main(args: Array[String]) =
+ Console.println(new CubeException("test"));
+
+}
diff --git a/tests/pos/t0029.scala b/tests/pos/t0029.scala
new file mode 100644
index 000000000..937b6d70c
--- /dev/null
+++ b/tests/pos/t0029.scala
@@ -0,0 +1,3 @@
+object Main {
+ def f[a]: List[List[a]] = for (l1 <- Nil; l2 <- Nil) yield l1
+}
diff --git a/tests/pos/t0030.scala b/tests/pos/t0030.scala
new file mode 100644
index 000000000..2f23be14d
--- /dev/null
+++ b/tests/pos/t0030.scala
@@ -0,0 +1,9 @@
+trait A {
+ def f(x: Int): Unit;
+ def f(x: String): Unit;
+}
+
+class B extends A {
+ def f(x: Int): Unit = ();
+ def f(x: String): Unit = ();
+}
diff --git a/tests/pos/t0031.scala b/tests/pos/t0031.scala
new file mode 100644
index 000000000..d4050c818
--- /dev/null
+++ b/tests/pos/t0031.scala
@@ -0,0 +1,29 @@
+object Main {
+
+ trait Ensure[a] {
+ def ensure(postcondition: a => Boolean): a
+ }
+
+ def require[a](precondition: => Boolean)(command: => a): Ensure[a] =
+ if (precondition)
+ new Ensure[a] {
+ def ensure(postcondition: a => Boolean): a = {
+ val result = command;
+ if (postcondition(result)) result
+ else sys.error("Assertion error")
+ }
+ }
+ else
+ sys.error("Assertion error");
+
+ def arb[a](s: List[a]) =
+ require (! s.isEmpty) {
+ s.head
+ } ensure (result => s contains result);
+
+ def main(args: Array[String]) = {
+ val s = List(1, 2);
+ Console.println(arb(s))
+ }
+
+}
diff --git a/tests/pos/t0032.scala b/tests/pos/t0032.scala
new file mode 100644
index 000000000..727a7d4e9
--- /dev/null
+++ b/tests/pos/t0032.scala
@@ -0,0 +1,17 @@
+import java.io.{OutputStream, PrintStream};
+
+class PromptStream(s: OutputStream) extends PrintStream(s) {
+ override def println() = super.println();
+}
+
+object Main {
+
+ val out = new PromptStream(java.lang.System.out);
+
+ java.lang.System.setOut(out);
+
+ def main(args: Array[String]) =
+ //out.println("hello world");
+ ()
+
+}
diff --git a/tests/pos/t0036.scala b/tests/pos/t0036.scala
new file mode 100644
index 000000000..3c9a84f8a
--- /dev/null
+++ b/tests/pos/t0036.scala
@@ -0,0 +1,8 @@
+object m {
+
+ val xs: List[Int] = Nil
+ def f(i: Int) = 0
+ val v = xs map f
+
+ def m() = {}
+}
diff --git a/tests/pos/t0039.scala b/tests/pos/t0039.scala
new file mode 100644
index 000000000..652c606b0
--- /dev/null
+++ b/tests/pos/t0039.scala
@@ -0,0 +1,6 @@
+abstract class Extensible[A, This <: Extensible[A, This]](x: A, xs: This) { self: This =>
+ def mkObj(x: A, xs: This): This;
+}
+class Fixed[A](x: A, xs: Fixed[A]) extends Extensible[A, Fixed[A]](x, xs) {
+ def mkObj(x: A, xs: Fixed[A]) = new Fixed(x, xs);
+}
diff --git a/tests/pos/t0049.scala b/tests/pos/t0049.scala
new file mode 100644
index 000000000..dd8664226
--- /dev/null
+++ b/tests/pos/t0049.scala
@@ -0,0 +1,3 @@
+class C1(x: AnyRef) {};
+
+class C2 extends C1({ class A extends AnyRef {}; (new A) : AnyRef }) {};
diff --git a/tests/pos/t0053.scala b/tests/pos/t0053.scala
new file mode 100644
index 000000000..44763ef14
--- /dev/null
+++ b/tests/pos/t0053.scala
@@ -0,0 +1,7 @@
+object bug {
+ def foobar[c]: Int = {
+ class Foo { def foo: Bar = new Bar(); }
+ class Bar { def bar: c = bar; }
+ 0
+ }
+}
diff --git a/tests/pos/t0055.scala b/tests/pos/t0055.scala
new file mode 100644
index 000000000..079629440
--- /dev/null
+++ b/tests/pos/t0055.scala
@@ -0,0 +1,6 @@
+class X(x : Any)
+class W {
+ new X(new Z() with Y) {}
+ trait Y { def y = () }
+}
+class Z(r : Any) { def this() = this(null) }
diff --git a/tests/pos/t0061.scala b/tests/pos/t0061.scala
new file mode 100644
index 000000000..dd3f94f30
--- /dev/null
+++ b/tests/pos/t0061.scala
@@ -0,0 +1,10 @@
+object O {
+
+ class testClass ;
+
+ case class testA() extends testClass ; // works if you leave away "extends..."
+ // or if you write TestA
+ def ga( x:testClass ) = x match {
+ case testA() => ()
+ }
+}
diff --git a/tests/pos/t0064.scala b/tests/pos/t0064.scala
new file mode 100644
index 000000000..1eeca8dca
--- /dev/null
+++ b/tests/pos/t0064.scala
@@ -0,0 +1,6 @@
+object B {
+ def main(Args:Array[String]) = {
+ val (_,x) = (1,2);
+ x + 1;
+ }
+}
diff --git a/tests/pos/t0066.scala b/tests/pos/t0066.scala
new file mode 100644
index 000000000..2153264e7
--- /dev/null
+++ b/tests/pos/t0066.scala
@@ -0,0 +1,7 @@
+class GBTree[A, B] /*with Map[A, B, GBTree[A,B]]*/ {
+ abstract class Tree[A,B];
+ case class Node[A,B](key:A,value:B,smaller:Node[A,B],bigger:Node[A,B])
+ extends Tree[A,B];
+ case class Nil[A,B]() extends Tree[A,B];
+
+}
diff --git a/tests/pos/t0068.scala b/tests/pos/t0068.scala
new file mode 100644
index 000000000..beb2c7c0a
--- /dev/null
+++ b/tests/pos/t0068.scala
@@ -0,0 +1,6 @@
+class E {
+ def f() = {
+ val (_::l1) = List(1,2,3);
+ l1.tail;
+ }
+}
diff --git a/tests/pos/t0069.scala b/tests/pos/t0069.scala
new file mode 100644
index 000000000..e4c242c0e
--- /dev/null
+++ b/tests/pos/t0069.scala
@@ -0,0 +1,10 @@
+object testCQ {
+ // why does this not work directly
+ case class Thing( name:String, contains:List[ Thing ] );
+
+ /* ... but this one does?
+ abstract class T;
+ case class Thing2( name:String, contains:List[ T ] ) extends T;
+ */
+
+}
diff --git a/tests/pos/t0076.scala b/tests/pos/t0076.scala
new file mode 100644
index 000000000..5419cf515
--- /dev/null
+++ b/tests/pos/t0076.scala
@@ -0,0 +1,9 @@
+// This is extracted from a test file => don't add a new test file.
+object bug {
+ def foo(i: => Int): Int = 0;
+
+ def bar: Int = {
+ var i: Int = 0;
+ foo (i);
+ }
+}
diff --git a/tests/pos/t0081.scala b/tests/pos/t0081.scala
new file mode 100644
index 000000000..20fd60497
--- /dev/null
+++ b/tests/pos/t0081.scala
@@ -0,0 +1,4 @@
+class A {
+ val b: A#B = new B;
+ class B {}
+}
diff --git a/tests/pos/t0082.scala b/tests/pos/t0082.scala
new file mode 100644
index 000000000..2b365ca33
--- /dev/null
+++ b/tests/pos/t0082.scala
@@ -0,0 +1,18 @@
+
+object Main {
+
+ def min0[A](less: (A, A) => Boolean, xs: List[A]): Option[A] = xs match {
+ case List() => None
+ case List(x) => Some(x)
+// case x :: Nil => Some(x)
+ case y :: ys => (min0(less, ys): @unchecked) match {
+ case Some(m) => if (less(y, m)) Some(y) else Some(m)
+ }
+ }
+
+ def min(xs: List[Int]) = min0((x: Int, y: Int) => x < y, xs);
+
+ def main(args: Array[String]) =
+ Console.println(min(List()));
+
+}
diff --git a/tests/pos/t0085.scala b/tests/pos/t0085.scala
new file mode 100644
index 000000000..e018afb6e
--- /dev/null
+++ b/tests/pos/t0085.scala
@@ -0,0 +1,8 @@
+object A {
+ case class B(c: C) {
+ class C;
+ }
+ class C;
+ val b: B = new B(new C());
+ val c: C = b.c;
+}
diff --git a/tests/pos/t0091.scala b/tests/pos/t0091.scala
new file mode 100644
index 000000000..d491b7cfb
--- /dev/null
+++ b/tests/pos/t0091.scala
@@ -0,0 +1,6 @@
+class Bug {
+ def main(args: Array[String]) = {
+ var msg: String = null; // no bug if "null" instead of "_"
+ val f: PartialFunction[Any, Unit] = { case 42 => msg = "coucou" };
+ }
+}
diff --git a/tests/pos/t0093.scala b/tests/pos/t0093.scala
new file mode 100644
index 000000000..d648d773b
--- /dev/null
+++ b/tests/pos/t0093.scala
@@ -0,0 +1,4 @@
+object Bug {
+ def f(cond: => Boolean) = while (cond == false) {};
+ // no bug with "false == cond"
+}
diff --git a/tests/pos/t0095.scala b/tests/pos/t0095.scala
new file mode 100644
index 000000000..2123237b5
--- /dev/null
+++ b/tests/pos/t0095.scala
@@ -0,0 +1,15 @@
+class ParseResult[+T]
+case class Success[+T](t: T) extends ParseResult[T]
+
+abstract class Nonterminal[Output] {
+
+ type SubNonterminal = Nonterminal[_ <: Output]
+
+ def parse: ParseResult[Output]
+
+ def parse1(nts: List[SubNonterminal]): ParseResult[Output] =
+ nts match {
+ case nt::nts => nt.parse match { case Success(so) => Success(so) }
+ case Nil => throw new Error
+ }
+}