Skip to content

Commit d63f5b9

Browse files
committed
Implement checking for illegal parent trait constructor calls.
A parent trait may not be parameterized (as in T()) if the calling class does not directly implement that trait.
1 parent 2c55900 commit d63f5b9

File tree

4 files changed

+29
-6
lines changed

4 files changed

+29
-6
lines changed

src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import annotation.unchecked
2020
import util.Positions._
2121
import util.{Stats, SimpleMap}
2222
import util.common._
23+
import transform.SymUtils._
2324
import Decorators._
2425
import Uniques._
2526
import ErrorReporting.{err, errorType, DiagnosticString}
@@ -334,9 +335,15 @@ trait Checking {
334335
}
335336
}
336337

337-
def checkInstantiatable(cls: ClassSymbol, pos: Position): Unit = {
338-
??? // to be done in later phase: check that class `cls` is legal in a new.
339-
}
338+
def checkParentCall(call: Tree, caller: ClassSymbol)(implicit ctx: Context) =
339+
if (!ctx.isAfterTyper) {
340+
val called = call.tpe.classSymbol
341+
if (caller is Trait)
342+
ctx.error(i"$caller may not call constructor of $called", call.pos)
343+
else if (called.is(Trait) && !caller.mixins.contains(called))
344+
ctx.error(i"""$called is already implemented by super${caller.superClass},
345+
|its constructor cannot be called again""".stripMargin, call.pos)
346+
}
340347
}
341348

342349
trait NoChecking extends Checking {
@@ -350,4 +357,5 @@ trait NoChecking extends Checking {
350357
override def checkImplicitParamsNotSingletons(vparamss: List[List[ValDef]])(implicit ctx: Context): Unit = ()
351358
override def checkFeasible(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = tp
352359
override def checkNoDoubleDefs(cls: Symbol)(implicit ctx: Context): Unit = ()
360+
override def checkParentCall(call: Tree, caller: ClassSymbol)(implicit ctx: Context) = ()
353361
}

src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -913,8 +913,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
913913
if (tree.isType) typedType(tree)(superCtx)
914914
else {
915915
val result = typedExpr(tree)(superCtx)
916-
if ((cls is Trait) && result.tpe.classSymbol.isRealClass && !ctx.isAfterTyper)
917-
ctx.error(s"trait may not call constructor of ${result.tpe.classSymbol}", tree.pos)
916+
checkParentCall(result, cls)
918917
result
919918
}
920919

test/dotc/tests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ class tests extends CompilerTest {
137137
@Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2)
138138
@Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8)
139139
@Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5)
140-
140+
@Test def neg_traitParamsTyper = compileFile(negDir, "traitParamsTyper", xerrors = 5)
141141

142142
@Test def run_all = runFiles(runDir)
143143

tests/neg/traitParamsTyper.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
trait T(x: Int) {
2+
def f = x
3+
}
4+
5+
class C(x: Int) extends T() // error
6+
7+
trait U extends C with T
8+
9+
trait V extends C(1) with T(2) // two errors
10+
11+
trait W extends T(3) // error
12+
13+
14+
class E extends T(0)
15+
class F extends E with T(1) // error
16+

0 commit comments

Comments
 (0)