diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 03b879699957..54e3d26d61ac 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -58,6 +58,9 @@ object desugar { case _ => false } + def isRetractableCaseClassOrEnumMethodName(name: Name)(using Context): Boolean = + isRetractableCaseClassMethodName(name) || name == nme.ordinal + /** Is `name` the name of a method that is added unconditionally to case classes? */ def isDesugaredCaseClassMethodName(name: Name)(using Context): Boolean = isRetractableCaseClassMethodName(name) || name.isSelectorName @@ -403,6 +406,7 @@ object desugar { val isCaseObject = mods.is(Case) && isObject val isEnum = mods.isEnumClass && !mods.is(Module) def isEnumCase = mods.isEnumCase + def isNonEnumCase = !isEnumCase && (isCaseClass || isCaseObject) val isValueClass = parents.nonEmpty && isAnyVal(parents.head) // This is not watertight, but `extends AnyVal` will be replaced by `inline` later. @@ -483,7 +487,9 @@ object desugar { val enumCompanionRef = TermRefTree() val enumImport = Import(enumCompanionRef, enumCases.flatMap(caseIds).map(ImportSelector(_))) - (enumImport :: enumStats, enumCases, enumCompanionRef) + val enumLabelDef = DesugarEnums.enumLabelMeth(EmptyTree) + val ordinalDef = DesugarEnums.ordinalMeth(EmptyTree) + (enumImport :: ordinalDef :: enumLabelDef :: enumStats, enumCases, enumCompanionRef) } else (stats, Nil, EmptyTree) } @@ -621,10 +627,8 @@ object desugar { var parents1 = parents if (isEnumCase && parents.isEmpty) parents1 = enumClassTypeRef :: Nil - if (isCaseClass | isCaseObject) + if (isNonEnumCase || isEnum) parents1 = parents1 :+ scalaDot(str.Product.toTypeName) :+ scalaDot(nme.Serializable.toTypeName) - if (isEnum) - parents1 = parents1 :+ ref(defn.EnumClass.typeRef) // derived type classes of non-module classes go to their companions val (clsDerived, companionDerived) = diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index 4ed857678b26..868552102262 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -328,10 +328,10 @@ object DesugarEnums { private def isJavaEnum(using Context): Boolean = enumClass.derivesFrom(defn.JavaEnumClass) def ordinalMeth(body: Tree)(using Context): DefDef = - DefDef(nme.ordinal, Nil, Nil, TypeTree(defn.IntType), body) + DefDef(nme.ordinal, Nil, Nil, TypeTree(defn.IntType), body).withAddedFlags(Synthetic) def enumLabelMeth(body: Tree)(using Context): DefDef = - DefDef(nme.enumLabel, Nil, Nil, TypeTree(defn.StringType), body) + DefDef(nme.enumLabel, Nil, Nil, TypeTree(defn.StringType), body).withAddedFlags(Synthetic) def ordinalMethLit(ord: Int)(using Context): DefDef = ordinalMeth(Literal(Constant(ord))) diff --git a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala index 62500b758612..5a577b0de28a 100644 --- a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala +++ b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala @@ -168,6 +168,9 @@ object SymUtils { self } + def isEnum(using Context): Boolean = self.is(Enum, butNot=JavaDefined) + def isEnumClass(using Context): Boolean = isEnum && !self.is(Case) + /** Does this symbol refer to anonymous classes synthesized by enum desugaring? */ def isEnumAnonymClass(using Context): Boolean = self.isAnonymousClass && (self.owner.name.eq(nme.DOLLAR_NEW) || self.owner.is(CaseVal)) diff --git a/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala b/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala index bbd2f13395a0..982ba4c00b22 100644 --- a/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala +++ b/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala @@ -94,8 +94,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) { lazy val accessors = if (isDerivedValueClass(clazz)) clazz.paramAccessors.take(1) // Tail parameters can only be `erased` else clazz.caseAccessors - val isEnumCase = clazz.derivesFrom(defn.EnumClass) && clazz != defn.EnumClass - val isEnumValue = isEnumCase && clazz.isAnonymousClass && clazz.classParents.head.classSymbol.is(Enum) + val isEnumValue = clazz.isAnonymousClass && clazz.classParents.head.classSymbol.is(Enum) val isNonJavaEnumValue = isEnumValue && !clazz.derivesFrom(defn.JavaEnumClass) val symbolsToSynthesize: List[Symbol] = diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 02607393580d..205f446030b7 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -377,13 +377,13 @@ class Namer { typer: Typer => /** Expand tree and create top-level symbols for statement and enter them into symbol table */ def index(stat: Tree)(using Context): Context = { expand(stat) - indexExpanded(stat) + indexExpanded(stat, mutable.Buffer.empty) // here we do not expect to populate the buffer } /** Create top-level symbols for all statements in the expansion of this statement and * enter them into symbol table */ - def indexExpanded(origStat: Tree)(using Context): Context = { + def indexExpanded(origStat: Tree, delayedEntry: mutable.Buffer[Context ?=> Context])(using Context): Context = { def recur(stat: Tree): Context = stat match { case pcl: PackageDef => val pkg = createPackageSymbol(pcl.pid) @@ -395,10 +395,23 @@ class Namer { typer: Typer => ctx.importContext(imp, createSymbol(imp)) case mdef: DefTree => val sym = createSymbol(mdef) - enterSymbol(sym) - setDocstring(sym, origStat) - addEnumConstants(mdef, sym) - ctx + def enterDefTree(sym: Symbol): Context = + enterSymbol(sym) + setDocstring(sym, origStat) + addEnumConstants(mdef, sym) + ctx + if sym.is(Synthetic) && isEnumOrdinal(sym) then + delayedEntry += { ctx ?=> + // Here we delay entering into scope of an enum ordinal method until after + // the parents of `sym.owner` are known. This is because it is illegal to override ordinal + // in java.lang.Enum + if !clashingJavaEnumOrdinal(sym) then + enterDefTree(sym) + ctx + } + ctx + else + enterDefTree(sym) case stats: Thicket => stats.toList.foreach(recur) ctx @@ -456,7 +469,10 @@ class Namer { typer: Typer => /** Create top-level symbols for statements and enter them into symbol table * @return A context that reflects all imports in `stats`. */ - def index(stats: List[Tree])(using Context): Context = { + def index(stats: List[Tree])(using Context): Context = + index(stats, mutable.Buffer.empty) // here we do not expect to fill the buffer + + def index(stats: List[Tree], delayedEntry: mutable.Buffer[Context ?=> Context])(using Context): Context = { // module name -> (stat, moduleCls | moduleVal) val moduleClsDef = mutable.Map[TypeName, (Tree, TypeDef)]() @@ -631,7 +647,7 @@ class Namer { typer: Typer => stats.foreach(expand) mergeCompanionDefs() - val ctxWithStats = stats.foldLeft(ctx)((ctx, stat) => indexExpanded(stat)(using ctx)) + val ctxWithStats = stats.foldLeft(ctx)((ctx, stat) => indexExpanded(stat, delayedEntry)(using ctx)) createCompanionLinks(using ctxWithStats) ctxWithStats } @@ -663,6 +679,23 @@ class Namer { typer: Typer => sym.resetFlag(GivenOrImplicit) } + private def findMatch(denot: SymDenotation, owner: Symbol)(using Context) = + owner.info.decls.lookupAll(denot.name).exists(alt => + alt != denot.symbol && alt.info.matchesLoosely(denot.info)) + + private def isEnumOrdinal(denot: SymDenotation)(using Context) = + denot.name == nme.ordinal + && denot.owner.isClass && denot.owner.isEnumClass + + private def clashingJavaEnumOrdinal(denot: SymDenotation)(using Context) = + def firstParentCls(owner: Symbol) = + owner.asClass.classParents.head.classSymbol + def isJavaEnumBaseClass(owner: Symbol) = + owner.isClass && owner.isEnumClass && owner.derivesFrom(defn.JavaEnumClass) + denot.name == nme.ordinal + && isJavaEnumBaseClass(denot.owner) + && findMatch(denot, firstParentCls(denot.owner)) + /** The completer of a symbol defined by a member def or import (except ClassSymbols) */ class Completer(val original: Tree)(ictx: Context) extends LazyType with SymbolLoaders.SecondCompleter { @@ -743,8 +776,11 @@ class Namer { typer: Typer => } /** Invalidate `denot` by overwriting its info with `NoType` if - * `denot` is a compiler generated case class method that clashes - * with a user-defined method in the same scope with a matching type. + * one of the following holds: + * - `denot` is a compiler generated case class method that clashes + * with a user-defined method in the same scope with a matching type. + * - `denot` is a compiler generated `ordinal` method that would override + * `ordinal` declared in `java.lang.Enum` */ private def invalidateIfClashingSynthetic(denot: SymDenotation): Unit = { def isCaseClass(owner: Symbol) = @@ -752,12 +788,11 @@ class Namer { typer: Typer => if (owner.is(Module)) owner.linkedClass.is(CaseClass) else owner.is(CaseClass) } - val isClashingSynthetic = - denot.is(Synthetic) && - desugar.isRetractableCaseClassMethodName(denot.name) && - isCaseClass(denot.owner) && - denot.owner.info.decls.lookupAll(denot.name).exists(alt => - alt != denot.symbol && alt.info.matchesLoosely(denot.info)) + def clashingCaseClassMethod = + desugar.isRetractableCaseClassMethodName(denot.name) + && isCaseClass(denot.owner) + && findMatch(denot, denot.owner) + val isClashingSynthetic = denot.is(Synthetic) && (clashingCaseClassMethod || clashingJavaEnumOrdinal(denot)) if (isClashingSynthetic) { typr.println(i"invalidating clashing $denot in ${denot.owner}") denot.markAbsent() @@ -923,6 +958,11 @@ class Namer { typer: Typer => /** info to be used temporarily while completing the class, to avoid cyclic references. */ private var tempInfo: TempClassInfo = _ + /** we delay entry of the following symbols (already created) until after parents are known: + * - def ordinal: Int (if parent is not java.lang.Enum) + */ + private var delayedEntry: List[Context ?=> Context] = _ + val TypeDef(name, impl @ Template(constr, _, self, _)) = original private val (params, rest): (List[Tree], List[Tree]) = impl.body.span { @@ -1083,8 +1123,11 @@ class Namer { typer: Typer => localCtx = completerCtx.inClassContext(selfInfo) + val delayedEntryBuf = collection.mutable.ListBuffer.empty[Context ?=> Context] + index(constr) - index(rest)(using localCtx) + index(rest, delayedEntryBuf)(using localCtx) + delayedEntry = delayedEntryBuf.toList symbolOfTree(constr).info.stripPoly match // Completes constr symbol as a side effect case mt: MethodType if cls.is(Case) && mt.isParamDependent => @@ -1189,6 +1232,10 @@ class Namer { typer: Typer => denot.info = tempInfo.finalized(parentTypes) tempInfo = null // The temporary info can now be garbage-collected + // now we know the parents we can decide if we enter the symbols or not + delayedEntry.foldLeft(localCtx) { (localCtx, op) => op(using localCtx) } + delayedEntry = null + Checking.checkWellFormed(cls) if (isDerivedValueClass(cls)) cls.setFlag(Final) cls.info = avoidPrivateLeaks(cls) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index f414c0aadf3a..f0139a05648a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1941,11 +1941,10 @@ class Typer extends Namer } def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(using Context): Tree = { - if (!sym.info.exists) { // it's a discarded synthetic case class method, drop it - assert(sym.is(Synthetic) && desugar.isRetractableCaseClassMethodName(sym.name)) + if !sym.info.exists then // it's a discarded synthetic case class method, or ordinal method drop it + assert(sym.is(Synthetic) && desugar.isRetractableCaseClassOrEnumMethodName(sym.name)) sym.owner.info.decls.openForMutations.unlink(sym) return EmptyTree - } val DefDef(name, tparams, vparamss, tpt, _) = ddef completeAnnotations(ddef, sym) val tparams1 = tparams.mapconserve(typed(_).asInstanceOf[TypeDef]) @@ -2105,7 +2104,8 @@ class Typer extends Namer val constr1 = typed(constr).asInstanceOf[DefDef] val parentsWithClass = ensureFirstTreeIsClass(parents.mapconserve(typedParent).filterConserve(!_.isEmpty), cdef.nameSpan) val parents1 = ensureConstrCall(cls, parentsWithClass)(using superCtx) - val firstParent = parents1.head.tpe.dealias.typeSymbol + val firstParentTpe = parents1.head.tpe.dealias + val firstParent = firstParentTpe.typeSymbol checkEnumParent(cls, firstParent) @@ -2122,7 +2122,7 @@ class Typer extends Namer .withType(dummy.termRef) if (!cls.isOneOf(AbstractOrTrait) && !ctx.isAfterTyper) checkRealizableBounds(cls, cdef.sourcePos.withSpan(cdef.nameSpan)) - if cls.derivesFrom(defn.EnumClass) then + if cls.isEnum || firstParentTpe.classSymbol.isEnum then checkEnum(cdef, cls, firstParent) val cdef1 = assignType(cpy.TypeDef(cdef)(name, impl1), cls) diff --git a/library/src-bootstrapped/scala/Enum.scala b/library/src-bootstrapped/scala/Enum.scala index ff713f90fe11..b0b2b95ace66 100644 --- a/library/src-bootstrapped/scala/Enum.scala +++ b/library/src-bootstrapped/scala/Enum.scala @@ -1,6 +1,7 @@ package scala -/** A base trait of all enum classes */ +/** A Product that also describes a label and ordinal */ +@deprecated("scala.Enum is no longer supported", "3.0.0-M1") trait Enum extends Product, Serializable: /** A string uniquely identifying a case of an enum */ diff --git a/library/src-non-bootstrapped/scala/Enum.scala b/library/src-non-bootstrapped/scala/Enum.scala index ce21eb12cd08..ff713f90fe11 100644 --- a/library/src-non-bootstrapped/scala/Enum.scala +++ b/library/src-non-bootstrapped/scala/Enum.scala @@ -3,5 +3,8 @@ package scala /** A base trait of all enum classes */ trait Enum extends Product, Serializable: + /** A string uniquely identifying a case of an enum */ + def enumLabel: String + /** A number uniquely identifying a case of an enum */ def ordinal: Int diff --git a/library/src-non-bootstrapped/scala/runtime/EnumValueSerializationProxy.java b/library/src-non-bootstrapped/scala/runtime/EnumValueSerializationProxy.java deleted file mode 100644 index 206a48f2b770..000000000000 --- a/library/src-non-bootstrapped/scala/runtime/EnumValueSerializationProxy.java +++ /dev/null @@ -1,36 +0,0 @@ -package scala.runtime; - -import java.io.Serializable; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; - -/** A serialization proxy for singleton enum values, based on `scala.runtime.ModuleSerializationProxy` */ -public final class EnumValueSerializationProxy implements Serializable { - private static final long serialVersionUID = 1L; - private final Class enumClass; - private final int ordinal; - private static final ClassValue enumValues = new ClassValue() { - @Override - protected Object[] computeValue(Class type) { - try { - return AccessController.doPrivileged((PrivilegedExceptionAction) () -> - (Object[])type.getMethod("values").invoke(null)); - } catch (PrivilegedActionException e) { - Throwable cause = e.getCause(); - if (cause instanceof RuntimeException) throw (RuntimeException) cause; - else throw new RuntimeException(cause); - } - } - }; - - public EnumValueSerializationProxy(Class enumClass, int ordinal) { - this.enumClass = enumClass; - this.ordinal = ordinal; - } - - @SuppressWarnings("unused") - private Object readResolve() { - return enumValues.get(enumClass)[ordinal]; - } -} diff --git a/library/src-non-bootstrapped/scala/runtime/EnumValues.scala b/library/src-non-bootstrapped/scala/runtime/EnumValues.scala deleted file mode 100644 index b3f960b7f604..000000000000 --- a/library/src-non-bootstrapped/scala/runtime/EnumValues.scala +++ /dev/null @@ -1,21 +0,0 @@ -package scala.runtime - -import scala.collection.immutable.TreeMap - -class EnumValues[E <: Enum] { - private[this] var myMap: Map[Int, E] = TreeMap.empty - private[this] var fromNameCache: Map[String, E] = null - - def register(v: E) = { - require(!myMap.contains(v.ordinal)) - myMap = myMap.updated(v.ordinal, v) - fromNameCache = null - } - - def fromInt: Map[Int, E] = myMap - def fromName: Map[String, E] = { - if (fromNameCache == null) fromNameCache = myMap.values.map(v => v.toString -> v).toMap - fromNameCache - } - def values: Iterable[E] = myMap.values -} diff --git a/tests/neg/enumsLabel-overrides.scala b/tests/neg/enumsLabel-overrides.scala new file mode 100644 index 000000000000..4b7036b4785f --- /dev/null +++ b/tests/neg/enumsLabel-overrides.scala @@ -0,0 +1,15 @@ +trait Mixin { def enumLabel: String = "mixin" } + +enum Mixed extends Mixin { + case B // error: overriding method enumLabel in trait Mixin of type => String; +} + +enum MixedAlso { + case C extends MixedAlso with Mixin // error: overriding method enumLabel in trait Mixin of type => String; +} + +trait HasEnumLabel { def enumLabel: String } + +enum MyEnum extends HasEnumLabel { + case D // ok +} diff --git a/tests/neg/enumsLabel-singleimpl.scala b/tests/neg/enumsLabel-singleimpl.scala new file mode 100644 index 000000000000..4dd489ccd337 --- /dev/null +++ b/tests/neg/enumsLabel-singleimpl.scala @@ -0,0 +1,15 @@ +enum Labelled { + + case A + + def enumLabel: String = "nolabel" // error: double definition of method enumLabel: => String + +} + +enum Ordinalled { + + case A + + def ordinal: Int = -1 // error: double definition of method ordinal: => Int + +} diff --git a/tests/neg/enumsLabelDef.scala b/tests/neg/enumsLabelDef.scala deleted file mode 100644 index e7bc10108bb6..000000000000 --- a/tests/neg/enumsLabelDef.scala +++ /dev/null @@ -1,22 +0,0 @@ -enum Labelled { - - case A // error overriding method enumLabel in class Labelled of type => String; - - def enumLabel: String = "nolabel" -} - -trait Mixin { def enumLabel: String = "mixin" } - -enum Mixed extends Mixin { - case B // error overriding method enumLabel in trait Mixin of type => String; -} - -enum MixedAlso { - case C extends MixedAlso with Mixin // error overriding method enumLabel in trait Mixin of type => String; -} - -trait HasEnumLabel { def enumLabel: String } - -enum MyEnum extends HasEnumLabel { - case D // ok -} diff --git a/tests/patmat/i7186.scala b/tests/patmat/i7186.scala index 95c7d4db02c4..d34945bed756 100644 --- a/tests/patmat/i7186.scala +++ b/tests/patmat/i7186.scala @@ -1,5 +1,7 @@ import MIPS._ +import deriving.Mirror.SumOf + object MIPS { type Labels = Label | ControlLabel type Src = Register | Constant @@ -233,8 +235,8 @@ object printMips { def getScopedLabel(s: Scoped): String = "L" + getScopedId(s) - def printEnum[E](e: String => Enum, t: E, code: String) = { - val num = e(t.toString).ordinal + def printEnum[E: SumOf](e: String => E, t: E, code: String) = { + val num = summon[SumOf[E]].ordinal(e(t.toString)) s"$code$num" } } diff --git a/tests/run/generic/Enum.scala b/tests/run/generic/Enum.scala index 3e04786de07d..40ce2983730b 100644 --- a/tests/run/generic/Enum.scala +++ b/tests/run/generic/Enum.scala @@ -22,4 +22,4 @@ object runtime { } def values: Iterable[E] = myMap.values } -} \ No newline at end of file +} diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index 41a2ac13737b..a075c2342092 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -641,7 +641,7 @@ Schema => SemanticDB v4 Uri => Enums.scala Text => empty Language => Scala -Symbols => 183 entries +Symbols => 200 entries Occurrences => 203 entries Symbols: @@ -649,6 +649,8 @@ _empty_/Enums. => final object Enums _empty_/Enums.Coin# => abstract sealed enum class Coin _empty_/Enums.Coin#``(). => primary ctor _empty_/Enums.Coin#``().(value) => param value +_empty_/Enums.Coin#enumLabel(). => abstract method enumLabel +_empty_/Enums.Coin#ordinal(). => abstract method ordinal _empty_/Enums.Coin#value. => val method value _empty_/Enums.Coin. => final object Coin _empty_/Enums.Coin.$fromOrdinal(). => method $fromOrdinal @@ -664,6 +666,8 @@ _empty_/Enums.Coin.valueOf().($name) => param $name _empty_/Enums.Coin.values(). => method values _empty_/Enums.Colour# => abstract sealed enum class Colour _empty_/Enums.Colour#``(). => primary ctor +_empty_/Enums.Colour#enumLabel(). => abstract method enumLabel +_empty_/Enums.Colour#ordinal(). => abstract method ordinal _empty_/Enums.Colour. => final object Colour _empty_/Enums.Colour.$fromOrdinal(). => method $fromOrdinal _empty_/Enums.Colour.$fromOrdinal().(_$ordinal) => param _$ordinal @@ -679,6 +683,8 @@ _empty_/Enums.Colour.valueOf().($name) => param $name _empty_/Enums.Colour.values(). => method values _empty_/Enums.Directions# => abstract sealed enum class Directions _empty_/Enums.Directions#``(). => primary ctor +_empty_/Enums.Directions#enumLabel(). => abstract method enumLabel +_empty_/Enums.Directions#ordinal(). => abstract method ordinal _empty_/Enums.Directions. => final object Directions _empty_/Enums.Directions.$fromOrdinal(). => method $fromOrdinal _empty_/Enums.Directions.$fromOrdinal().(_$ordinal) => param _$ordinal @@ -696,6 +702,8 @@ _empty_/Enums.Directions.values(). => method values _empty_/Enums.Maybe# => abstract sealed enum class Maybe _empty_/Enums.Maybe#[A] => covariant typeparam A _empty_/Enums.Maybe#``(). => primary ctor +_empty_/Enums.Maybe#enumLabel(). => abstract method enumLabel +_empty_/Enums.Maybe#ordinal(). => abstract method ordinal _empty_/Enums.Maybe. => final object Maybe _empty_/Enums.Maybe.$fromOrdinal(). => method $fromOrdinal _empty_/Enums.Maybe.$fromOrdinal().(_$ordinal) => param _$ordinal @@ -730,6 +738,7 @@ _empty_/Enums.Planet#G. => final val method G _empty_/Enums.Planet#``(). => primary ctor _empty_/Enums.Planet#``().(mass) => param mass _empty_/Enums.Planet#``().(radius) => param radius +_empty_/Enums.Planet#enumLabel(). => abstract method enumLabel _empty_/Enums.Planet#mass. => val method mass _empty_/Enums.Planet#radius. => val method radius _empty_/Enums.Planet#surfaceGravity(). => method surfaceGravity @@ -750,6 +759,8 @@ _empty_/Enums.Planet.valueOf().($name) => param $name _empty_/Enums.Planet.values(). => method values _empty_/Enums.Suits# => abstract sealed enum class Suits _empty_/Enums.Suits#``(). => primary ctor +_empty_/Enums.Suits#enumLabel(). => abstract method enumLabel +_empty_/Enums.Suits#ordinal(). => abstract method ordinal _empty_/Enums.Suits. => final object Suits _empty_/Enums.Suits.$fromOrdinal(). => method $fromOrdinal _empty_/Enums.Suits.$fromOrdinal().(_$ordinal) => param _$ordinal @@ -772,6 +783,8 @@ _empty_/Enums.Suits.values(). => method values _empty_/Enums.Tag# => abstract sealed enum class Tag _empty_/Enums.Tag#[A] => typeparam A _empty_/Enums.Tag#``(). => primary ctor +_empty_/Enums.Tag#enumLabel(). => abstract method enumLabel +_empty_/Enums.Tag#ordinal(). => abstract method ordinal _empty_/Enums.Tag. => final object Tag _empty_/Enums.Tag.$fromOrdinal(). => method $fromOrdinal _empty_/Enums.Tag.$fromOrdinal().(_$ordinal) => param _$ordinal @@ -783,6 +796,8 @@ _empty_/Enums.Tag.valueOf().($name) => param $name _empty_/Enums.Tag.values(). => method values _empty_/Enums.WeekDays# => abstract sealed enum class WeekDays _empty_/Enums.WeekDays#``(). => primary ctor +_empty_/Enums.WeekDays#enumLabel(). => abstract method enumLabel +_empty_/Enums.WeekDays#ordinal(). => abstract method ordinal _empty_/Enums.WeekDays. => final object WeekDays _empty_/Enums.WeekDays.$fromOrdinal(). => method $fromOrdinal _empty_/Enums.WeekDays.$fromOrdinal().(_$ordinal) => param _$ordinal @@ -804,6 +819,8 @@ _empty_/Enums.`<:<`# => abstract sealed enum class <:< _empty_/Enums.`<:<`#[A] => contravariant typeparam A _empty_/Enums.`<:<`#[B] => typeparam B _empty_/Enums.`<:<`#``(). => primary ctor +_empty_/Enums.`<:<`#enumLabel(). => abstract method enumLabel +_empty_/Enums.`<:<`#ordinal(). => abstract method ordinal _empty_/Enums.`<:<`. => final object <:< _empty_/Enums.`<:<`.Refl# => final case enum class Refl _empty_/Enums.`<:<`.Refl#[C] => typeparam C