Skip to content

Commit

Permalink
Check that a self type T is closed.
Browse files Browse the repository at this point in the history
What is checked: A self type T is a subtype of all
selftypes of classes refernced by T. That is, a self type
has to subsume all self types of its required type. Ot,
otherwise said, requirements must be closed; you cannot
discover new ones in following them.
  • Loading branch information
odersky committed Jun 28, 2015
1 parent 35151a1 commit 40cd899
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 7 deletions.
18 changes: 12 additions & 6 deletions src/dotty/tools/dotc/typer/RefChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,20 @@ object RefChecks {
}
}

/** Check that self type of this class conforms to self types of parents */
private def checkSelfType(clazz: Symbol)(implicit ctx: Context): Unit = clazz.info match {
/** Check that self type of this class conforms to self types of parents
* and required classes.
*/
private def checkSelfType(cls: Symbol)(implicit ctx: Context): Unit = cls.info match {
case cinfo: ClassInfo =>
for (parent <- cinfo.classParents) {
val pself = parent.givenSelfType.asSeenFrom(clazz.thisType, parent.classSymbol)
if (pself.exists && !(cinfo.selfType <:< pself))
ctx.error(d"illegal inheritance: self type ${cinfo.selfType} of $clazz does not conform to self type $pself of parent ${parent.classSymbol}", clazz.pos)
def checkSelfConforms(other: TypeRef, category: String, relation: String) = {
val otherSelf = other.givenSelfType.asSeenFrom(cls.thisType, other.classSymbol)
if (otherSelf.exists && !(cinfo.selfType <:< otherSelf))
ctx.error(d"$category: self type ${cinfo.selfType} of $cls does not conform to self type $otherSelf of $relation ${other.classSymbol}", cls.pos)
}
for (parent <- cinfo.classParents)
checkSelfConforms(parent, "illegal inheritance", "parent")
for (reqd <- cinfo.givenSelfType.classSymbols)
checkSelfConforms(reqd.typeRef, "missing requirement", "required")
case _ =>
}

Expand Down
2 changes: 1 addition & 1 deletion test/dotc/tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class tests extends CompilerTest {
@Test def neg_moduleSubtyping = compileFile(negDir, "moduleSubtyping", xerrors = 4)
@Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2)
@Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8)
@Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5)
@Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 6)
@Test def neg_selfreq = compileFile(negDir, "selfreq", xerrors = 4)
@Test def neg_shadowedImplicits = compileFile(negDir, "arrayclone-new", xerrors = 2)
@Test def neg_traitParamsTyper = compileFile(negDir, "traitParamsTyper", xerrors = 5)
Expand Down
4 changes: 4 additions & 0 deletions tests/neg/selfInheritance.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ object Test {
object M extends C // error

}

trait X { self: Y => }
trait Y { self: Z => }
trait Z

0 comments on commit 40cd899

Please sign in to comment.