aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--tests/neg/i705-inner-value-class.scala2
-rw-r--r--tests/neg/i705-inner-value-class2.scala9
5 files changed, 24 insertions, 12 deletions
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index dd7326fae..687de1e7a 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -656,6 +656,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)
@@ -674,7 +676,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
+}
diff --git a/tests/neg/i705-inner-value-class.scala b/tests/neg/i705-inner-value-class.scala
index 82ac962b5..ecef8c5fe 100644
--- a/tests/neg/i705-inner-value-class.scala
+++ b/tests/neg/i705-inner-value-class.scala
@@ -15,8 +15,6 @@ object Test {
class C(val a: Int) extends AnyVal // error: value class may not be a local class
new C(1)
}
- class B1(val b: Int) extends B(b) // error: cannot extend final class B
-// class D extends B( { class E(val a: Int) extends AnyVal; new E(1) } )
}
diff --git a/tests/neg/i705-inner-value-class2.scala b/tests/neg/i705-inner-value-class2.scala
new file mode 100644
index 000000000..a084da338
--- /dev/null
+++ b/tests/neg/i705-inner-value-class2.scala
@@ -0,0 +1,9 @@
+class Foo {
+ class B(val a: Int) extends AnyVal
+}
+
+object Test {
+ class B1(val b: Int) extends B(b) // error: cannot extend final class B
+}
+
+