Skip to content

Commit 1cba611

Browse files
committed
Don't treat default classes as sum types
Classes representing sum types need to be be abstract, which default classes are not. This partially reverts "Treat non-open classes as effectively sealed." d98c2d6.
1 parent eb95fe1 commit 1cba611

File tree

6 files changed

+15
-18
lines changed

6 files changed

+15
-18
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@ object SymDenotations {
10771077
final def isEffectivelySealed(given Context): Boolean =
10781078
isOneOf(FinalOrSealed) || isClass && !isOneOf(EffectivelyOpenFlags)
10791079

1080-
/** The class containing this denotation which has the given effective name. */
1080+
/** The class containing this denotation which has the given effective name. */
10811081
final def enclosingClassNamed(name: Name)(implicit ctx: Context): Symbol = {
10821082
val cls = enclosingClass
10831083
if (cls.effectiveName == name || !cls.exists) cls else cls.owner.enclosingClassNamed(name)

compiler/src/dotty/tools/dotc/transform/SymUtils.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,8 @@ class SymUtils(val self: Symbol) extends AnyVal {
9191
* - all of its children are generic products or singletons
9292
*/
9393
def whyNotGenericSum(implicit ctx: Context): String =
94-
if !self.isEffectivelySealed then
94+
if (!self.is(Sealed))
9595
s"it is not a sealed ${self.kindString}"
96-
else if self.is(Final) then
97-
s"it is a final class"
9896
else {
9997
val children = self.children
10098
val companion = self.linkedClass

compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
509509
if (clazz.is(Case)) makeSingletonMirror()
510510
else if (linked.isGenericProduct) makeProductMirror(linked)
511511
else if (linked.isGenericSum) makeSumMirror(linked)
512-
else if linked.isEffectivelySealed then
512+
else if (linked.is(Sealed))
513513
derive.println(i"$linked is not a sum because ${linked.whyNotGenericSum}")
514514
}
515515
else if (impl.removeAttachment(ExtendsSingletonMirror).isDefined)

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
550550
def canDecompose(tp: Type): Boolean = {
551551
val dealiasedTp = tp.dealias
552552
val res =
553-
(tp.classSymbol.isEffectivelySealed &&
553+
(tp.classSymbol.is(Sealed) &&
554554
tp.classSymbol.isOneOf(AbstractOrTrait) &&
555555
!tp.classSymbol.hasAnonymousChild &&
556556
tp.classSymbol.children.nonEmpty ) ||
@@ -672,7 +672,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
672672
if (mergeList) "_: _*" else "_: List"
673673
else if (scalaConsType.isRef(sym))
674674
if (mergeList) "_, _: _*" else "List(_, _: _*)"
675-
else if (tp.classSymbol.isEffectivelySealed && tp.classSymbol.hasAnonymousChild)
675+
else if (tp.classSymbol.is(Sealed) && tp.classSymbol.hasAnonymousChild)
676676
"_: " + showType(tp) + " (anonymous)"
677677
else if (tp.classSymbol.is(CaseClass) && !hasCustomUnapply(tp.classSymbol))
678678
// use constructor syntax for case class

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -874,19 +874,18 @@ class Namer { typer: Typer =>
874874
def registerIfChild(denot: SymDenotation)(implicit ctx: Context): Unit = {
875875
val sym = denot.symbol
876876

877-
def register(child: Symbol, parent: Type) =
877+
def register(child: Symbol, parent: Type) = {
878878
val cls = parent.classSymbol
879-
if cls.isEffectivelySealed
880-
&& child.associatedFile == cls.associatedFile // don't register ad-hoc extensions as children
881-
then
882-
if (child.isInaccessibleChildOf(cls) || child.isAnonymousClass) && !sym.hasAnonymousChild then
879+
if (cls.is(Sealed))
880+
if ((child.isInaccessibleChildOf(cls) || child.isAnonymousClass) && !sym.hasAnonymousChild)
883881
addChild(cls, cls)
884-
else if !cls.is(ChildrenQueried) then
882+
else if (!cls.is(ChildrenQueried))
885883
addChild(cls, child)
886884
else
887885
ctx.error(em"""children of $cls were already queried before $sym was discovered.
888886
|As a remedy, you could move $sym on the same nesting level as $cls.""",
889887
child.sourcePos)
888+
}
890889

891890
if (denot.isClass && !sym.isEnumAnonymClass && !sym.isRefinementClass)
892891
denot.asClass.classParents.foreach { parent =>

docs/docs/reference/other-new-features/open-classes.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ open class Writer[T] with
1616
/** Send all arguments using `send` */
1717
def sendAll(xs: T*) = xs.foreach(send)
1818

19+
1920
// File EncryptedWriter.scala
2021
package p
2122

@@ -29,12 +30,11 @@ Classes that are not open can still be extended, but only if one of two alternat
2930

3031
- The extending class is in the same source file as the extended class. In this case, the extension is usually an internal implementation matter.
3132

32-
- The language feature `adhocExtensions` is enabled for the extending class. This is typically enabled by an import statement
33+
- The language feature `adhocExtensions` is enabled for the extending class. This is typically enabled by an import statement in the source file of the extension:
3334
```scala
3435
import scala.language.adhocExtensions
3536
```
36-
in the source file of the extension, but can alternatively be provided
37-
by a command line option `-language:adhocExtensions`.
37+
Alternatively, the feature can be enabled by the command line option `-language:adhocExtensions`.
3838
If the feature is not enabled, the compiler will issue a "feature" warning. For instance, if the `open` modifier on class `Writer` is dropped, compiling `EncryptedWriter` would produce a warning:
3939
```
4040
-- Feature Warning: EncryptedWriter.scala:6:14 ----
@@ -69,9 +69,9 @@ to mock classes in tests, or to apply temporary patches that add features or fix
6969
- An `open` class cannot be `final` or `sealed`.
7070
- Traits or `abstract` classes are always `open`, so `open` is redundant for them.
7171

72-
### Relatinship with `sealed`
72+
### Relationship with `sealed`
7373

74-
A class that is neither `abstract` nor `open` is similar to a `sealed` class`: it can still be extended, but only in the same compilation unit. The difference is what happens if an extension of the class is attempted in a different compilation unit. For a `sealed` class, this is an error, whereas for a simple non-open class, this is still permitted provided the `adhocExtensions` feature is enabled, and gives a warning otherwise.
74+
A class that is neither `abstract` nor `open` is similar to a `sealed` class: it can still be extended, but only in the same compilation unit. The difference is what happens if an extension of the class is attempted in another compilation unit. For a `sealed` class, this is an error, whereas for a simple non-open class, this is still permitted provided the `adhocExtensions` feature is enabled, and it gives a warning otherwise.
7575

7676
### Migration
7777

0 commit comments

Comments
 (0)