summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-09-02 17:27:57 +0000
committerMartin Odersky <odersky@gmail.com>2003-09-02 17:27:57 +0000
commitd8a3d0acaa3ff4bae5a20ff64d265754e7c1fbe5 (patch)
treeb22dd299335625f6970d2374dda2001e66cc755e
parentdd1ebac2aae5844ba01dbe2aab6e7fd67e19c15a (diff)
downloadscala-d8a3d0acaa3ff4bae5a20ff64d265754e7c1fbe5.tar.gz
scala-d8a3d0acaa3ff4bae5a20ff64d265754e7c1fbe5.tar.bz2
scala-d8a3d0acaa3ff4bae5a20ff64d265754e7c1fbe5.zip
*** empty log message ***
-rw-r--r--sources/scalac/ast/parser/Parser.java1
-rw-r--r--sources/scalac/symtab/Definitions.java2
-rw-r--r--sources/scalac/symtab/Symbol.java5
-rw-r--r--sources/scalac/transformer/UnCurry.java7
-rw-r--r--sources/scalac/typechecker/Analyzer.java11
-rw-r--r--test/files/neg/bug86.check4
-rw-r--r--test/files/neg/bug86.scala7
-rw-r--r--test/files/neg/bug87.check4
-rw-r--r--test/files/neg/bug87.scala3
-rw-r--r--test/files/neg/bug95.check7
-rw-r--r--test/files/neg/bug95.scala2
-rw-r--r--test/files/neg/bug96.check5
-rw-r--r--test/files/neg/bug96.scala6
-rw-r--r--test/files/neg/bug97.check4
-rw-r--r--test/files/neg/bug97.scala7
-rw-r--r--test/files/pos/bug81.scala4
-rw-r--r--test/files/pos/bug85.scala8
-rw-r--r--test/files/pos/bug91.scala6
-rw-r--r--test/files/pos/bug93.scala4
-rw-r--r--test/files/pos/compound.scala9
-rw-r--r--test/files/pos/gui.scala99
-rw-r--r--test/files/pos/thistype.scala14
-rw-r--r--test/files/pos/traits.scala42
-rw-r--r--test/neg/bug86.check4
-rw-r--r--test/neg/bug86.scala7
-rw-r--r--test/neg/bug87.check4
-rw-r--r--test/neg/bug87.scala3
-rw-r--r--test/neg/bug95.check7
-rw-r--r--test/neg/bug95.scala2
-rw-r--r--test/neg/bug96.check5
-rw-r--r--test/neg/bug96.scala6
-rw-r--r--test/neg/bug97.check4
-rw-r--r--test/neg/bug97.scala7
-rw-r--r--test/pos/bug81.scala4
-rw-r--r--test/pos/bug85.scala8
-rw-r--r--test/pos/bug91.scala6
-rw-r--r--test/pos/bug93.scala4
-rw-r--r--test/pos/compound.scala9
-rw-r--r--test/pos/gui.scala99
-rw-r--r--test/pos/thistype.scala14
-rw-r--r--test/pos/traits.scala42
41 files changed, 486 insertions, 10 deletions
diff --git a/sources/scalac/ast/parser/Parser.java b/sources/scalac/ast/parser/Parser.java
index 7a6cd2b3db..7206114a39 100644
--- a/sources/scalac/ast/parser/Parser.java
+++ b/sources/scalac/ast/parser/Parser.java
@@ -1671,6 +1671,7 @@ public class Parser implements Tokens {
return ts.toArray();
case OBJECT:
case CASEOBJECT:
+ if (s.token == CASEOBJECT) mods |= Modifiers.CASE;
do {
s.nextToken();
ts.append(objectDef(mods));
diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java
index 7a33403004..e9f000b848 100644
--- a/sources/scalac/symtab/Definitions.java
+++ b/sources/scalac/symtab/Definitions.java
@@ -236,8 +236,6 @@ public class Definitions {
// the scala.ANYVAL class
ANYVAL_CLASS = getClass(Names.scala_AnyVal);
- ANYVAL_CLASS.initialize();
- ANYVAL_CLASS.flags |= Modifiers.SEALED;
ANYVAL_TYPE = ANYVAL_CLASS.typeConstructor();
// the scala.ALL class
diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java
index 04eff30d3a..5acaec4dee 100644
--- a/sources/scalac/symtab/Symbol.java
+++ b/sources/scalac/symtab/Symbol.java
@@ -255,6 +255,11 @@ public abstract class Symbol implements Modifiers, Kinds {
return (flags & FINAL) != 0;
}
+ /** Does this symbol denote a sealed class symbol? */
+ public final boolean isSealed() {
+ return (flags & SEALED) != 0;
+ }
+
/** Does this symbol denote a method?
*/
public final boolean isInitializedMethod() {
diff --git a/sources/scalac/transformer/UnCurry.java b/sources/scalac/transformer/UnCurry.java
index 3cae85252a..6294631ce5 100644
--- a/sources/scalac/transformer/UnCurry.java
+++ b/sources/scalac/transformer/UnCurry.java
@@ -53,7 +53,8 @@ public class UnCurry extends OwnerTransformer
case MethodType(_, _):
return tree;
default:
- return tree.setType(Type.MethodType(Symbol.EMPTY_ARRAY, tree.type));
+ return tree.setType(
+ Type.MethodType(Symbol.EMPTY_ARRAY, tree.type.widen()));
}
}
@@ -145,7 +146,7 @@ public class UnCurry extends OwnerTransformer
default:
if (tree1.symbol().isDefParameter()) {
tree1.type = global.definitions.functionType(
- Type.EMPTY_ARRAY, tree1.type);
+ Type.EMPTY_ARRAY, tree1.type.widen());
return gen.Apply(gen.Select(tree1, Names.apply), new Tree[0]);
} else {
return tree1;
@@ -214,7 +215,7 @@ public class UnCurry extends OwnerTransformer
}
}
return transform(
- gen.mkUnitFunction(arg, descr.uncurry(arg.type), currentOwner));
+ gen.mkUnitFunction(arg, descr.uncurry(arg.type.widen()), currentOwner));
} else {
return transform(arg);
}
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 8cf7347498..2c887c9393 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -368,7 +368,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
if ((bsym.flags & FINAL) != 0) {
error(constrs[i].pos, "illegal inheritance from final class");
- } else if ((bsym.flags & SEALED) != 0) {
+ } else if (bsym.isSealed() ||
+ bsym.isSubClass(definitions.ANYVAL_CLASS)) {
// are we in same scope as base type definition?
Scope.Entry e = context.scope.lookupEntry(bsym.name);
if (e.sym != bsym || e.owner != context.scope) {
@@ -1248,12 +1249,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (seqtp != Type.NoType) {
tree.type = seqConstructorType(seqtp, pt);
} else {
- error(tree.pos, "expected pattern type " + pt +
- " does not conform to sequence " + clazz);
+ return error(tree.pos, "expected pattern type " + pt +
+ " does not conform to sequence " + clazz);
}
} else if (tree.type != Type.ErrorType) {
- error(tree.pos, tree.type.symbol() +
- " is neither a case class constructor nor a sequence class constructor");
+ return error(tree.pos, tree.type.symbol() +
+ " is neither a case class constructor nor a sequence class constructor");
}
}
if ((mode & FUNmode) != 0) {
diff --git a/test/files/neg/bug86.check b/test/files/neg/bug86.check
new file mode 100644
index 0000000000..9ef489429c
--- /dev/null
+++ b/test/files/neg/bug86.check
@@ -0,0 +1,4 @@
+bug86.scala:4: trait Foo is abstract, so it cannot be instantiated
+ new Foo();
+ ^
+one error found
diff --git a/test/files/neg/bug86.scala b/test/files/neg/bug86.scala
new file mode 100644
index 0000000000..a11f49aa90
--- /dev/null
+++ b/test/files/neg/bug86.scala
@@ -0,0 +1,7 @@
+trait Foo();
+
+object foo {
+ new Foo();
+ new Foo(){};
+ new Foo(){0};
+}
diff --git a/test/files/neg/bug87.check b/test/files/neg/bug87.check
new file mode 100644
index 0000000000..595ba64ee4
--- /dev/null
+++ b/test/files/neg/bug87.check
@@ -0,0 +1,4 @@
+bug87.scala:2: type C is not a member of foo
+ new foo.C;
+ ^
+one error found
diff --git a/test/files/neg/bug87.scala b/test/files/neg/bug87.scala
new file mode 100644
index 0000000000..8e9a84928f
--- /dev/null
+++ b/test/files/neg/bug87.scala
@@ -0,0 +1,3 @@
+object foo {
+ new foo.C;
+}
diff --git a/test/files/neg/bug95.check b/test/files/neg/bug95.check
new file mode 100644
index 0000000000..d142a27b6f
--- /dev/null
+++ b/test/files/neg/bug95.check
@@ -0,0 +1,7 @@
+test/neg/bug95.scala:1: illegal inheritance from sealed class
+class C extends AnyVal;
+ ^
+test/neg/bug95.scala:2: illegal inheritance from sealed class
+class T extends Unit;
+ ^
+two errors found
diff --git a/test/files/neg/bug95.scala b/test/files/neg/bug95.scala
new file mode 100644
index 0000000000..9893d7f5a4
--- /dev/null
+++ b/test/files/neg/bug95.scala
@@ -0,0 +1,2 @@
+class C extends AnyVal;
+class T extends Unit;
diff --git a/test/files/neg/bug96.check b/test/files/neg/bug96.check
new file mode 100644
index 0000000000..ab5871b39e
--- /dev/null
+++ b/test/files/neg/bug96.check
@@ -0,0 +1,5 @@
+bug96.scala:5: method foo in class B of type (def scala.Any)scala.Object
+ cannot override method foo in class A of type (scala.Any)scala.Object
+ override def foo(def x: Any): Object = null;
+ ^
+one error found
diff --git a/test/files/neg/bug96.scala b/test/files/neg/bug96.scala
new file mode 100644
index 0000000000..4694e9edc7
--- /dev/null
+++ b/test/files/neg/bug96.scala
@@ -0,0 +1,6 @@
+class A {
+ def foo(x: Any): Object = null;
+}
+class B extends A {
+ override def foo(def x: Any): Object = null;
+}
diff --git a/test/files/neg/bug97.check b/test/files/neg/bug97.check
new file mode 100644
index 0000000000..5d4fcacb1b
--- /dev/null
+++ b/test/files/neg/bug97.check
@@ -0,0 +1,4 @@
+test/neg/bug97.scala:3: expected pattern type scala.Any does not conform to sequence trait scala.List
+ case List(y) => "zero"
+ ^
+one error found
diff --git a/test/files/neg/bug97.scala b/test/files/neg/bug97.scala
new file mode 100644
index 0000000000..c9bfebcfa0
--- /dev/null
+++ b/test/files/neg/bug97.scala
@@ -0,0 +1,7 @@
+object Main {
+ def foo(x: Any) = x match {
+ case List(y) => "zero"
+ case y :: ys => "one"
+ }
+ def main(args: Array[String]) = System.out.println(List(1, 2));
+}
diff --git a/test/files/pos/bug81.scala b/test/files/pos/bug81.scala
new file mode 100644
index 0000000000..20fd604974
--- /dev/null
+++ b/test/files/pos/bug81.scala
@@ -0,0 +1,4 @@
+class A {
+ val b: A#B = new B;
+ class B {}
+}
diff --git a/test/files/pos/bug85.scala b/test/files/pos/bug85.scala
new file mode 100644
index 0000000000..e018afb6ee
--- /dev/null
+++ b/test/files/pos/bug85.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/test/files/pos/bug91.scala b/test/files/pos/bug91.scala
new file mode 100644
index 0000000000..e05365caf4
--- /dev/null
+++ b/test/files/pos/bug91.scala
@@ -0,0 +1,6 @@
+class Bug {
+ def main(args: Array[String]) = {
+ var msg: String = _; // no bug if "null" instead of "_"
+ val f: PartialFunction[Any, unit] = { case 42 => msg = "coucou" };
+ }
+}
diff --git a/test/files/pos/bug93.scala b/test/files/pos/bug93.scala
new file mode 100644
index 0000000000..f3441fe9c3
--- /dev/null
+++ b/test/files/pos/bug93.scala
@@ -0,0 +1,4 @@
+object Bug {
+ def f(def cond: Boolean) = while (cond == false) {};
+ // no bug with "false == cond"
+}
diff --git a/test/files/pos/compound.scala b/test/files/pos/compound.scala
new file mode 100644
index 0000000000..60890f9102
--- /dev/null
+++ b/test/files/pos/compound.scala
@@ -0,0 +1,9 @@
+abstract class A { type T }
+
+abstract class B { val xz: Any }
+
+abstract class Test {
+ var yy: A with B { type T; val xz: T } = null;
+ var xx: A with B { type T; val xz: T } = null;
+ xx = yy;
+}
diff --git a/test/files/pos/gui.scala b/test/files/pos/gui.scala
new file mode 100644
index 0000000000..27863f7368
--- /dev/null
+++ b/test/files/pos/gui.scala
@@ -0,0 +1,99 @@
+object Geom {
+ trait Shape;
+ case class Point(x: int, y: int) extends Shape;
+ case class Rectangle(ll: Point, ur: Point) extends Shape {
+ def inset(delta: int) =
+ Rectangle(Point(ll.x - delta, ll.y - delta), Point(ur.x + delta, ur.y + delta));
+ }
+}
+
+object Color {
+ type Color = int;
+ val black = 0x000000;
+ val grey = 0x808080;
+}
+
+trait Screen {
+ type Color = int;
+ def drawRect(r: Geom.Rectangle, c: Color): unit;
+ def fillRect(r: Geom.Rectangle, c: Color): unit;
+}
+
+object DummyScreen extends Screen {
+ def drawRect(r: Geom.Rectangle, c: Color): unit =
+ System.out.println("draw " + r + " with " + c);
+ def fillRect(r: Geom.Rectangle, c: Color): unit =
+ System.out.println("fill " + r + " with " + c);
+}
+
+object GUI {
+
+ object Controller {
+ def addMouseCtl(c: MouseCtl) = ()
+ }
+
+ trait Glyph {
+ def getRect: Geom.Rectangle;
+ def setLoc(p: Geom.Point): unit;
+ def draw() = System.out.println("draw " + this);
+ }
+
+ class Label(scr: Screen, p: Geom.Point, name: String) extends Glyph {
+ private var origin = p;
+ def getRect = Geom.Rectangle(origin, origin).inset(10);
+ def setLoc(p: Geom.Point) = { origin = p }
+ }
+
+ trait Ctl {
+ def getGlyph: Glyph;
+ def enable(b: Boolean): this.type;
+ }
+
+ trait MouseCtl with Ctl {
+ def mouseDown(p: Geom.Point): unit;
+ }
+
+ abstract class Button(scr: Screen, p: Geom.Point, name: String)
+ extends Glyph with MouseCtl {
+ var enabled: boolean = false;
+ val label = new Label(scr, p, name);
+
+ /* Glyph methods */
+ override def draw(): unit = {
+ if (enabled) scr.drawRect(getRect, Color.black)
+ else scr.fillRect(getRect, Color.grey);
+ label.draw();
+ }
+ def setLoc(p: Geom.Point) = label.setLoc(p);
+ def getRect = label.getRect.inset(-2);
+
+ /* Ctl methods */
+ def enable(b: boolean): this.type = { enabled = b; draw(); this }
+ def getGlyph = label;
+ final def mouseDown(p: Geom.Point): unit =
+ if (enabled) doit() else System.out.println("button is disabled");
+
+ /* deferred method to be specified by client */
+ def doit(): unit;
+ }
+}
+
+object GUIClient {
+
+ class Application {
+ def quit() = System.out.println("application exited");
+ }
+
+ class QuitButton (scr: Screen, p: Geom.Point, name: String, a: Application)
+ extends GUI.Button(scr, p, name) {
+ def doit(): unit = a.quit();
+ }
+
+ def main(args: Array[String]) = {
+ val b = new QuitButton(
+ DummyScreen, Geom.Point(1, 1), "quit", new Application);
+ b.draw();
+ b.enable(true).mouseDown(Geom.Point(1, 2));
+ }
+}
+
diff --git a/test/files/pos/thistype.scala b/test/files/pos/thistype.scala
new file mode 100644
index 0000000000..8c0ba209be
--- /dev/null
+++ b/test/files/pos/thistype.scala
@@ -0,0 +1,14 @@
+object Test {
+
+ class Ctl {
+ def enable: this.type = { System.out.println("enable"); this }
+ }
+
+ class MouseCtl extends Ctl {
+ def mouseDown(x: int, y: int): unit = { System.out.println("mouse down"); }
+ }
+
+ def main(args: Array[String]) =
+ new MouseCtl().enable.mouseDown(1, 2);
+
+}
diff --git a/test/files/pos/traits.scala b/test/files/pos/traits.scala
new file mode 100644
index 0000000000..5fdf4b342e
--- /dev/null
+++ b/test/files/pos/traits.scala
@@ -0,0 +1,42 @@
+object Test {
+ type Color = int;
+ trait Shape {
+ override def equals(other: Any) = true;
+ }
+ trait Bordered extends Shape {
+ val thickness: int;
+ override def equals(other: Any) = other match {
+ case that: Bordered => this.thickness == that.thickness;
+ case _ => false
+ }
+ }
+ trait Colored extends Shape {
+ val color: Color;
+ override def equals(other: Any) = other match {
+ case that: Colored => this.color == that.color;
+ case _ => false
+ }
+ }
+ trait BorderedColoredShape extends Shape with Bordered with Colored {
+ override def equals(other: Any) = other match {
+ case that: BorderedColoredShape =>
+ super.equals(that) &&
+ super[Bordered].equals(that) &&
+ super[Colored].equals(that)
+ case _ => false
+ }
+ }
+
+ val bcs1 = new BorderedColoredShape {
+ val thickness = 1;
+ val color = 0;
+ }
+ val bcs2 = new BorderedColoredShape {
+ val thickness = 2;
+ val color = 0;
+ }
+ System.out.println(bcs1 == bcs1);
+ System.out.println(bcs1 == bcs2);
+}
+
+
diff --git a/test/neg/bug86.check b/test/neg/bug86.check
new file mode 100644
index 0000000000..9ef489429c
--- /dev/null
+++ b/test/neg/bug86.check
@@ -0,0 +1,4 @@
+bug86.scala:4: trait Foo is abstract, so it cannot be instantiated
+ new Foo();
+ ^
+one error found
diff --git a/test/neg/bug86.scala b/test/neg/bug86.scala
new file mode 100644
index 0000000000..a11f49aa90
--- /dev/null
+++ b/test/neg/bug86.scala
@@ -0,0 +1,7 @@
+trait Foo();
+
+object foo {
+ new Foo();
+ new Foo(){};
+ new Foo(){0};
+}
diff --git a/test/neg/bug87.check b/test/neg/bug87.check
new file mode 100644
index 0000000000..595ba64ee4
--- /dev/null
+++ b/test/neg/bug87.check
@@ -0,0 +1,4 @@
+bug87.scala:2: type C is not a member of foo
+ new foo.C;
+ ^
+one error found
diff --git a/test/neg/bug87.scala b/test/neg/bug87.scala
new file mode 100644
index 0000000000..8e9a84928f
--- /dev/null
+++ b/test/neg/bug87.scala
@@ -0,0 +1,3 @@
+object foo {
+ new foo.C;
+}
diff --git a/test/neg/bug95.check b/test/neg/bug95.check
new file mode 100644
index 0000000000..d142a27b6f
--- /dev/null
+++ b/test/neg/bug95.check
@@ -0,0 +1,7 @@
+test/neg/bug95.scala:1: illegal inheritance from sealed class
+class C extends AnyVal;
+ ^
+test/neg/bug95.scala:2: illegal inheritance from sealed class
+class T extends Unit;
+ ^
+two errors found
diff --git a/test/neg/bug95.scala b/test/neg/bug95.scala
new file mode 100644
index 0000000000..9893d7f5a4
--- /dev/null
+++ b/test/neg/bug95.scala
@@ -0,0 +1,2 @@
+class C extends AnyVal;
+class T extends Unit;
diff --git a/test/neg/bug96.check b/test/neg/bug96.check
new file mode 100644
index 0000000000..ab5871b39e
--- /dev/null
+++ b/test/neg/bug96.check
@@ -0,0 +1,5 @@
+bug96.scala:5: method foo in class B of type (def scala.Any)scala.Object
+ cannot override method foo in class A of type (scala.Any)scala.Object
+ override def foo(def x: Any): Object = null;
+ ^
+one error found
diff --git a/test/neg/bug96.scala b/test/neg/bug96.scala
new file mode 100644
index 0000000000..4694e9edc7
--- /dev/null
+++ b/test/neg/bug96.scala
@@ -0,0 +1,6 @@
+class A {
+ def foo(x: Any): Object = null;
+}
+class B extends A {
+ override def foo(def x: Any): Object = null;
+}
diff --git a/test/neg/bug97.check b/test/neg/bug97.check
new file mode 100644
index 0000000000..5d4fcacb1b
--- /dev/null
+++ b/test/neg/bug97.check
@@ -0,0 +1,4 @@
+test/neg/bug97.scala:3: expected pattern type scala.Any does not conform to sequence trait scala.List
+ case List(y) => "zero"
+ ^
+one error found
diff --git a/test/neg/bug97.scala b/test/neg/bug97.scala
new file mode 100644
index 0000000000..c9bfebcfa0
--- /dev/null
+++ b/test/neg/bug97.scala
@@ -0,0 +1,7 @@
+object Main {
+ def foo(x: Any) = x match {
+ case List(y) => "zero"
+ case y :: ys => "one"
+ }
+ def main(args: Array[String]) = System.out.println(List(1, 2));
+}
diff --git a/test/pos/bug81.scala b/test/pos/bug81.scala
new file mode 100644
index 0000000000..20fd604974
--- /dev/null
+++ b/test/pos/bug81.scala
@@ -0,0 +1,4 @@
+class A {
+ val b: A#B = new B;
+ class B {}
+}
diff --git a/test/pos/bug85.scala b/test/pos/bug85.scala
new file mode 100644
index 0000000000..e018afb6ee
--- /dev/null
+++ b/test/pos/bug85.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/test/pos/bug91.scala b/test/pos/bug91.scala
new file mode 100644
index 0000000000..e05365caf4
--- /dev/null
+++ b/test/pos/bug91.scala
@@ -0,0 +1,6 @@
+class Bug {
+ def main(args: Array[String]) = {
+ var msg: String = _; // no bug if "null" instead of "_"
+ val f: PartialFunction[Any, unit] = { case 42 => msg = "coucou" };
+ }
+}
diff --git a/test/pos/bug93.scala b/test/pos/bug93.scala
new file mode 100644
index 0000000000..f3441fe9c3
--- /dev/null
+++ b/test/pos/bug93.scala
@@ -0,0 +1,4 @@
+object Bug {
+ def f(def cond: Boolean) = while (cond == false) {};
+ // no bug with "false == cond"
+}
diff --git a/test/pos/compound.scala b/test/pos/compound.scala
new file mode 100644
index 0000000000..60890f9102
--- /dev/null
+++ b/test/pos/compound.scala
@@ -0,0 +1,9 @@
+abstract class A { type T }
+
+abstract class B { val xz: Any }
+
+abstract class Test {
+ var yy: A with B { type T; val xz: T } = null;
+ var xx: A with B { type T; val xz: T } = null;
+ xx = yy;
+}
diff --git a/test/pos/gui.scala b/test/pos/gui.scala
new file mode 100644
index 0000000000..27863f7368
--- /dev/null
+++ b/test/pos/gui.scala
@@ -0,0 +1,99 @@
+object Geom {
+ trait Shape;
+ case class Point(x: int, y: int) extends Shape;
+ case class Rectangle(ll: Point, ur: Point) extends Shape {
+ def inset(delta: int) =
+ Rectangle(Point(ll.x - delta, ll.y - delta), Point(ur.x + delta, ur.y + delta));
+ }
+}
+
+object Color {
+ type Color = int;
+ val black = 0x000000;
+ val grey = 0x808080;
+}
+
+trait Screen {
+ type Color = int;
+ def drawRect(r: Geom.Rectangle, c: Color): unit;
+ def fillRect(r: Geom.Rectangle, c: Color): unit;
+}
+
+object DummyScreen extends Screen {
+ def drawRect(r: Geom.Rectangle, c: Color): unit =
+ System.out.println("draw " + r + " with " + c);
+ def fillRect(r: Geom.Rectangle, c: Color): unit =
+ System.out.println("fill " + r + " with " + c);
+}
+
+object GUI {
+
+ object Controller {
+ def addMouseCtl(c: MouseCtl) = ()
+ }
+
+ trait Glyph {
+ def getRect: Geom.Rectangle;
+ def setLoc(p: Geom.Point): unit;
+ def draw() = System.out.println("draw " + this);
+ }
+
+ class Label(scr: Screen, p: Geom.Point, name: String) extends Glyph {
+ private var origin = p;
+ def getRect = Geom.Rectangle(origin, origin).inset(10);
+ def setLoc(p: Geom.Point) = { origin = p }
+ }
+
+ trait Ctl {
+ def getGlyph: Glyph;
+ def enable(b: Boolean): this.type;
+ }
+
+ trait MouseCtl with Ctl {
+ def mouseDown(p: Geom.Point): unit;
+ }
+
+ abstract class Button(scr: Screen, p: Geom.Point, name: String)
+ extends Glyph with MouseCtl {
+ var enabled: boolean = false;
+ val label = new Label(scr, p, name);
+
+ /* Glyph methods */
+ override def draw(): unit = {
+ if (enabled) scr.drawRect(getRect, Color.black)
+ else scr.fillRect(getRect, Color.grey);
+ label.draw();
+ }
+ def setLoc(p: Geom.Point) = label.setLoc(p);
+ def getRect = label.getRect.inset(-2);
+
+ /* Ctl methods */
+ def enable(b: boolean): this.type = { enabled = b; draw(); this }
+ def getGlyph = label;
+ final def mouseDown(p: Geom.Point): unit =
+ if (enabled) doit() else System.out.println("button is disabled");
+
+ /* deferred method to be specified by client */
+ def doit(): unit;
+ }
+}
+
+object GUIClient {
+
+ class Application {
+ def quit() = System.out.println("application exited");
+ }
+
+ class QuitButton (scr: Screen, p: Geom.Point, name: String, a: Application)
+ extends GUI.Button(scr, p, name) {
+ def doit(): unit = a.quit();
+ }
+
+ def main(args: Array[String]) = {
+ val b = new QuitButton(
+ DummyScreen, Geom.Point(1, 1), "quit", new Application);
+ b.draw();
+ b.enable(true).mouseDown(Geom.Point(1, 2));
+ }
+}
+
diff --git a/test/pos/thistype.scala b/test/pos/thistype.scala
new file mode 100644
index 0000000000..8c0ba209be
--- /dev/null
+++ b/test/pos/thistype.scala
@@ -0,0 +1,14 @@
+object Test {
+
+ class Ctl {
+ def enable: this.type = { System.out.println("enable"); this }
+ }
+
+ class MouseCtl extends Ctl {
+ def mouseDown(x: int, y: int): unit = { System.out.println("mouse down"); }
+ }
+
+ def main(args: Array[String]) =
+ new MouseCtl().enable.mouseDown(1, 2);
+
+}
diff --git a/test/pos/traits.scala b/test/pos/traits.scala
new file mode 100644
index 0000000000..5fdf4b342e
--- /dev/null
+++ b/test/pos/traits.scala
@@ -0,0 +1,42 @@
+object Test {
+ type Color = int;
+ trait Shape {
+ override def equals(other: Any) = true;
+ }
+ trait Bordered extends Shape {
+ val thickness: int;
+ override def equals(other: Any) = other match {
+ case that: Bordered => this.thickness == that.thickness;
+ case _ => false
+ }
+ }
+ trait Colored extends Shape {
+ val color: Color;
+ override def equals(other: Any) = other match {
+ case that: Colored => this.color == that.color;
+ case _ => false
+ }
+ }
+ trait BorderedColoredShape extends Shape with Bordered with Colored {
+ override def equals(other: Any) = other match {
+ case that: BorderedColoredShape =>
+ super.equals(that) &&
+ super[Bordered].equals(that) &&
+ super[Colored].equals(that)
+ case _ => false
+ }
+ }
+
+ val bcs1 = new BorderedColoredShape {
+ val thickness = 1;
+ val color = 0;
+ }
+ val bcs2 = new BorderedColoredShape {
+ val thickness = 2;
+ val color = 0;
+ }
+ System.out.println(bcs1 == bcs1);
+ System.out.println(bcs1 == bcs2);
+}
+
+