diff options
author | Martin Odersky <odersky@gmail.com> | 2013-12-16 16:08:26 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-12-16 16:09:25 +0100 |
commit | 58059264842fac39a27356d052680a09c2da7571 (patch) | |
tree | 5b3ef0642b19cfbbf7bf91ebc7ec016955fa50b7 | |
parent | 36476e46815370ca282cbb3179711125444319e9 (diff) | |
download | dotty-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.scala | 8 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Inferencing.scala | 23 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 31 | ||||
-rw-r--r-- | test/dotc/tests.scala | 3 | ||||
-rw-r--r-- | tests/pos/desugar.scala | 2 | ||||
-rw-r--r-- | tests/pos/functions1.scala | 48 | ||||
-rw-r--r-- | tests/pos/typers.scala | 2 |
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 } } |