@@ -8,7 +8,7 @@ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
8
8
import Decorators ._
9
9
import collection .mutable .ListBuffer
10
10
import util .Property
11
- import reporting . diagnostic . messages ._
11
+ import typer . ErrorReporting ._
12
12
13
13
object DesugarEnums {
14
14
import untpd ._
@@ -56,6 +56,31 @@ object DesugarEnums {
56
56
}
57
57
}
58
58
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
+
59
84
def enumTagMeth (implicit ctx : Context ) =
60
85
DefDef (nme.enumTag, Nil , Nil , TypeTree (),
61
86
Literal (Constant (nextEnumTag(isSimpleCase = false )._1)))
@@ -111,7 +136,12 @@ object DesugarEnums {
111
136
112
137
def expandEnumModule (name : TermName , impl : Template , mods : Modifiers , pos : Position )(implicit ctx : Context ): Tree =
113
138
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
+ }
115
145
else {
116
146
def toStringMeth =
117
147
DefDef (nme.toString_, Nil , Nil , TypeTree (defn.StringType ), Literal (Constant (name.toString)))
@@ -121,13 +151,17 @@ object DesugarEnums {
121
151
ValDef (name, TypeTree (), New (impl1)).withMods(mods | Final ).withPos(pos)
122
152
}
123
153
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
+ }
133
167
}
0 commit comments