Skip to content

Commit 4e3d6e4

Browse files
committed
Remove untpd.EnumGetters
no longer special case some definitions for indexing after the parents of a class are discovered. Extend invalidateIfClashingSynthetic to cover ordinal override from java.lang.Enum
1 parent 7adfa3f commit 4e3d6e4

File tree

8 files changed

+41
-53
lines changed

8 files changed

+41
-53
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ object desugar {
5858
case _ => false
5959
}
6060

61+
def isRetractableCaseClassOrEnumMethodName(name: Name)(using Context): Boolean =
62+
isRetractableCaseClassMethodName(name) || name == nme.ordinal
63+
6164
/** Is `name` the name of a method that is added unconditionally to case classes? */
6265
def isDesugaredCaseClassMethodName(name: Name)(using Context): Boolean =
6366
isRetractableCaseClassMethodName(name) || name.isSelectorName
@@ -485,8 +488,8 @@ object desugar {
485488
val enumImport =
486489
Import(enumCompanionRef, enumCases.flatMap(caseIds).map(ImportSelector(_)))
487490
val enumLabelDef = DesugarEnums.enumLabelMeth(EmptyTree)
488-
val enumGetters = EnumGetters() // optionally generate ordinal method
489-
(enumImport :: enumGetters :: enumLabelDef :: enumStats, enumCases, enumCompanionRef)
491+
val ordinalDef = DesugarEnums.ordinalMeth(EmptyTree).withAddedFlags(Synthetic)
492+
(enumImport :: ordinalDef :: enumLabelDef :: enumStats, enumCases, enumCompanionRef)
490493
}
491494
else (stats, Nil, EmptyTree)
492495
}
@@ -891,9 +894,6 @@ object desugar {
891894
}
892895
}
893896

894-
def enumGetters(getters: EnumGetters)(using Context): Tree =
895-
flatTree(DesugarEnums.optionalOrdinalMethod).withSpan(getters.span)
896-
897897
/** Transform extension construct to list of extension methods */
898898
def extMethods(ext: ExtMethods)(using Context): Tree = flatTree {
899899
for mdef <- ext.methods yield

compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,6 @@ object DesugarEnums {
322322
(ordinal, Nil)
323323
}
324324

325-
def optionalOrdinalMethod(using Context): List[Tree] =
326-
if isJavaEnum then Nil
327-
else ordinalMeth(EmptyTree) :: Nil
328-
329325
def param(name: TermName, typ: Type)(using Context): ValDef = param(name, TypeTree(typ))
330326
def param(name: TermName, tpt: Tree)(using Context): ValDef = ValDef(name, tpt, EmptyTree).withFlags(Param)
331327

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
116116
case class Export(expr: Tree, selectors: List[ImportSelector])(implicit @constructorOnly src: SourceFile) extends Tree
117117
case class ExtMethods(tparams: List[TypeDef], vparamss: List[List[ValDef]], methods: List[DefDef])(implicit @constructorOnly src: SourceFile) extends Tree
118118
case class MacroTree(expr: Tree)(implicit @constructorOnly src: SourceFile) extends Tree
119-
case class EnumGetters()(implicit @constructorOnly src: SourceFile) extends Tree
120119

121120
case class ImportSelector(imported: Ident, renamed: Tree = EmptyTree, bound: Tree = EmptyTree)(implicit @constructorOnly src: SourceFile) extends Tree {
122121
// TODO: Make bound a typed tree?
@@ -701,7 +700,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
701700
cpy.Export(tree)(transform(expr), selectors)
702701
case ExtMethods(tparams, vparamss, methods) =>
703702
cpy.ExtMethods(tree)(transformSub(tparams), vparamss.mapConserve(transformSub(_)), transformSub(methods))
704-
case enums: EnumGetters => enums
705703
case ImportSelector(imported, renamed, bound) =>
706704
cpy.ImportSelector(tree)(transformSub(imported), transform(renamed), transform(bound))
707705
case Number(_, _) | TypedSplice(_) =>
@@ -763,8 +761,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
763761
this(x, expr)
764762
case ExtMethods(tparams, vparamss, methods) =>
765763
this(vparamss.foldLeft(this(x, tparams))(apply), methods)
766-
case EnumGetters() =>
767-
x
768764
case ImportSelector(imported, renamed, bound) =>
769765
this(this(this(x, imported), renamed), bound)
770766
case Number(_, _) =>

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ object SymUtils {
168168
self
169169
}
170170

171-
def isScalaEnum(using Context): Boolean = self.is(Enum, butNot=JavaDefined)
171+
def isEnum(using Context): Boolean = self.is(Enum, butNot=JavaDefined)
172+
def isEnumClass(using Context): Boolean = isEnum && !self.is(Case)
172173

173174
/** Does this symbol refer to anonymous classes synthesized by enum desugaring? */
174175
def isEnumAnonymClass(using Context): Boolean =

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
9494
lazy val accessors =
9595
if (isDerivedValueClass(clazz)) clazz.paramAccessors.take(1) // Tail parameters can only be `erased`
9696
else clazz.caseAccessors
97-
val isEnumCase = clazz.classParents.exists(_.classSymbol.isScalaEnum)
98-
val isEnumValue = isEnumCase && clazz.isAnonymousClass && clazz.classParents.head.classSymbol.is(Enum)
97+
val isEnumCase = clazz.isEnum || clazz.classParents.exists(_.classSymbol.isEnum)
98+
val isEnumValue = isEnumCase && clazz.isAnonymousClass && clazz.classParents.head.classSymbol.isEnum
9999
val isNonJavaEnumValue = isEnumValue && !clazz.derivesFrom(defn.JavaEnumClass)
100100

101101
val symbolsToSynthesize: List[Symbol] =

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

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -343,20 +343,17 @@ class Namer { typer: Typer =>
343343
tree.pushAttachment(ExpandedTree, expanded)
344344
}
345345
tree match {
346-
case tree: DefTree => record(desugar.defTree(tree))
347-
case tree: PackageDef => record(desugar.packageDef(tree))
348-
case tree: ExtMethods => record(desugar.extMethods(tree))
349-
case tree: EnumGetters => record(desugar.enumGetters(tree))
350-
case _ =>
346+
case tree: DefTree => record(desugar.defTree(tree))
347+
case tree: PackageDef => record(desugar.packageDef(tree))
348+
case tree: ExtMethods => record(desugar.extMethods(tree))
349+
case _ =>
351350
}
352351
}
353352

354353
/** The expanded version of this tree, or tree itself if not expanded */
355354
def expanded(tree: Tree)(using Context): Tree = tree match {
356-
case _: DefTree | _: PackageDef | _: ExtMethods | _: EnumGetters =>
357-
tree.attachmentOrElse(ExpandedTree, tree)
358-
case _ =>
359-
tree
355+
case _: DefTree | _: PackageDef | _: ExtMethods => tree.attachmentOrElse(ExpandedTree, tree)
356+
case _ => tree
360357
}
361358

362359
/** For all class definitions `stat` in `xstats`: If the companion class is
@@ -746,21 +743,34 @@ class Namer { typer: Typer =>
746743
}
747744

748745
/** Invalidate `denot` by overwriting its info with `NoType` if
749-
* `denot` is a compiler generated case class method that clashes
750-
* with a user-defined method in the same scope with a matching type.
746+
* one of the following holds:
747+
* - `denot` is a compiler generated case class method that clashes
748+
* with a user-defined method in the same scope with a matching type.
749+
* - `denot` is a compiler generated `ordinal` method that would override
750+
* `ordinal` declared in `java.lang.Enum`
751751
*/
752752
private def invalidateIfClashingSynthetic(denot: SymDenotation): Unit = {
753753
def isCaseClass(owner: Symbol) =
754754
owner.isClass && {
755755
if (owner.is(Module)) owner.linkedClass.is(CaseClass)
756756
else owner.is(CaseClass)
757757
}
758-
val isClashingSynthetic =
759-
denot.is(Synthetic) &&
760-
desugar.isRetractableCaseClassMethodName(denot.name) &&
761-
isCaseClass(denot.owner) &&
762-
denot.owner.info.decls.lookupAll(denot.name).exists(alt =>
758+
def isJavaEnumBaseClass(owner: Symbol) =
759+
owner.isClass && owner.isEnumClass && owner.derivesFrom(defn.JavaEnumClass)
760+
def firstParentCls(owner: Symbol) =
761+
owner.asClass.classParents.head.classSymbol
762+
def findMatch(owner: Symbol) =
763+
owner.info.decls.lookupAll(denot.name).exists(alt =>
763764
alt != denot.symbol && alt.info.matchesLoosely(denot.info))
765+
def clashingCaseClassMethod =
766+
desugar.isRetractableCaseClassMethodName(denot.name)
767+
&& isCaseClass(denot.owner)
768+
&& findMatch(denot.owner)
769+
def clashingEnumMethod =
770+
denot.name == nme.ordinal
771+
&& isJavaEnumBaseClass(denot.owner)
772+
&& findMatch(firstParentCls(denot.owner))
773+
val isClashingSynthetic = denot.is(Synthetic) && (clashingCaseClassMethod || clashingEnumMethod)
764774
if (isClashingSynthetic) {
765775
typr.println(i"invalidating clashing $denot in ${denot.owner}")
766776
denot.markAbsent()
@@ -928,21 +938,11 @@ class Namer { typer: Typer =>
928938

929939
val TypeDef(name, impl @ Template(constr, _, self, _)) = original
930940

931-
private val (params, restOfBody): (List[Tree], List[Tree]) = impl.body.span {
941+
private val (params, rest): (List[Tree], List[Tree]) = impl.body.span {
932942
case td: TypeDef => td.mods.is(Param)
933943
case vd: ValDef => vd.mods.is(ParamAccessor)
934944
case _ => false
935945
}
936-
private val (restAfterParents, rest): (List[Tree], List[Tree]) =
937-
if original.mods.isEnumClass then
938-
// in Desugar.scala, desugaring an enum class definition fixes the
939-
// first and second statements in the body to be `imports` and `getters`.
940-
// `imports` is an import list of the enum cases from the companion of `cls`
941-
// `getters` will expand to `def ordinal: Int` if the parents of `cls` are not java.lang.Enum
942-
val (imports :: getters :: Nil, stats): @unchecked = restOfBody.splitAt(2)
943-
(getters :: Nil, imports :: stats)
944-
else
945-
(Nil, restOfBody)
946946

947947
def init(): Context = index(params)
948948

@@ -1209,7 +1209,6 @@ class Namer { typer: Typer =>
12091209
cls.setNoInitsFlags(parentsKind(parents), untpd.bodyKind(rest))
12101210
if (cls.isNoInitsClass) cls.primaryConstructor.setFlag(StableRealizable)
12111211
processExports(using localCtx)
1212-
index(restAfterParents)(using localCtx)
12131212
}
12141213
}
12151214

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,11 +1941,10 @@ class Typer extends Namer
19411941
}
19421942

19431943
def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(using Context): Tree = {
1944-
if (!sym.info.exists) { // it's a discarded synthetic case class method, drop it
1945-
assert(sym.is(Synthetic) && desugar.isRetractableCaseClassMethodName(sym.name))
1944+
if !sym.info.exists then // it's a discarded synthetic case class method, or ordinal method drop it
1945+
assert(sym.is(Synthetic) && desugar.isRetractableCaseClassOrEnumMethodName(sym.name))
19461946
sym.owner.info.decls.openForMutations.unlink(sym)
19471947
return EmptyTree
1948-
}
19491948
val DefDef(name, tparams, vparamss, tpt, _) = ddef
19501949
completeAnnotations(ddef, sym)
19511950
val tparams1 = tparams.mapconserve(typed(_).asInstanceOf[TypeDef])
@@ -2123,7 +2122,7 @@ class Typer extends Namer
21232122
.withType(dummy.termRef)
21242123
if (!cls.isOneOf(AbstractOrTrait) && !ctx.isAfterTyper)
21252124
checkRealizableBounds(cls, cdef.sourcePos.withSpan(cdef.nameSpan))
2126-
if cls.isScalaEnum || firstParentTpe.classSymbol.isScalaEnum then
2125+
if cls.isEnum || firstParentTpe.classSymbol.isEnum then
21272126
checkEnum(cdef, cls, firstParent)
21282127
val cdef1 = assignType(cpy.TypeDef(cdef)(name, impl1), cls)
21292128

@@ -2636,9 +2635,6 @@ class Typer extends Namer
26362635
case (stat: untpd.ExtMethods) :: rest =>
26372636
val xtree = stat.removeAttachment(ExpandedTree).get
26382637
traverse(xtree :: rest)
2639-
case (stat: untpd.EnumGetters) :: rest =>
2640-
val xtree = stat.removeAttachment(ExpandedTree).get
2641-
traverse(xtree :: rest)
26422638
case stat :: rest =>
26432639
val stat1 = typed(stat)(using ctx.exprContext(stat, exprOwner))
26442640
checkStatementPurity(stat1)(stat, exprOwner)

tests/neg/enumsLabel-singleimpl.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ enum Labelled {
88

99
enum Ordinalled {
1010

11-
case A // error: double definition of method ordinal: => Int
11+
case A
1212

13-
def ordinal: Int = -1
13+
def ordinal: Int = -1 // error: double definition of method ordinal: => Int
1414

1515
}

0 commit comments

Comments
 (0)