aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala14
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala3
-rw-r--r--test/dotc/tests.scala1
-rw-r--r--tests/neg/traitParamsTyper.scala16
4 files changed, 29 insertions, 5 deletions
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index 3ef6d059a..9047b8cb3 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -20,6 +20,7 @@ import annotation.unchecked
import util.Positions._
import util.{Stats, SimpleMap}
import util.common._
+import transform.SymUtils._
import Decorators._
import Uniques._
import ErrorReporting.{err, errorType, DiagnosticString}
@@ -328,9 +329,15 @@ trait Checking {
}
}
- def checkInstantiatable(cls: ClassSymbol, pos: Position): Unit = {
- ??? // to be done in later phase: check that class `cls` is legal in a new.
- }
+ def checkParentCall(call: Tree, caller: ClassSymbol)(implicit ctx: Context) =
+ if (!ctx.isAfterTyper) {
+ val called = call.tpe.classSymbol
+ if (caller is Trait)
+ ctx.error(i"$caller may not call constructor of $called", call.pos)
+ else if (called.is(Trait) && !caller.mixins.contains(called))
+ ctx.error(i"""$called is already implemented by super${caller.superClass},
+ |its constructor cannot be called again""".stripMargin, call.pos)
+ }
}
trait NoChecking extends Checking {
@@ -343,4 +350,5 @@ trait NoChecking extends Checking {
override def checkImplicitParamsNotSingletons(vparamss: List[List[ValDef]])(implicit ctx: Context): Unit = ()
override def checkFeasible(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = tp
override def checkNoDoubleDefs(cls: Symbol)(implicit ctx: Context): Unit = ()
+ override def checkParentCall(call: Tree, caller: ClassSymbol)(implicit ctx: Context) = ()
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 5f03d19e7..2bdd0d197 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -911,8 +911,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
if (tree.isType) typedType(tree)(superCtx)
else {
val result = typedExpr(tree)(superCtx)
- if ((cls is Trait) && result.tpe.classSymbol.isRealClass && !ctx.isAfterTyper)
- ctx.error(s"trait may not call constructor of ${result.tpe.classSymbol}", tree.pos)
+ checkParentCall(result, cls)
result
}
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index 0a6127580..ec5e34574 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -138,6 +138,7 @@ class tests extends CompilerTest {
@Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8)
@Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5)
@Test def neg_shadowedImplicits = compileFile(negDir, "arrayclone-new", xerrors = 2)
+ @Test def neg_traitParamsTyper = compileFile(negDir, "traitParamsTyper", xerrors = 5)
@Test def run_all = runFiles(runDir)
diff --git a/tests/neg/traitParamsTyper.scala b/tests/neg/traitParamsTyper.scala
new file mode 100644
index 000000000..f87ba3691
--- /dev/null
+++ b/tests/neg/traitParamsTyper.scala
@@ -0,0 +1,16 @@
+trait T(x: Int) {
+ def f = x
+}
+
+class C(x: Int) extends T() // error
+
+trait U extends C with T
+
+trait V extends C(1) with T(2) // two errors
+
+trait W extends T(3) // error
+
+
+class E extends T(0)
+class F extends E with T(1) // error
+