diff options
author | Martin Odersky <odersky@gmail.com> | 2015-06-28 19:33:35 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-07-06 17:02:17 +0200 |
commit | 175499537c87c78d0b926d84b7a9030011e42c00 (patch) | |
tree | 20d6897f2dc55689dc90650fba09259d228cb622 /src/dotty/tools/dotc/typer/RefChecks.scala | |
parent | 1061743aaaf2b18419c8fdb1cc89cb1498c9673f (diff) | |
download | dotty-175499537c87c78d0b926d84b7a9030011e42c00.tar.gz dotty-175499537c87c78d0b926d84b7a9030011e42c00.tar.bz2 dotty-175499537c87c78d0b926d84b7a9030011e42c00.zip |
Check that a self type T is closed.
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.
Diffstat (limited to 'src/dotty/tools/dotc/typer/RefChecks.scala')
-rw-r--r-- | src/dotty/tools/dotc/typer/RefChecks.scala | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala index bb22e2045..71fba1588 100644 --- a/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/src/dotty/tools/dotc/typer/RefChecks.scala @@ -73,19 +73,25 @@ object RefChecks { /** Check that final and sealed restrictions on class parents * and that self type of this class conforms to self types of parents. + * and required classes. */ - private def checkParents(clazz: Symbol)(implicit ctx: Context): Unit = clazz.info match { + private def checkParents(cls: Symbol)(implicit ctx: Context): Unit = cls.info match { case cinfo: ClassInfo => + 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) { val pclazz = parent.classSymbol if (pclazz.is(Final)) - ctx.error(d"cannot extend final $pclazz", clazz.pos) - if (pclazz.is(Sealed) && pclazz.associatedFile != clazz.associatedFile) - ctx.error(d"cannot extend sealed $pclazz in different compilation unit", clazz.pos) - 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) + ctx.error(d"cannot extend final $pclazz", cls.pos) + if (pclazz.is(Sealed) && pclazz.associatedFile != cls.associatedFile) + ctx.error(d"cannot extend sealed $pclazz in different compilation unit", cls.pos) + checkSelfConforms(parent, "illegal inheritance", "parent") } + for (reqd <- cinfo.givenSelfType.classSymbols) + checkSelfConforms(reqd.typeRef, "missing requirement", "required") case _ => } |