Skip to content
Open
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
10 changes: 9 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,15 @@ object DesugarEnums {
val (tag, scaffolding) = nextOrdinal(name, CaseKind.Object, definesLookups)
val impl1 = cpy.Template(impl)(parents = impl.parents :+ scalaRuntimeDot(tpnme.EnumValue), body = Nil)
.withAttachment(ExtendsSingletonMirror, ())
val vdef = ValDef(name, TypeTree(), New(impl1)).withMods(mods.withAddedFlags(EnumValue, span))

/** i11443: Attempt to provide an explicit type annotation for the enum case to allow certain cycles.
* We pick the intersection of all parents, but only if they can be determined to be all types at this point.
* Notably, this doesn't hold if one of the parents is a constructor call (e.g., extends Planet("Pluto")),
* which might involve yet-to-be inferred generic parameters.
*/
val tpt = if impl.parents.forall(_.isType) then impl.parents.reduceLeft(makeAndType(_, _)) else TypeTree()

val vdef = ValDef(name, tpt, New(impl1)).withMods(mods.withAddedFlags(EnumValue, span))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we always add an explicit type without checking parent types?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No because we have a constructor, not a type when we desugar.

Copy link
Contributor Author

@bracevac bracevac Oct 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The best explicit annotation at this point seems to be the intersection of the parents, but only if all parent trees are known to be types. For example, all bets are off with constructor calls, because we have not yet inferred types.

flatTree(vdef :: scaffolding).withSpan(span)
}
}
Expand Down
10 changes: 5 additions & 5 deletions tests/neg/i6601.scala
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
object GADTs2 {
enum Var[G, A] {
case Z[A, G]() extends Expr[(A, G), A] // error
case X extends AnyRef // error
case X extends AnyRef // error // error
}
enum Expr[G, A] {
case Lit[G](n: Int) extends Expr[G, Int]
// case S[A, G](x:
}
enum Covariant[+T] {
case Bottom extends AnyRef // error
case Bottom extends AnyRef // error // error
}
enum Contravariant[-T] {
case Top extends AnyRef // error
case Top extends AnyRef // error // error
}
enum Color {
case Red extends AnyRef // error
case Red extends AnyRef // error // error
}
enum Parameterized[T](x: T) {
case Foo extends AnyRef // error
case Foo extends AnyRef // error // error
}
}
5 changes: 5 additions & 0 deletions tests/pos/i11443.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
enum Opt[T] {
case Nn extends Opt[Nothing] with Comparable[Nn.type]

def compareTo(nn: Nn.type) = 0
}
2 changes: 1 addition & 1 deletion tests/warn/i21860.scala → tests/pos/i21860.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ enum Shape extends Figure:
case Ellipsis extends Shape

def hasCorners(s: Shape): Boolean = s match
case hasCorners: Corners => true // <--- reported as `Unreachable case`
case hasCorners: Corners => true // <--- previously reported as `Unreachable case` (i21860), ok now (i11443)
case _ => false

class Test:
Expand Down
Loading