Skip to content

Commit c8f54cf

Browse files
committed
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.
1 parent a55a260 commit c8f54cf

File tree

3 files changed

+15
-10
lines changed

3 files changed

+15
-10
lines changed

src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,8 @@ class Namer { typer: Typer =>
666666
* (1) It must be a class type with a stable prefix (@see checkClassTypeWithStablePrefix)
667667
* (2) If may not derive from itself
668668
* (3) Overriding type parameters must be correctly forwarded. (@see checkTypeParamOverride)
669+
* (4) The class is not final
670+
* (5) If the class is sealed, it is defined in the same compilation unit as the current class
669671
*/
670672
def checkedParentType(parent: untpd.Tree, paramAccessors: List[Symbol]): Type = {
671673
val ptype = parentType(parent)(ctx.superCallContext)
@@ -684,7 +686,14 @@ class Namer { typer: Typer =>
684686
}
685687
else if (!paramAccessors.forall(checkTypeParamOverride(pt, _)))
686688
defn.ObjectType
687-
else pt
689+
else {
690+
val pclazz = pt.typeSymbol
691+
if (pclazz.is(Final))
692+
ctx.error(em"cannot extend final $pclazz", cls.pos)
693+
if (pclazz.is(Sealed) && pclazz.associatedFile != cls.associatedFile)
694+
ctx.error(em"cannot extend sealed $pclazz in different compilation unit", cls.pos)
695+
pt
696+
}
688697
}
689698
}
690699

src/dotty/tools/dotc/typer/RefChecks.scala

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ object RefChecks {
7272
}
7373
}
7474

75-
/** Check that final and sealed restrictions on class parents
76-
* and that self type of this class conforms to self types of parents.
75+
/** Check that self type of this class conforms to self types of parents.
7776
* and required classes.
7877
*/
7978
private def checkParents(cls: Symbol)(implicit ctx: Context): Unit = cls.info match {
@@ -83,14 +82,8 @@ object RefChecks {
8382
if (otherSelf.exists && !(cinfo.selfType <:< otherSelf))
8483
ctx.error(ex"$category: self type ${cinfo.selfType} of $cls does not conform to self type $otherSelf of $relation ${other.classSymbol}", cls.pos)
8584
}
86-
for (parent <- cinfo.classParents) {
87-
val pclazz = parent.classSymbol
88-
if (pclazz.is(Final))
89-
ctx.error(em"cannot extend final $pclazz", cls.pos)
90-
if (pclazz.is(Sealed) && pclazz.associatedFile != cls.associatedFile)
91-
ctx.error(em"cannot extend sealed $pclazz in different compilation unit", cls.pos)
85+
for (parent <- cinfo.classParents)
9286
checkSelfConforms(parent, "illegal inheritance", "parent")
93-
}
9487
for (reqd <- cinfo.givenSelfType.classSymbols)
9588
checkSelfConforms(reqd.typeRef, "missing requirement", "required")
9689
case _ =>

tests/neg/i1653.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
trait Foo {
2+
def foo() = new Unit with Foo // error
3+
}

0 commit comments

Comments
 (0)