From 88cd71a283f25b20414b1a22b9fded83692ffc14 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 25 Apr 2006 14:01:59 +0000 Subject: --- src/compiler/scala/tools/nsc/symtab/Types.scala | 8 +++- src/compiler/scala/tools/nsc/transform/Mixin.scala | 2 +- .../scala/tools/nsc/typechecker/Namers.scala | 6 ++- .../scala/tools/nsc/typechecker/RefChecks.scala | 6 ++- .../scala/tools/nsc/typechecker/Typers.scala | 17 ++++++++- test/pending/pos/bug572.scala | 33 ++++++++++++++++ test/pending/pos/bug573.scala | 43 +++++++++++++++++++++ test/pending/pos/foo.scala | 3 ++ test/pending/pos/gosh.scala | 44 ++++++++++++++++++++++ test/pending/pos/moors.scala | 12 ++++++ test/pending/run/exc.scala | 10 +++++ test/pending/run/exc1.scala | 10 +++++ test/pending/run/exc2.scala | 12 ++++++ 13 files changed, 197 insertions(+), 9 deletions(-) create mode 100644 test/pending/pos/bug572.scala create mode 100644 test/pending/pos/bug573.scala create mode 100755 test/pending/pos/foo.scala create mode 100755 test/pending/pos/gosh.scala create mode 100644 test/pending/pos/moors.scala create mode 100755 test/pending/run/exc.scala create mode 100755 test/pending/run/exc1.scala create mode 100755 test/pending/run/exc2.scala diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 428bdb3ab6..883a45b8a2 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -201,7 +201,11 @@ trait Types requires SymbolTable { def memberType(sym: Symbol): Type = { sym.tpe match { case OverloadedType(pre, alts) => - assert(this =:= pre); + val pre1 = pre match { + case ClassInfoType(_, _, clazz) => clazz.tpe + case _ => pre + } + assert(this =:= pre1); sym.tpe case _ => //System.out.println("" + this + ".memberType(" + sym +":" + sym.tpe +")");//DEBUG @@ -2035,7 +2039,7 @@ trait Types requires SymbolTable { /** Make symbol `sym' a member of scope `tp.decls' where `thistp' is the narrowed * owner type of the scope */ - private def addMember(thistp: Type, tp: Type, sym: Symbol): unit = { + def addMember(thistp: Type, tp: Type, sym: Symbol): unit = { if (settings.debug.value) log("add member " + sym);//debug if (!(thistp specializes sym)) { if (sym.isTerm) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index c7f9f775fd..e8f36bf785 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -260,7 +260,7 @@ abstract class Mixin extends InfoTransform { private def addNewDefs(clazz: Symbol, stats: List[Tree]): List[Tree] = { val newDefs = new ListBuffer[Tree]; def addDef(pos: int, tree: Tree): unit = { - if (settings.debug.value) log("add new def to " + clazz + ": " + tree); + if (settings.debug.value) System.out.println("add new def to " + clazz + ": " + tree); newDefs += localTyper.typed { atPos(pos) { tree diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 6c42012d18..a74c7f20b9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -22,8 +22,8 @@ trait Namers requires Analyzer { class DeSkolemizeMap(tparams: List[Symbol]) extends TypeMap { def apply(tp: Type): Type = tp match { case TypeRef(pre, sym, args) => - val tparam = sym.deSkolemize; - mapOver( + val tparam = sym.deSkolemize; + mapOver( if (tparam == sym || !(tparams contains tparam)) tp else rawTypeRef(NoPrefix, tparam, args)) case SingleType(pre, sym) if (sym.isThisSkolem) => @@ -551,6 +551,8 @@ trait Namers requires Analyzer { "\nit should be omitted for abstract members"); if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && sym.isClass) context.error(sym.pos, "`override' modifier not allowed for classes"); + if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && sym.isConstructor) + context.error(sym.pos, "`override' modifier not allowed for constructors"); if (sym.hasFlag(ABSOVERRIDE) && !sym.owner.isTrait) context.error(sym.pos, "`abstract override' modifier only allowed for members of traits"); if (sym.info.symbol == FunctionClass(0) && diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index e88545992c..ea640cc661 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -175,7 +175,9 @@ abstract class RefChecks extends InfoTransform { } else if (!(other hasFlag DEFERRED) && !(member hasFlag (OVERRIDE | ABSOVERRIDE))) { // (1.3) overrideError("needs `override' modifier"); } else if ((other hasFlag ABSOVERRIDE) && other.isIncompleteIn(clazz) && !(member hasFlag ABSOVERRIDE)) { - overrideError("needs `abstract override' modifiers"); + overrideError("needs `abstract override' modifiers") + } else if ((member hasFlag (OVERRIDE | ABSOVERRIDE)) && (other hasFlag ACCESSOR) && other.accessed.isVariable) { + overrideError("cannot override a mutable variable") } else if (other.isStable) { if (!member.isStable) // (1.4) overrideError("needs to be an immutable value") @@ -558,7 +560,7 @@ abstract class RefChecks extends InfoTransform { case TypeTree() => new TypeTraverser { - def traverse(tp: Type) = tp match { + def traverse(tp: Type): TypeTraverser = tp match { case TypeRef(pre, sym, args) => checkBounds(sym.typeParams, args); this case _ => this } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 8b151063db..5a150c3dcd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -846,6 +846,19 @@ trait Typers requires Analyzer { copy.LabelDef(ldef, ldef.name, ldef.params, rhs1) setType restpe } + def anonymousClassRefinement(clazz: Symbol): Type = { + val tp = refinedType(clazz.info.parents, clazz.owner) + val thistp = tp.symbol.thisType + for (val sym <- clazz.info.decls.toList) { + if (!sym.hasFlag(PRIVATE) && !sym.isClass && !sym.isConstructor && + tp.nonPrivateMember(sym.name).filter(other => + !other.isTerm || (thistp.memberType(other) matches thistp.memberType(sym))) + != NoSymbol) + addMember(thistp, tp, sym) + } + tp + } + def typedBlock(block: Block, mode: int, pt: Type): Block = { namer.enterSyms(block.stats) block.stats foreach enterLabelDef @@ -854,9 +867,9 @@ trait Typers requires Analyzer { val block1 = copy.Block(block, stats1, expr1) .setType(if (treeInfo.isPureExpr(block)) expr1.tpe else expr1.tpe.deconst) if (isFullyDefined(pt)) block1 - else { //todo: correct? + else { if (block1.tpe.symbol.isAnonymousClass) - block1 setType intersectionType(block1.tpe.parents, block1.tpe.symbol.owner) + block1 setType anonymousClassRefinement(block1.tpe.symbol) checkNoEscaping.locals(context.scope, pt, block1) } } diff --git a/test/pending/pos/bug572.scala b/test/pending/pos/bug572.scala new file mode 100644 index 0000000000..3a69cde4a6 --- /dev/null +++ b/test/pending/pos/bug572.scala @@ -0,0 +1,33 @@ +package lampion.collections; + +object DirX { + abstract class Dir { + def reverse : Dir; + } + object BEFORE extends Dir { + def reverse = AFTER; + } + object AFTER extends Dir { + def reverse = BEFORE; + } +} +import DirX._; +abstract class Linked { + type Node <: Node0; + + abstract class Node0 { + var next : Node = _; + var prev : Node = _; + + def get(dir : Dir) = if (dir == BEFORE) prev; else next; + private def set(dir : Dir, node : Node) = + if (dir == BEFORE) prev = node; else next = node; + + def link(dir : Dir, node : Node) = { + assert(get(dir) == null); + assert(node.get(dir.reverse) == null); + set(dir, node); + node.set(dir.reverse(), node); + } + } +} diff --git a/test/pending/pos/bug573.scala b/test/pending/pos/bug573.scala new file mode 100644 index 0000000000..b1b4f75098 --- /dev/null +++ b/test/pending/pos/bug573.scala @@ -0,0 +1,43 @@ +package lampion.collections; + +object DirX { + abstract class Dir { + def reverse : Dir; + } + object BEFORE extends Dir { + def reverse = AFTER; + } + object AFTER extends Dir { + def reverse = BEFORE; + } +} + +import DirX._; + +abstract class Linked { + type Node <: Node0; + + abstract class Node0 { + var next : Node = _; + var prev : Node = _; + + def self : Node; + + def get(dir : Dir) = if (dir == BEFORE) prev; else next; + private def set(dir : Dir, node : Node) = + if (dir == BEFORE) prev = node; else next = node; + + def link(dir : Dir, node : Node) = { + assert(get(dir) == null); + assert(node.get(dir.reverse) == null); + set(dir, node); + node.set(dir.reverse, self); + } + + + def end(dir : Dir) : Node = { + if (get(dir) == null) this; + else get(dir).end(dir); + } + } +} diff --git a/test/pending/pos/foo.scala b/test/pending/pos/foo.scala new file mode 100755 index 0000000000..8b45addbd5 --- /dev/null +++ b/test/pending/pos/foo.scala @@ -0,0 +1,3 @@ +object foo { + var x: String +} diff --git a/test/pending/pos/gosh.scala b/test/pending/pos/gosh.scala new file mode 100755 index 0000000000..c4cd3df80b --- /dev/null +++ b/test/pending/pos/gosh.scala @@ -0,0 +1,44 @@ +object ShapeTest extends Application { + + class Point(x : int, y : int) { + override def toString() = "[" + x + "," + y + "]" + } + + abstract class Shape { + def draw() : unit + } + + class Line(s : Point, e : Point) extends Shape { + def draw() : unit = { Console.println("draw line " + s + "," + e) } + } + + abstract class Foo { + type T <: Object + + def show(o : T) : unit + def print() : unit = {Console.println("in Foo")} + } + + abstract class ShapeFoo extends Foo { + type T <: Shape + def show(o : T) : unit = { o.draw() } + override def print() : unit = {Console.println("in ShapeFoo")} + } + + class LineFoo extends ShapeFoo { + type T = Line + override def print() : unit = {Console.println("in LineFoo")} + } + + val p1 = new Point(1,4) + val p2 = new Point(12, 28) + + val l1 = new Line(p1, p2) + + + val l = new ShapeFoo{ // ** // + type T = Line // ** // + override def print() : unit = {Console.println("in LineFoo")} // ** // + } + l.show(l1) // ** // +} diff --git a/test/pending/pos/moors.scala b/test/pending/pos/moors.scala new file mode 100644 index 0000000000..4f7346f57f --- /dev/null +++ b/test/pending/pos/moors.scala @@ -0,0 +1,12 @@ +object Test { + + implicit def foo2bar(foo :Foo) :Bar = foo.bar + + class Foo(val bar :Bar) { + def testCoercion ={ val a: this.type = this; a.baz /* here, foo2bar is inferred by the compiler, as expected */} + def testCoercionThis = baz // --> error: not found: value baz + def testCoercionThis = (this: Foo).baz // --> error: value baz is not a member of Foo + } + + class Bar { def baz = System.out.println("baz")} +} diff --git a/test/pending/run/exc.scala b/test/pending/run/exc.scala new file mode 100755 index 0000000000..26f80412c0 --- /dev/null +++ b/test/pending/run/exc.scala @@ -0,0 +1,10 @@ +object exc1 extends Application { + def foo() = { + while (true) { + try { + } catch { + case ex: Exception => + } + } + } +} diff --git a/test/pending/run/exc1.scala b/test/pending/run/exc1.scala new file mode 100755 index 0000000000..48fc084dda --- /dev/null +++ b/test/pending/run/exc1.scala @@ -0,0 +1,10 @@ +object exc1 extends Application { + def foo(): unit = { + while (true) { + try { + } catch { + case ex: Exception => + } + } + } +} diff --git a/test/pending/run/exc2.scala b/test/pending/run/exc2.scala new file mode 100755 index 0000000000..8adf9b4a37 --- /dev/null +++ b/test/pending/run/exc2.scala @@ -0,0 +1,12 @@ +object exc2 extends Application { + def foo() = { + while (true) { + try { + Console.println("foo") + } catch { + case ex: Exception => + Console.println("bar") + } + } + } +} -- cgit v1.2.3