aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-11-06 09:28:44 +0100
committerMartin Odersky <odersky@gmail.com>2016-11-06 09:32:49 +0100
commitc8f54cf0a1438f3a17341eb3458d8eaa76b8293d (patch)
treef24f83bf69d7738cd48accd4ef5c0b95b6ee0c2d
parenta55a2607c7376ed81141ef958d6a8eeaeea8fd72 (diff)
downloaddotty-c8f54cf0a1438f3a17341eb3458d8eaa76b8293d.tar.gz
dotty-c8f54cf0a1438f3a17341eb3458d8eaa76b8293d.tar.bz2
dotty-c8f54cf0a1438f3a17341eb3458d8eaa76b8293d.zip
Fix #1653: Check "no inherit from final" earlier.
The test case is an illegal inheritance from a primitive value class, which makes this an illegal value class. Previously, the error was detected by refchecks, but crashes occured earlier (when generating synthesized methods) or at the same phase block (in extension methods). The problem is avoided by moving the test to Namer. Review by @smarter.
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala11
-rw-r--r--src/dotty/tools/dotc/typer/RefChecks.scala11
-rw-r--r--tests/neg/i1653.scala3
3 files changed, 15 insertions, 10 deletions
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 9da0e2edc..d4aa31498 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -666,6 +666,8 @@ class Namer { typer: Typer =>
* (1) It must be a class type with a stable prefix (@see checkClassTypeWithStablePrefix)
* (2) If may not derive from itself
* (3) Overriding type parameters must be correctly forwarded. (@see checkTypeParamOverride)
+ * (4) The class is not final
+ * (5) If the class is sealed, it is defined in the same compilation unit as the current class
*/
def checkedParentType(parent: untpd.Tree, paramAccessors: List[Symbol]): Type = {
val ptype = parentType(parent)(ctx.superCallContext)
@@ -684,7 +686,14 @@ class Namer { typer: Typer =>
}
else if (!paramAccessors.forall(checkTypeParamOverride(pt, _)))
defn.ObjectType
- else pt
+ else {
+ val pclazz = pt.typeSymbol
+ if (pclazz.is(Final))
+ ctx.error(em"cannot extend final $pclazz", cls.pos)
+ if (pclazz.is(Sealed) && pclazz.associatedFile != cls.associatedFile)
+ ctx.error(em"cannot extend sealed $pclazz in different compilation unit", cls.pos)
+ pt
+ }
}
}
diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala
index 026015d1d..46bdbf3b3 100644
--- a/src/dotty/tools/dotc/typer/RefChecks.scala
+++ b/src/dotty/tools/dotc/typer/RefChecks.scala
@@ -72,8 +72,7 @@ object RefChecks {
}
}
- /** Check that final and sealed restrictions on class parents
- * and that self type of this class conforms to self types of parents.
+ /** Check that self type of this class conforms to self types of parents.
* and required classes.
*/
private def checkParents(cls: Symbol)(implicit ctx: Context): Unit = cls.info match {
@@ -83,14 +82,8 @@ object RefChecks {
if (otherSelf.exists && !(cinfo.selfType <:< otherSelf))
ctx.error(ex"$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(em"cannot extend final $pclazz", cls.pos)
- if (pclazz.is(Sealed) && pclazz.associatedFile != cls.associatedFile)
- ctx.error(em"cannot extend sealed $pclazz in different compilation unit", cls.pos)
+ for (parent <- cinfo.classParents)
checkSelfConforms(parent, "illegal inheritance", "parent")
- }
for (reqd <- cinfo.givenSelfType.classSymbols)
checkSelfConforms(reqd.typeRef, "missing requirement", "required")
case _ =>
diff --git a/tests/neg/i1653.scala b/tests/neg/i1653.scala
new file mode 100644
index 000000000..ab5369e5f
--- /dev/null
+++ b/tests/neg/i1653.scala
@@ -0,0 +1,3 @@
+trait Foo {
+ def foo() = new Unit with Foo // error
+}