Skip to content

Fix #1653: Check "no inherit from final" earlier. #1666

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
}
}
}

Expand Down
11 changes: 2 additions & 9 deletions src/dotty/tools/dotc/typer/RefChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 _ =>
Expand Down
3 changes: 3 additions & 0 deletions tests/neg/i1653.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
trait Foo {
def foo() = new Unit with Foo // error
}
2 changes: 0 additions & 2 deletions tests/neg/i705-inner-value-class.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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) } )
}


9 changes: 9 additions & 0 deletions tests/neg/i705-inner-value-class2.scala
Original file line number Diff line number Diff line change
@@ -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
}