From 00afa24fb6f2621e02e6ecd8ef86db56dd3913b5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 8 May 2006 16:34:57 +0000 Subject: Bug fixes --- src/compiler/scala/tools/nsc/Global.scala | 5 +++ src/compiler/scala/tools/nsc/Main.scala | 2 +- src/compiler/scala/tools/nsc/symtab/StdNames.scala | 1 + src/compiler/scala/tools/nsc/symtab/Types.scala | 23 +++++++++++--- .../scala/tools/nsc/transform/Erasure.scala | 4 ++- .../tools/nsc/typechecker/SyntheticMethods.scala | 17 +++++++++- test/files/neg/bug391.check | 16 ++++++++++ test/files/neg/bug391.scala | 6 ++++ test/files/neg/bug588.check | 13 ++++++++ test/files/neg/bug588.scala | 15 +++++++++ test/files/pos/bug422.scala | 17 ++++++++++ test/files/run/bug428.check | 8 +++++ test/files/run/bug428.scala | 37 ++++++++++++++++++++++ test/pending/neg/bug421.scala | 9 ++++++ test/pending/run/bug551.scala | 5 +++ 15 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 test/files/neg/bug391.check create mode 100644 test/files/neg/bug391.scala create mode 100644 test/files/neg/bug588.check create mode 100755 test/files/neg/bug588.scala create mode 100644 test/files/pos/bug422.scala create mode 100644 test/files/run/bug428.check create mode 100644 test/files/run/bug428.scala create mode 100644 test/pending/neg/bug421.scala create mode 100755 test/pending/run/bug551.scala diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 4fd5404a91..da135674a1 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -343,6 +343,11 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable genJVM, sampleTransform); + protected def insertBefore(c: SubComponent, cs: List[SubComponent], before: SubComponent): List[SubComponent] = cs match { + case List() => List(c) + case c1 :: cs1 => if (c1 == before) c :: cs else c1 :: insertBefore(c, cs1, before) + } + private var curRun: Run = NoRun; override def currentRun: Run = curRun; diff --git a/src/compiler/scala/tools/nsc/Main.scala b/src/compiler/scala/tools/nsc/Main.scala index ff23178c4a..41345083e1 100644 --- a/src/compiler/scala/tools/nsc/Main.scala +++ b/src/compiler/scala/tools/nsc/Main.scala @@ -24,7 +24,7 @@ object Main extends Object with EvalLoop { val versionMsg = PRODUCT + " " + VERSION + " -- " + COPYRIGHT val prompt = "\nnsc> " - private var reporter: ConsoleReporter = _ + var reporter: ConsoleReporter = _ def error(msg: String): unit = reporter.error(new Position(PRODUCT), diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala index e841813272..1d64005f58 100644 --- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala +++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala @@ -234,6 +234,7 @@ trait StdNames requires SymbolTable { val elements = newTermName("elements"); val eq = newTermName("eq"); val equals_ = newTermName("equals"); + val _equals = newTermName("_equals"); val ex = newTermName("ex"); val fail = newTermName("fail"); val false_ = newTermName("false"); diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 2702a42057..0b3c16e56d 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -979,6 +979,15 @@ trait Types requires SymbolTable { } else sym } + /** Convert a `super' prefix to a this-type if `sym' is abstract or final */ + private def removeSuper(tp: Type, sym: Symbol): Type = tp match { + case SuperType(thistp, _) => + if (sym.isFinal || sym.hasFlag(DEFERRED)) thistp + else tp + case _ => + tp + } + /** The canonical creator for this-types */ def ThisType(sym: Symbol): Type = if (phase.erasedTypes) sym.tpe else unique(new ThisType(sym) with UniqueType); @@ -989,8 +998,12 @@ trait Types requires SymbolTable { sym.tpe.resultType else if (checkMalformedSwitch && !pre.isStable && !pre.isError) throw new MalformedType(pre, sym.name.toString()) - else - unique(new SingleType(pre, rebind(pre, sym)) with UniqueType) + else { + var sym1 = rebind(pre, sym) + val pre1 = removeSuper(pre, sym1) + if (pre1 ne pre) sym1 = rebind(pre1, sym1) + unique(new SingleType(pre1, sym1) with UniqueType) + } } /** The canonical creator for super-types */ @@ -1024,7 +1037,7 @@ trait Types requires SymbolTable { /** The canonical creator for typerefs */ def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type = { - val sym1 = if (sym.isAbstractType) rebind(pre, sym) else sym; + var sym1 = if (sym.isAbstractType) rebind(pre, sym) else sym; if (checkMalformedSwitch && sym1.isAbstractType && !pre.isStable && !pre.isError) throw new MalformedType(pre, sym.nameString); // if (sym1.hasFlag(LOCKED)) @@ -1039,7 +1052,9 @@ trait Types requires SymbolTable { sym1.resetFlag(LOCKED); result } else { - rawTypeRef(pre, sym1, args) + val pre1 = removeSuper(pre, sym1) + if ((pre1 ne pre) && sym1.isAbstractType) sym1 = rebind(pre1, sym1) + rawTypeRef(pre1, sym1, args) } } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 13d39c70e5..bb8ebb8cd4 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -392,7 +392,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { * but their erased types are the same. */ private def checkNoDoubleDefs(root: Symbol): unit = { - def doubleDefError(sym1: Symbol, sym2: Symbol) = { + def doubleDefError(sym1: Symbol, sym2: Symbol): unit = { val tpe1 = atPhase(currentRun.refchecksPhase.next)(root.thisType.memberType(sym1)); val tpe2 = atPhase(currentRun.refchecksPhase.next)(root.thisType.memberType(sym2)); unit.error( @@ -406,8 +406,10 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { (if (sym2.owner == root) " at line " + Position.line(unit.source, sym2.pos) else sym2.locationString) + "\nhave same type" + (if (tpe1 =:= tpe2) "" else " after erasure: " + atPhase(phase.next)(sym1.tpe))) + sym2.setInfo(ErrorType) } + val decls = root.info.decls; var e = decls.elems; while (e != null) { diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 6b11c5818f..7f06291c7c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -86,6 +86,21 @@ trait SyntheticMethods requires Analyzer { Apply(gen.mkAttributedRef(target), This(clazz) :: (vparamss.head map Ident)))); } + def equalsMethod: Tree = { + val target = getMember(ScalaRunTimeModule, nme._equals); + val method = syntheticMethod( + nme.equals_, 0, MethodType(target.tpe.paramTypes.tail, target.tpe.resultType)); + typed(DefDef(method, vparamss => + Apply( + Select( + TypeApply( + Select(Ident(vparamss.head.head), Any_isInstanceOf), + List(TypeTree(clazz.tpe))), + Boolean_and), + List( + Apply(gen.mkAttributedRef(target), This(clazz) :: (vparamss.head map Ident)))))); + } + def isSerializable(clazz: Symbol): Boolean = !clazz.getAttributes(definitions.SerializableAttr).isEmpty @@ -169,7 +184,7 @@ trait SyntheticMethods requires Analyzer { } else { if (!hasImplementation(nme.hashCode_)) ts += forwardingMethod(nme.hashCode_); if (!hasImplementation(nme.toString_)) ts += forwardingMethod(nme.toString_); - if (!hasImplementation(nme.equals_)) ts += forwardingMethod(nme.equals_); + if (!hasImplementation(nme.equals_)) ts += equalsMethod //forwardingMethod(nme.equals_); } if (!hasImplementation(nme.caseElement)) ts += caseElementMethod; if (!hasImplementation(nme.caseArity)) ts += caseArityMethod; diff --git a/test/files/neg/bug391.check b/test/files/neg/bug391.check new file mode 100644 index 0000000000..57b3f5d565 --- /dev/null +++ b/test/files/neg/bug391.check @@ -0,0 +1,16 @@ +bug391.scala:2 error: identifier expected but 'def' found. + def fun1(def x: Int): Int = x; // the "def x" is illegal + ^ +bug391.scala:3 error: ':' expected but '}' found. + def fun2(val x: Int): Int = x; // the "val x" is illegal + ^ +bug391.scala:4 error: illegal start of simple expression +} +^ +bug391.scala:6 error: identifier expected but 'def' found. +class E(def x: Int); // the "def x" is illegal + ^ +bug391.scala:6 error: ':' expected but eof found. +class E(def x: Int); // the "def x" is illegal + ^ +5 errors found diff --git a/test/files/neg/bug391.scala b/test/files/neg/bug391.scala new file mode 100644 index 0000000000..08c083baa5 --- /dev/null +++ b/test/files/neg/bug391.scala @@ -0,0 +1,6 @@ +trait C { + def fun1(def x: Int): Int = x; // the "def x" is illegal + def fun2(val x: Int): Int = x; // the "val x" is illegal +} + +class E(def x: Int); // the "def x" is illegal diff --git a/test/files/neg/bug588.check b/test/files/neg/bug588.check new file mode 100644 index 0000000000..02a9b9c482 --- /dev/null +++ b/test/files/neg/bug588.check @@ -0,0 +1,13 @@ +/home/odersky/scala/test/files/pos/bug588.scala:3 error: double definition: +method visit:((scala.Int) => java.lang.String)scala.Boolean and +method visit:((scala.Int) => scala.Unit)scala.Boolean at line 2 +have same type after erasure: (scala.Function1)scala.Boolean + def visit(f: int => String): boolean + ^ +/home/odersky/scala/test/files/pos/bug588.scala:10 error: double definition: +method f:(Test.this.TypeB)scala.Unit and +method f:(Test.this.TypeA)scala.Unit at line 9 +have same type after erasure: (Test#TraitA)scala.Unit + def f(brac : TypeB) : Unit; + ^ +two errors found diff --git a/test/files/neg/bug588.scala b/test/files/neg/bug588.scala new file mode 100755 index 0000000000..bbb79ed79e --- /dev/null +++ b/test/files/neg/bug588.scala @@ -0,0 +1,15 @@ +abstract class Test0 { + def visit(f: int => unit): boolean + def visit(f: int => String): boolean +} +trait Test { + type TypeA <: TraitA; + type TypeB <: TypeA with TraitB; + + def f(node : TypeA) : Unit; + def f(brac : TypeB) : Unit; + + trait TraitA; + trait TraitB; + +} diff --git a/test/files/pos/bug422.scala b/test/files/pos/bug422.scala new file mode 100644 index 0000000000..cb3ba279d4 --- /dev/null +++ b/test/files/pos/bug422.scala @@ -0,0 +1,17 @@ +import scala.util.regexp.WordExp; +import scala.util.automata.WordBerrySethi; + +object BoolWordExp extends WordExp { + type _labelT = MyLabels; + type _regexpT = RegExp; + abstract class MyLabels extends Label ; + case class MyLabel(c:Char) extends MyLabels; +} + +object MyTranslator extends WordBerrySethi { + override val lang = BoolWordExp; + import lang._; + override protected def seenLabel( r:RegExp, i:Int, label: _labelT ): Unit = { + super.seenLabel(r,i,label) + } +} diff --git a/test/files/run/bug428.check b/test/files/run/bug428.check new file mode 100644 index 0000000000..21bef2f8d3 --- /dev/null +++ b/test/files/run/bug428.check @@ -0,0 +1,8 @@ +Foo 1: a = 0, b = 0, x = 0, y = 0 +Foo 2: a = 2, b = 0, x = 0, y = 0 +Foo 3: a = 2, b = 3, x = 0, y = 0 +Foo 4: a = 2, b = 3, x = 0, y = 0 +Foo 5: a = 2, b = 3, x = 0, y = 0 +Bar 1: a = 2, b = 3, x = 0, y = 0 +Bar 2: a = 2, b = 3, x = 5, y = 0 +Bar 3: a = 2, b = 3, x = 5, y = 7 diff --git a/test/files/run/bug428.scala b/test/files/run/bug428.scala new file mode 100644 index 0000000000..34d99efd1f --- /dev/null +++ b/test/files/run/bug428.scala @@ -0,0 +1,37 @@ +object Test { + + abstract class Foo(_a: Int, _b: Int) { + + Console.println("Foo 1: " + this); + val a: Int = _a; + Console.println("Foo 2: " + this); + val b: Int = { fun(); _b } + Console.println("Foo 3: " + this); + val x: Int; + Console.println("Foo 4: " + this); + val y: Int; + Console.println("Foo 5: " + this); + + + def fun(): Unit = (); + + override def toString(): String = + "a = " + a + ", b = " + b + ", x = " + x + ", y = " + y; + + } + + class Bar(_a: Int, _b: Int, _x: Int, _y: Int) extends Foo(_a, _b) { + + Console.println("Bar 1: " + this); + val x: Int = _x; + Console.println("Bar 2: " + this); + val y: Int = { fun(); _y } + Console.println("Bar 3: " + this); + + } + + def main (args: Array[String]): Unit = { + new Bar(2,3,5,7); + } + +} diff --git a/test/pending/neg/bug421.scala b/test/pending/neg/bug421.scala new file mode 100644 index 0000000000..bf7346f01a --- /dev/null +++ b/test/pending/neg/bug421.scala @@ -0,0 +1,9 @@ +object foo { + case class Bar(a:String, b:Object, c:String*); + + + Bar("foo","meets","bar") match { + case Bar("foo",_*) => error("huh?"); + } + +} diff --git a/test/pending/run/bug551.scala b/test/pending/run/bug551.scala new file mode 100755 index 0000000000..ffa36d7cb0 --- /dev/null +++ b/test/pending/run/bug551.scala @@ -0,0 +1,5 @@ +case class A(x: int) +class B(x: int) extends A(x) +object Test extends Application { + Console.println(A(1) == new B(1)) +} -- cgit v1.2.3