diff options
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 11 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/RefChecks.scala | 11 | ||||
-rw-r--r-- | tests/neg/i1653.scala | 3 | ||||
-rw-r--r-- | tests/neg/i705-inner-value-class.scala | 2 | ||||
-rw-r--r-- | tests/neg/i705-inner-value-class2.scala | 9 |
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 +} + + |