aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala11
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala2
-rw-r--r--tests/neg/typers.scala62
-rw-r--r--tests/pos/typers.scala84
4 files changed, 92 insertions, 67 deletions
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index 287e93c7a..ae325af2a 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -102,13 +102,14 @@ trait Checking {
tp
}
- /** Check that class does not define */
+ /** Check that class does not define same symbol twice */
def checkNoDoubleDefs(cls: Symbol)(implicit ctx: Context): Unit = {
val seen = new mutable.HashMap[Name, List[Symbol]] {
override def default(key: Name) = Nil
}
typr.println(i"check no double defs $cls")
- for (decl <- cls.info.decls) {
+
+ def checkDecl(decl: Symbol): Unit = {
for (other <- seen(decl.name)) {
typr.println(i"conflict? $decl $other")
if (decl.signature matches other.signature) {
@@ -129,6 +130,12 @@ trait Checking {
}
seen(decl.name) = decl :: seen(decl.name)
}
+
+ cls.info.decls.foreach(checkDecl)
+ cls.info match {
+ case ClassInfo(_, _, _, _, selfSym: Symbol) => checkDecl(selfSym)
+ case _ =>
+ }
}
def checkInstantiatable(cls: ClassSymbol, pos: Position): Unit = {
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 2425bea50..cce2f7318 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -209,7 +209,7 @@ class Namer { typer: Typer =>
ctx.error(s"${preExisting.showLocated} is compiled twice, runid = ${ctx.runId}", tree.pos)
}
else if ((!ctx.owner.isClass || name.isTypeName) && preExisting.exists) {
- ctx.error(d"$name is already defined as $preExisting")
+ ctx.error(i"$name is already defined as $preExisting", tree.pos)
}
}
diff --git a/tests/neg/typers.scala b/tests/neg/typers.scala
index d25a8911e..2f1cf40c4 100644
--- a/tests/neg/typers.scala
+++ b/tests/neg/typers.scala
@@ -1,40 +1,56 @@
object typers {
-
+
+ class A(x: Int) {
+ val x: String = "a" // error: double def
+
+ { val y: String = ""
+ val y: Int = 0 // error: double def
+ y
+ }
+ }
+
+ class B { self => // error: double def
+ def self: Int = 0
+ def self(x: Int): Int = x
+ }
+
class C {
val x: Int
- val x: String
+ val x: String // error: double def
val y: Int
- def y: String
+ def y: String // error: double def
val z: Int
- def z(): String
-
- def f(x: Any) = ()
+ def z(): String // error: double def
+
+ def f(x: Any) = () // error: double def
def f(x: AnyRef): AnyRef
-
+
def g(x: Object): Unit
- def g[T](x: T): T = x
+ def g[T](x: T): T = x // error: double def
}
-
-
+
+
+
+
object returns {
-
- def foo(x: Int) = {
+
+ def foo(x: Int) = { // error: has return; needs result type
return 3
}
-
- return 4
+
+ return 4 // error: return outside method definition
}
-
+
object cyclic {
- def factorial(acc: Int, n: Int) =
+ def factorial(acc: Int, n: Int) =
if (n == 0) acc
- else factorial(acc * n, n - 1)
-
- def foo(x: Int) = x
+ else factorial(acc * n, n - 1) // error: cyclic reference
+
+ def foo(x: Int) = x // error: cyclic reference
def foo() = foo(1)
-
+
}
-
+
object tries {
val x = try {
@@ -46,6 +62,6 @@ object typers {
}
class Refinements {
- val y: C { val x: T; type T }
+ val y: C { val x: T; type T } // error: illegal forward reference in refinement
}
-} \ No newline at end of file
+}
diff --git a/tests/pos/typers.scala b/tests/pos/typers.scala
index cb3bbc590..4f012e7bf 100644
--- a/tests/pos/typers.scala
+++ b/tests/pos/typers.scala
@@ -1,61 +1,61 @@
-package test
+package test
import annotation.{tailrec, switch}
import collection.mutable._
object typers {
-
+
val names = List("a", "b", "c")
val ints = List(1, 2, 3)
-
+
object Inference {
for ((name, n) <- (names, ints).zipped)
println(name.length + n)
-
+
def double(x: Char): String = s"$x$x"
-
+
"abc" flatMap double
-
+
}
object Eta {
-
+
def fun(x: Int): Int = x + 1
val foo = fun(_)
}
-
+
case class DefaultParams(init: String => String = identity)
object DefaultParams {
def foo(x: String => String = identity) = x("abc")
-
+
foo()
}
-
+
class List[+T] {
def :: (x: T) = new :: (x, this)
-
+
def len: Int = this match {
case x :: xs1 => 1 + xs1.len
case Nil => 0
}
}
-
+
object Nil extends List[Nothing]
-
+
case class :: [+T] (hd: T, tl: List[T]) extends List[T]
-
+
def len[U](xs: List[U]): Int = xs match {
case x :: xs1 => 1 + len(xs1)
case Nil => 0
}
-
+
object returns {
-
+
def foo(x: Int): Int = {
return 3
}
}
-
+
object tries {
val x = try {
@@ -70,69 +70,71 @@ object typers {
val y = try 2 catch Predef.identity
val z = try 3 finally "abc"
-
+
println("abc".toString)
}
class C {
-
+
@tailrec def factorial(acc: Int, n: Int): Int = (n: @switch) match {
case 0 => acc
case _ => factorial(acc * n, n - 1)
}
-
+
println(factorial(1, 10))
-
-
+
+
}
-
+
class Refinements {
val y: C { type T; val key: T; def process(x: T): Int }
}
-
+
object Accessibility {
-
+
class A {
val x: String = "abc"
}
-
+
class B extends A {
private def x: Int = 1
}
-
+
val b: B = new B
val y = b.x
val z: String = y
-
+
}
-
+
object Self {
-
- class A(self: Int) { self =>
-
+
+ class A(self1: Int) { self =>
+
+ def self1(x: Int) = x
+
class B {
val b = self
val c: A = b
}
-
+
val a = self
val c: A = a
}
-
-
+
+
}
-
+
object Arrays {
-
+
val arr = List("a", "b", "c").toArray
val i = 2
arr(i).charAt(0)
-
+
val x = new ArrayBuffer[String] // testing overloaded polymorphic constructors
val entries = Array("abc", "def")
-
+
for ((x, i) <- entries.zipWithIndex)
println(x)
}
@@ -145,6 +147,6 @@ object typers {
}
val yy: String = y
}
-
-} \ No newline at end of file
+
+}