diff options
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); +} + + |