aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-12-16 16:08:26 +0100
committerMartin Odersky <odersky@gmail.com>2013-12-16 16:09:25 +0100
commit58059264842fac39a27356d052680a09c2da7571 (patch)
tree5b3ef0642b19cfbbf7bf91ebc7ec016955fa50b7
parent36476e46815370ca282cbb3179711125444319e9 (diff)
downloaddotty-58059264842fac39a27356d052680a09c2da7571.tar.gz
dotty-58059264842fac39a27356d052680a09c2da7571.tar.bz2
dotty-58059264842fac39a27356d052680a09c2da7571.zip
Checking for double definitions among class definitions.
Also fixes to typedReturn. Adapted tests accordingly.
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala8
-rw-r--r--src/dotty/tools/dotc/core/Types.scala1
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala23
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala31
-rw-r--r--test/dotc/tests.scala3
-rw-r--r--tests/pos/desugar.scala2
-rw-r--r--tests/pos/functions1.scala48
-rw-r--r--tests/pos/typers.scala2
8 files changed, 73 insertions, 45 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index c0b805eeb..f21075f11 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -359,7 +359,13 @@ object Denotations {
final def signature(implicit ctx: Context): Signature = {
if (isType) Signature.NotAMethod // don't force info if this is a type SymDenotation
else info match {
- case info: SignedType => info.signature
+ case info: SignedType =>
+ try info.signature
+ catch { // !!! DEBUG
+ case ex: MatchError =>
+ println(s"cannot take signature of ${info.show}")
+ throw ex
+ }
case _ => Signature.NotAMethod
}
}
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 22d84c4e1..a617f86d2 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1434,6 +1434,7 @@ object Types {
extends CachedGroundType with BindingType with TermType with SignedType { thisMethodType =>
override val resultType = resultTypeExp(this)
+ assert(resultType != NoType, this)
def isJava = false
def isImplicit = false
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index cb22e8e88..4d418fe97 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -12,7 +12,7 @@ import util.Positions._
import util.{Stats, SimpleMap}
import Decorators._
import ErrorReporting.{errorType, InfoString}
-import collection.mutable.ListBuffer
+import collection.mutable
object Inferencing {
@@ -249,6 +249,27 @@ object Inferencing {
defn.ObjectClass
}
+ /** Check that class does not define */
+ def checkNoDoubleDefs(cls: Symbol)(implicit ctx: Context): Unit = {
+ val seen = new mutable.HashMap[Name, List[Symbol]] {
+ override def default(key: Name) = Nil
+ }
+ println(i"cndd $cls")
+ for (decl <- cls.info.decls) {
+ for (other <- seen(decl.name)) {
+ println(i"conflict? $decl $other")
+ if (decl.signature matches other.signature) {
+ val ofType = if (decl.isType) "" else i": ${other.info}"
+ val explanation =
+ if (!decl.isSourceMethod) ""
+ else "\n (both definitions have the same erased type signature)"
+ ctx.error(i"$decl is already defined as $other$ofType$explanation", decl.pos)
+ }
+ }
+ seen(decl.name) = decl :: seen(decl.name)
+ }
+ }
+
def checkInstantiatable(cls: ClassSymbol, pos: Position): Unit = {
??? // to be done in later phase: check that class `cls` is legal in a new.
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 4e9d5953a..20f9aeb19 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -611,26 +611,21 @@ class Typer extends Namer with Applications with Implicits {
}
def typedReturn(tree: untpd.Return)(implicit ctx: Context): Return = track("typedReturn") {
- def enclMethInfo(cx: Context): (Tree, Type) =
- if (cx == NoContext || cx.owner.isType) {
- ctx.error("return outside method definition")
+ def enclMethInfo(cx: Context): (Tree, Type) = {
+ val owner = cx.owner
+ if (cx == NoContext || owner.isType) {
+ ctx.error("return outside method definition", tree.pos)
(EmptyTree, WildcardType)
}
- else cx.tree match {
- case ddef: DefDef =>
- val meth = cx.owner
- val from = Ident(TermRef(NoPrefix, meth.asTerm))
- val proto =
- if (meth.isConstructor)
- defn.UnitType
- else if (ddef.tpt.isEmpty)
- errorType(i"method ${meth.name} has return statement; needs result type", tree.pos)
- else
- ddef.tpt.tpe
+ else if (owner.isSourceMethod)
+ if (owner.isCompleted) {
+ val from = Ident(TermRef(NoPrefix, owner.asTerm))
+ val proto = if (owner.isConstructor) defn.UnitType else owner.info.finalResultType
(from, proto)
- case _ =>
- enclMethInfo(cx.outer)
- }
+ }
+ else (EmptyTree, errorType(i"$owner has return statement; needs result type", tree.pos))
+ else enclMethInfo(cx.outer)
+ }
val (from, proto) = enclMethInfo(ctx)
val expr1 = typedExpr(tree.expr orElse untpd.unitLiteral, proto)
cpy.Return(tree, expr1, from) withType defn.NothingType
@@ -786,9 +781,9 @@ class Typer extends Namer with Applications with Implicits {
val self1 = typed(self).asInstanceOf[ValDef]
val localDummy = ctx.newLocalDummy(cls, impl.pos)
val body1 = typedStats(body, localDummy)(inClassContext(self1.symbol))
+ checkNoDoubleDefs(cls)
val impl1 = cpy.Template(impl, constr1, parents1, self1, body1)
.withType(localDummy.termRef)
-
cpy.TypeDef(cdef, mods1, name, impl1).withType(cls.typeRef)
// todo later: check that
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index acaa58068..0d7d84457 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -33,5 +33,6 @@ class tests extends CompilerTest {
@Test def neg_blockescapes() = compileFile(negDir, "blockescapesNeg", xerrors = 2)
@Test def neg_typedapply() = compileFile(negDir, "typedapply", xerrors = 4)
@Test def neg_typedidents() = compileFile(negDir, "typedidents", xerrors = 2)
- @Test def nef_assignments() = compileFile(negDir, "assignments", xerrors = 3)
+ @Test def neg_assignments() = compileFile(negDir, "assignments", xerrors = 3)
+ @Test def neg_typers() = compileFile(negDir, "typers", xerrors = 7)
} \ No newline at end of file
diff --git a/tests/pos/desugar.scala b/tests/pos/desugar.scala
index cfd695af6..f0d8645b7 100644
--- a/tests/pos/desugar.scala
+++ b/tests/pos/desugar.scala
@@ -38,7 +38,7 @@ object desugar {
val (cons: Cons[Int]) = xs
- val x, y, z: Int = 1
+ val x1, y1, z1: Int = 1
}
object Binops {
diff --git a/tests/pos/functions1.scala b/tests/pos/functions1.scala
index 52ea3c3f9..93f4fc7b6 100644
--- a/tests/pos/functions1.scala
+++ b/tests/pos/functions1.scala
@@ -4,29 +4,33 @@ class X(val elem: Int) extends Object {
object Functions {
- val x = new X(2)
- val xe = x.elem
- val xf: String => Int = x.foo(_: String)
- val xf2: String => Int = x.foo(_)
- val x2: String => Int = x.foo
- val x3 = x.foo _
-
- abstract class Spore[T, U] {
- def run(x: T): U
- }
-
- trait Spore2[T, U] { self: Spore2[T, U] =>
- def run(x: T): U
+ object simple {
+ val x = new X(2)
+ val xe = x.elem
+ val xf: String => Int = x.foo(_: String)
+ val xf2: String => Int = x.foo(_)
+ val x2: String => Int = x.foo
+ val x3 = x.foo _
}
- val x: String => String = {
- case "abc" => ""
- case x => x
- }
- val y: PartialFunction[String, String] = x => x match {
- case "abc" => ""
- case _ => x
+ object sams {
+ abstract class Spore[T, U] {
+ def run(x: T): U
+ }
+
+ trait Spore2[T, U] { self: Spore2[T, U] =>
+ def run(x: T): U
+ }
+
+ val x: String => String = {
+ case "abc" => ""
+ case x => x
+ }
+ val y: PartialFunction[String, String] = x => x match {
+ case "abc" => ""
+ case _ => x
+ }
+ val z: Spore[String, String] = x => x + x
+ val z2: Spore2[String, String] = x => x + x
}
- val z: Spore[String, String] = x => x + x
- val z2: Spore2[String, String] = x => x + x
}
diff --git a/tests/pos/typers.scala b/tests/pos/typers.scala
index 51692e026..900baef75 100644
--- a/tests/pos/typers.scala
+++ b/tests/pos/typers.scala
@@ -43,8 +43,8 @@ object typers {
}
class C {
-
}
+
class Refinements {
val y: C { type T; val key: T; def process(x: T): Int }
}