@@ -8,7 +8,7 @@ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
88import Decorators ._
99import collection .mutable .ListBuffer
1010import util .Property
11- import reporting . diagnostic . messages ._
11+ import typer . ErrorReporting ._
1212
1313object DesugarEnums {
1414 import untpd ._
@@ -56,6 +56,31 @@ object DesugarEnums {
5656 }
5757 }
5858
59+ /** A reference to the enum class `E`, possibly followed by type arguments.
60+ * Each covariant type parameter is approximated by its lower bound.
61+ * Each contravariant type parameter is approximated by its upper bound.
62+ * It is an error if a type parameter is non-variant, or if its approximation
63+ * refers to pther type parameters.
64+ */
65+ def interpolatedEnumParent (pos : Position )(implicit ctx : Context ): Tree = {
66+ val tparams = enumClass.typeParams
67+ def isGround (tp : Type ) = tp.subst(tparams, tparams.map(_ => NoType )) eq tp
68+ val targs = tparams map { tparam =>
69+ if (tparam.variance > 0 && isGround(tparam.info.bounds.lo))
70+ tparam.info.bounds.lo
71+ else if (tparam.variance < 0 && isGround(tparam.info.bounds.hi))
72+ tparam.info.bounds.hi
73+ else {
74+ def problem =
75+ if (tparam.variance == 0 ) " is non variant"
76+ else " has bounds that depend on a type parameter in the same parameter list"
77+ errorType(i """ cannot determine type argument for enum parent $enumClass,
78+ |type parameter $tparam $problem""" , pos)
79+ }
80+ }
81+ TypeTree (enumClass.typeRef.appliedTo(targs)).withPos(pos)
82+ }
83+
5984 def enumTagMeth (implicit ctx : Context ) =
6085 DefDef (nme.enumTag, Nil , Nil , TypeTree (),
6186 Literal (Constant (nextEnumTag(isSimpleCase = false )._1)))
@@ -111,7 +136,12 @@ object DesugarEnums {
111136
112137 def expandEnumModule (name : TermName , impl : Template , mods : Modifiers , pos : Position )(implicit ctx : Context ): Tree =
113138 if (impl.parents.isEmpty)
114- expandSimpleEnumCase(name, mods, pos)
139+ if (impl.body.isEmpty)
140+ expandSimpleEnumCase(name, mods, pos)
141+ else {
142+ val parent = interpolatedEnumParent(pos)
143+ expandEnumModule(name, cpy.Template (impl)(parents = parent :: Nil ), mods, pos)
144+ }
115145 else {
116146 def toStringMeth =
117147 DefDef (nme.toString_, Nil , Nil , TypeTree (defn.StringType ), Literal (Constant (name.toString)))
@@ -121,13 +151,17 @@ object DesugarEnums {
121151 ValDef (name, TypeTree (), New (impl1)).withMods(mods | Final ).withPos(pos)
122152 }
123153
124- def expandSimpleEnumCase (name : TermName , mods : Modifiers , pos : Position )(implicit ctx : Context ): Tree = {
125- if (reconstitutedEnumTypeParams(pos).nonEmpty)
126- ctx.error(i " illegal enum value of generic $enumClass: an explicit `extends' clause is needed " , pos)
127- val (tag, simpleSeen) = nextEnumTag(isSimpleCase = true )
128- val prefix = if (simpleSeen) Nil else enumScaffolding
129- val creator = Apply (Ident (nme.DOLLAR_NEW ), List (Literal (Constant (tag)), Literal (Constant (name.toString))))
130- val vdef = ValDef (name, enumClassRef, creator).withMods(mods | Final ).withPos(pos)
131- flatTree(prefix ::: vdef :: Nil ).withPos(pos.startPos)
132- }
154+ def expandSimpleEnumCase (name : TermName , mods : Modifiers , pos : Position )(implicit ctx : Context ): Tree =
155+ if (reconstitutedEnumTypeParams(pos).nonEmpty) {
156+ val parent = interpolatedEnumParent(pos)
157+ val impl = Template (emptyConstructor, parent :: Nil , EmptyValDef , Nil )
158+ expandEnumModule(name, impl, mods, pos)
159+ }
160+ else {
161+ val (tag, simpleSeen) = nextEnumTag(isSimpleCase = true )
162+ val prefix = if (simpleSeen) Nil else enumScaffolding
163+ val creator = Apply (Ident (nme.DOLLAR_NEW ), List (Literal (Constant (tag)), Literal (Constant (name.toString))))
164+ val vdef = ValDef (name, enumClassRef, creator).withMods(mods | Final ).withPos(pos)
165+ flatTree(prefix ::: vdef :: Nil ).withPos(pos.startPos)
166+ }
133167}
0 commit comments