diff options
author | Martin Odersky <odersky@gmail.com> | 2014-08-13 11:31:39 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-08-13 12:05:05 +0200 |
commit | 34f73ded3519a1df7d278685f3f33facd00f1c58 (patch) | |
tree | 3cf71a8baea0de46c9ca126a1ea2dbd6ea55c731 | |
parent | 3558e07b8f3a604bfd67c721cdec3eb9db29e7eb (diff) | |
download | dotty-34f73ded3519a1df7d278685f3f33facd00f1c58.tar.gz dotty-34f73ded3519a1df7d278685f3f33facd00f1c58.tar.bz2 dotty-34f73ded3519a1df7d278685f3f33facd00f1c58.zip |
Fix and enable RefChecks
RefChecks is now enabled. Some of the tests had to be fixed to be refchecks-correct.
-rw-r--r-- | src/dotty/tools/dotc/Compiler.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/RefChecks.scala | 35 | ||||
-rw-r--r-- | test/dotc/tests.scala | 2 | ||||
-rw-r--r-- | tests/pos/desugar.scala | 37 | ||||
-rw-r--r-- | tests/pos/hk.scala | 6 | ||||
-rw-r--r-- | tests/pos/inferred.scala | 26 | ||||
-rw-r--r-- | tests/pos/opassign.scala | 18 | ||||
-rw-r--r-- | tests/pos/t1832.scala | 2 | ||||
-rw-r--r-- | tests/pos/tycons.scala | 4 | ||||
-rw-r--r-- | tests/pos/typers.scala | 2 |
10 files changed, 76 insertions, 58 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index 13fcc8a70..09e58d186 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -22,7 +22,7 @@ class Compiler { List(new FirstTransform, new SyntheticMethods), List(new SuperAccessors), // pickling goes here - List(/*new RefChecks, */new ElimRepeated, new ElimLocals), + List(new RefChecks, new ElimRepeated, new ElimLocals), List(new ExtensionMethods), List(new TailRec), List(new PatternMatcher, diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala index 85e4696ef..67cb1745f 100644 --- a/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/src/dotty/tools/dotc/typer/RefChecks.scala @@ -102,6 +102,8 @@ object RefChecks { * 4. Check that every member with an `override` modifier * overrides some other member. * TODO check that classes are not overridden + * TODO This still needs to be cleaned up; the current version is a staright port of what was there + * before, but it looks too complicated and method bodies are far too large. */ private def checkAllOverrides(clazz: Symbol)(implicit ctx: Context): Unit = { val self = clazz.thisType @@ -116,11 +118,15 @@ object RefChecks { case List(MixinOverrideError(_, msg)) => ctx.error(msg, clazz.pos) case MixinOverrideError(member, msg) :: others => - val others1 = others.map(_.member.name.decode).filter(member.name.decode != _).distinct - ctx.error( - msg + (if (others1.isEmpty) "" - else ";\n other members with override errors are: " + (others1 mkString ", ")), - clazz.pos) + val others1 = others.map(_.member).filter(_.name != member.name).distinct + def othersMsg = { + val others1 = others.map(_.member) + .filter(_.name != member.name) + .map(_.show).distinct + if (others1.isEmpty) "" + else i";\n other members with override errors are:: $others1%, %" + } + ctx.error(msg + othersMsg, clazz.pos) } } @@ -129,9 +135,9 @@ object RefChecks { def infoString0(sym: Symbol, showLocation: Boolean) = { val sym1 = sym.underlyingSymbol - if (showLocation) sym1.show + if (showLocation) sym1.showLocated else - sym1.showLocated + + sym1.show + (if (sym1.isAliasType) ", which equals " + self.memberInfo(sym1) else if (sym1.isAbstractType) " with bounds" + self.memberInfo(sym1) else if (sym1.is(Module)) "" @@ -182,6 +188,8 @@ object RefChecks { } def overrideAccessError() = { + ctx.log(i"member: ${member.showLocated} ${member.flags}") // DEBUG + ctx.log(i"other: ${other.showLocated} ${other.flags}") // DEBUG val otherAccess = (other.flags & AccessFlags).toString overrideError("has weaker access privileges; it should be " + (if (otherAccess == "") "public" else "at least " + otherAccess)) @@ -331,7 +339,7 @@ object RefChecks { // 2. Check that only abstract classes have deferred members def checkNoAbstractMembers(): Unit = { // Avoid spurious duplicates: first gather any missing members. - val missing = clazz.info.abstractTermMembers.filterNot(ignoreDeferred) + val missing = clazz.thisType.abstractTermMembers.filterNot(ignoreDeferred) // Group missing members by the name of the underlying symbol, // to consolidate getters and setters. val grouped: Map[Name, Seq[SingleDenotation]] = missing groupBy (_.symbol.underlyingSymbol.name) @@ -464,6 +472,9 @@ object RefChecks { if (decl.is(Deferred) && !ignoreDeferred(decl)) { val impl = decl.matchingMember(clazz.thisType) if (impl == NoSymbol || (decl.owner isSubClass impl.owner)) { + val impl1 = clazz.thisType.nonPrivateMember(decl.name) // DEBUG + ctx.log(i"${impl1}: ${impl1.info}") // DEBUG + ctx.log(i"${clazz.thisType.memberInfo(decl)}") // DEBUG abstractClassError(false, "there is a deferred declaration of " + infoString(decl) + " which is not implemented in a subclass" + err.abstractVarMessage(decl)) } @@ -499,7 +510,7 @@ object RefChecks { def hasMatchingSym(inclazz: Symbol, member: Symbol): Boolean = { def isSignatureMatch(sym: Symbol) = !sym.isTerm || - clazz.thisType.memberInfo(sym).matches(member.info) + clazz.thisType.memberInfo(sym).matchesLoosely(member.info) /* The rules for accessing members which have an access boundary are more * restrictive in java than scala. Since java has no concept of package nesting, @@ -626,7 +637,11 @@ object RefChecks { override val levelAndIndex: LevelAndIndex = ((outerLevelAndIndex, 0) /: stats) {(mi, stat) => val (m, idx) = mi - (if (stat.symbol.exists) m.updated(stat.symbol, (this, idx)) else m, idx + 1) + val m1 = stat match { + case stat: MemberDef => m.updated(stat.symbol, (this, idx)) + case _ => m + } + (m1, idx + 1) }._1 var maxIndex: Int = Int.MinValue var refPos: Position = _ diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 6035b661a..12a2a8cb8 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -14,7 +14,7 @@ class tests extends CompilerTest { "-pagewidth", "160") implicit val defaultOptions = noCheckOptions ++ List( - "-Ycheck:synthetic,tailrec" + "-Ycheck:refchecks,tailrec" ) val twice = List("#runs", "2", "-YnoDoubleBindings") diff --git a/tests/pos/desugar.scala b/tests/pos/desugar.scala index f0d8645b7..0d3b6d8ca 100644 --- a/tests/pos/desugar.scala +++ b/tests/pos/desugar.scala @@ -6,11 +6,11 @@ object desugar { val list = List(1, 2, 3) { var z: Int = y } - + def foo0(first: Int, second: Int = 2, third: Int = 3) = first + second def foo1(first: Int, second: Int = 2)(third: Int = 3) = first + second def foo2(first: Int)(second: Int = 2)(third: Int = 3) = first + second - + object caseClasses { self => trait List[+T] { def head: T @@ -23,34 +23,37 @@ object desugar { def apply[T](head: T): Cons[T] = apply(head, Nil) } - case object Nil extends List[Nothing] + case object Nil extends List[Nothing] { + def head = throw new Error() + def tail = throw new Error() + } } - + object patDefs { - + import caseClasses._ val xs: List[Int] = Cons(1, Cons(2, Nil)) - - val Cons(y, ys) = xs + + val Cons(y, ys) = xs val Cons(z, _) = xs val Cons(_, _) = xs - + val (cons: Cons[Int]) = xs - + val x1, y1, z1: Int = 1 } - + object Binops { - + x :: y :: Nil - + val x :: y :: Nil = list - + } - + object fors { - + for (x <- List(1, 2, 3)) yield 2 for (x <- List(1, 2, 3) if x % 2 == 0) yield x * x for (x <- List(1, 2, 3); y <- 0 to x) yield x * y @@ -65,7 +68,7 @@ object desugar { for (x <- List(1, 2, 3); y = x * x; if x + y % 2 == 0) println(x * y) for (x <- List(1, 2, 3); y = x * x; z = x * y; u <- 0 to y) println(x * y * z * u) } - + object misc { 'hello s"this is a $x + ${x + y} string" @@ -82,4 +85,4 @@ object desugar { do x -= 1 while (x > 0) } -}
\ No newline at end of file +} diff --git a/tests/pos/hk.scala b/tests/pos/hk.scala index 461c6e386..9fdaf94f6 100644 --- a/tests/pos/hk.scala +++ b/tests/pos/hk.scala @@ -2,7 +2,7 @@ import language.higherKinds object hk0 { - class Base { + abstract class Base { type Rep[T] val strRep: Rep[String] } @@ -13,7 +13,7 @@ object hk0 { val sr: Rep[String] = "" } - class Functor[F[_]] { + abstract class Functor[F[_]] { def map[A, B](f: A => B): F[A] => F[B] } val ml: Functor[List] = ??? @@ -53,4 +53,4 @@ object higherKinded { tree1: Tree[String] } -}
\ No newline at end of file +} diff --git a/tests/pos/inferred.scala b/tests/pos/inferred.scala index 525848541..87bbd9473 100644 --- a/tests/pos/inferred.scala +++ b/tests/pos/inferred.scala @@ -1,13 +1,13 @@ -class LIST[+T] { - +abstract class LIST[+T] { + def isEmpty: Boolean def head: T def tail: LIST[T] - + def prepend [U >: T] (x: U): LIST[U] = new CONS(x, this) - + def map[U](f: T => U): LIST[U] = if (isEmpty) NIL else tail.map(f).prepend(f(head)) - + } object NIL extends LIST[Nothing] { @@ -37,22 +37,22 @@ object Inferred { val nn = bar(NIL) val ints: LIST[Int] = NIL prepend 1 - + val ints1 = NIL prepend 1 prepend 2 val a = if (1 == 0) NIL else ints - + val n2 = scala.collection.immutable.Nil - + val ss2: scala.collection.immutable.List[String] = "abc" :: n2 - + val ss3 = "abc" :: n2 - + def cl = ((x: Int) => x + 1) - + val ints2 = ints map (_ + 1) - + val ints3 = new CONS[Int](1, NIL) - + val ints4 = new CONS(1, NIL) }
\ No newline at end of file diff --git a/tests/pos/opassign.scala b/tests/pos/opassign.scala index 7b8fec652..8f6cad903 100644 --- a/tests/pos/opassign.scala +++ b/tests/pos/opassign.scala @@ -1,28 +1,28 @@ object opassign { - + var count: Int = 0 def next = { count += 1; count } - + var x: Int = 0 x += 1 - + { var x: Int = 0 x += 1 } - + class Ref { - var x: Int + var x: Int = _ } val r = new Ref r.x += 1 - + val arr = new Array[Int](10) arr(0) += 1 - + def f(x: Int): Ref = new Ref f(next).x += 1 - + val buf = new collection.mutable.ListBuffer[Int] buf += 1 -}
\ No newline at end of file +} diff --git a/tests/pos/t1832.scala b/tests/pos/t1832.scala index 9ad9703c2..c34fe4bfa 100644 --- a/tests/pos/t1832.scala +++ b/tests/pos/t1832.scala @@ -2,7 +2,7 @@ trait Cloning { trait Foo def fn(g: Any => Unit): Foo - class Star { def *(a: Cloning.this.Foo): Cloning.this.Foo } + abstract class Star { def *(a: Cloning.this.Foo): Cloning.this.Foo } implicit def mkStar(i: Int): Star = new Star { def *(a: Foo): Foo = null } diff --git a/tests/pos/tycons.scala b/tests/pos/tycons.scala index f138c78be..ef16a7792 100644 --- a/tests/pos/tycons.scala +++ b/tests/pos/tycons.scala @@ -12,11 +12,11 @@ object obj extends List[Number] with Set[Exception] { val e: Exception = x } -class Functor[F <: TypeConstructor] { +abstract class Functor[F <: TypeConstructor] { def map[A, B](f: F { type TypeArg <: A }): F { type TypeArg <: B } } implicit object ListFunctor extends Functor[List] { - def map[A, B](f: List[A]): List[B] = ??? + override def map[A, B](f: List { type TypeArg <: A }): List { type TypeArg <: B } = ??? } diff --git a/tests/pos/typers.scala b/tests/pos/typers.scala index b2d786c1c..fe11ca602 100644 --- a/tests/pos/typers.scala +++ b/tests/pos/typers.scala @@ -88,7 +88,7 @@ object typers { } class Refinements { - val y: C { type T; val key: T; def process(x: T): Int } + val y: C { type T; val key: T; def process(x: T): Int } = ??? } object Accessibility { |