aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-08-13 11:31:39 +0200
committerMartin Odersky <odersky@gmail.com>2014-08-13 12:05:05 +0200
commit34f73ded3519a1df7d278685f3f33facd00f1c58 (patch)
tree3cf71a8baea0de46c9ca126a1ea2dbd6ea55c731
parent3558e07b8f3a604bfd67c721cdec3eb9db29e7eb (diff)
downloaddotty-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.scala2
-rw-r--r--src/dotty/tools/dotc/typer/RefChecks.scala35
-rw-r--r--test/dotc/tests.scala2
-rw-r--r--tests/pos/desugar.scala37
-rw-r--r--tests/pos/hk.scala6
-rw-r--r--tests/pos/inferred.scala26
-rw-r--r--tests/pos/opassign.scala18
-rw-r--r--tests/pos/t1832.scala2
-rw-r--r--tests/pos/tycons.scala4
-rw-r--r--tests/pos/typers.scala2
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 {