@@ -62,7 +62,8 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
6262 if (myValueSymbols.isEmpty) {
6363 myValueSymbols = List (defn.Any_hashCode , defn.Any_equals )
6464 myCaseSymbols = myValueSymbols ++ List (defn.Any_toString , defn.Product_canEqual ,
65- defn.Product_productArity , defn.Product_productPrefix , defn.Product_productElement )
65+ defn.Product_productArity , defn.Product_productPrefix , defn.Product_productElement ,
66+ defn.Product_productElementName )
6667 myCaseModuleSymbols = myCaseSymbols.filter(_ ne defn.Any_equals )
6768 myEnumCaseSymbols = List (defn.Enum_ordinal )
6869 }
@@ -126,6 +127,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
126127 case nme.productArity => Literal (Constant (accessors.length))
127128 case nme.productPrefix => ownName
128129 case nme.productElement => productElementBody(accessors.length, vrefss.head.head)
130+ case nme.productElementName => productElementNameBody(accessors.length, vrefss.head.head)
129131 case nme.ordinal => Select (This (clazz), nme.ordinalDollar)
130132 }
131133 ctx.log(s " adding $synthetic to $clazz at ${ctx.phase}" )
@@ -149,6 +151,40 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
149151 * ```
150152 */
151153 def productElementBody (arity : Int , index : Tree )(implicit ctx : Context ): Tree = {
154+ // case N => _${N + 1}
155+ val cases = 0 .until(arity).map { i =>
156+ CaseDef (Literal (Constant (i)), EmptyTree , Select (This (clazz), nme.selectorName(i)))
157+ }
158+
159+ Match (index, (cases :+ generateIOBECase(index)).toList)
160+ }
161+
162+ /** The class
163+ *
164+ * ```
165+ * case class C(x: T, y: T)
166+ * ```
167+ *
168+ * gets the `productElementName` method:
169+ *
170+ * ```
171+ * def productElementName(index: Int): String = index match {
172+ * case 0 => "x"
173+ * case 1 => "y"
174+ * case _ => throw new IndexOutOfBoundsException(index.toString)
175+ * }
176+ * ```
177+ */
178+ def productElementNameBody (arity : Int , index : Tree )(implicit ctx : Context ): Tree = {
179+ // case N => // name for case arg N
180+ val cases = 0 .until(arity).map { i =>
181+ CaseDef (Literal (Constant (i)), EmptyTree , Literal (Constant (accessors(i).name.toString)))
182+ }
183+
184+ Match (index, (cases :+ generateIOBECase(index)).toList)
185+ }
186+
187+ def generateIOBECase (index : Tree ): CaseDef = {
152188 val ioob = defn.IndexOutOfBoundsException .typeRef
153189 // Second constructor of ioob that takes a String argument
154190 def filterStringConstructor (s : Symbol ): Boolean = s.info match {
@@ -160,14 +196,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
160196 val error = Throw (New (ioob, constructor, List (stringIndex)))
161197
162198 // case _ => throw new IndexOutOfBoundsException(i.toString)
163- val defaultCase = CaseDef (Underscore (defn.IntType ), EmptyTree , error)
164-
165- // case N => _${N + 1}
166- val cases = 0 .until(arity).map { i =>
167- CaseDef (Literal (Constant (i)), EmptyTree , Select (This (clazz), nme.selectorName(i)))
168- }
169-
170- Match (index, (cases :+ defaultCase).toList)
199+ CaseDef (Underscore (defn.IntType ), EmptyTree , error)
171200 }
172201
173202 /** The class
0 commit comments