Skip to content

Commit 2a1ea2d

Browse files
committed
Do not generate _N members for case classes in stdlib-bootstrapped
1 parent 9547198 commit 2a1ea2d

File tree

2 files changed

+52
-19
lines changed

2 files changed

+52
-19
lines changed

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

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -667,18 +667,20 @@ object desugar {
667667
DefDef(name, Nil, tpt, rhs).withMods(synthetic)
668668

669669
def productElemMeths =
670-
val caseParams = derivedVparamss.head.toArray
671-
val selectorNamesInBody = normalizedBody.collect {
672-
case vdef: ValDef if vdef.name.isSelectorName =>
673-
vdef.name
674-
case ddef: DefDef if ddef.name.isSelectorName && ddef.paramss.isEmpty =>
675-
ddef.name
676-
}
677-
for i <- List.range(0, arity)
678-
selName = nme.selectorName(i)
679-
if (selName ne caseParams(i).name) && !selectorNamesInBody.contains(selName)
680-
yield syntheticProperty(selName, caseParams(i).tpt,
681-
Select(This(EmptyTypeIdent), caseParams(i).name))
670+
if caseClassInScala2StdLib then Nil
671+
else
672+
val caseParams = derivedVparamss.head.toArray
673+
val selectorNamesInBody = normalizedBody.collect {
674+
case vdef: ValDef if vdef.name.isSelectorName =>
675+
vdef.name
676+
case ddef: DefDef if ddef.name.isSelectorName && ddef.paramss.isEmpty =>
677+
ddef.name
678+
}
679+
for i <- List.range(0, arity)
680+
selName = nme.selectorName(i)
681+
if (selName ne caseParams(i).name) && !selectorNamesInBody.contains(selName)
682+
yield syntheticProperty(selName, caseParams(i).tpt,
683+
Select(This(EmptyTypeIdent), caseParams(i).name))
682684

683685
def enumCaseMeths =
684686
if isEnumCase then
@@ -768,11 +770,13 @@ object desugar {
768770
val unapplyMeth = {
769771
def scala2LibCompatUnapplyRhs(unapplyParamName: Name) =
770772
assert(arity <= Definitions.MaxTupleArity, "Unexpected case class with tuple larger than 22: "+ cdef.show)
771-
if arity == 1 then Apply(scalaDot(nme.Option), Select(Ident(unapplyParamName), nme._1))
772-
else
773-
val tupleApply = Select(Ident(nme.scala), s"Tuple$arity".toTermName)
774-
val members = List.tabulate(arity) { n => Select(Ident(unapplyParamName), s"_${n+1}".toTermName) }
775-
Apply(scalaDot(nme.Option), Apply(tupleApply, members))
773+
derivedVparamss.head match
774+
case vparam :: Nil =>
775+
Apply(scalaDot(nme.Option), Select(Ident(unapplyParamName), vparam.name))
776+
case vparams =>
777+
val tupleApply = Select(Ident(nme.scala), s"Tuple$arity".toTermName)
778+
val members = vparams.map(vparam => Select(Ident(unapplyParamName), vparam.name))
779+
Apply(scalaDot(nme.Option), Apply(tupleApply, members))
776780

777781
val hasRepeatedParam = constrVparamss.head.exists {
778782
case ValDef(_, tpt, _) => isRepeated(tpt)

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

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
161161
case nme.productArity => Literal(Constant(accessors.length))
162162
case nme.productPrefix if isEnumValue => nameRef
163163
case nme.productPrefix => ownName
164-
case nme.productElement => productElementBody(accessors.length, vrefss.head.head)
164+
case nme.productElement =>
165+
if ctx.settings.Yscala2Stdlib.value then productElementBodyForScala2Compat(accessors.length, vrefss.head.head)
166+
else productElementBody(accessors.length, vrefss.head.head)
165167
case nme.productElementName => productElementNameBody(accessors.length, vrefss.head.head)
166168
}
167169
report.log(s"adding $synthetic to $clazz at ${ctx.phase}")
@@ -185,7 +187,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
185187
* ```
186188
*/
187189
def productElementBody(arity: Int, index: Tree)(using Context): Tree = {
188-
// case N => _${N + 1}
190+
// case N => this._${N + 1}
189191
val cases = 0.until(arity).map { i =>
190192
val sel = This(clazz).select(nme.selectorName(i), _.info.isParameterless)
191193
CaseDef(Literal(Constant(i)), EmptyTree, sel)
@@ -194,6 +196,33 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
194196
Match(index, (cases :+ generateIOBECase(index)).toList)
195197
}
196198

199+
/** The class
200+
*
201+
* ```
202+
* case class C(x: T, y: T)
203+
* ```
204+
*
205+
* gets the `productElement` method:
206+
*
207+
* ```
208+
* def productElement(index: Int): Any = index match {
209+
* case 0 => this.x
210+
* case 1 => this.y
211+
* case _ => throw new IndexOutOfBoundsException(index.toString)
212+
* }
213+
* ```
214+
*/
215+
def productElementBodyForScala2Compat(arity: Int, index: Tree)(using Context): Tree = {
216+
val paramNames = ctx.owner.owner.info.decls.toList.filter(_.flags.is(ParamAccessor)).map(_.name)
217+
// case N => this.${paramNames(N)}
218+
val cases = paramNames.zip(0.until(arity)).map { (name, i) =>
219+
val sel = This(clazz).select(name, _.info.isParameterless)
220+
CaseDef(Literal(Constant(i)), EmptyTree, sel)
221+
}
222+
223+
Match(index, (cases :+ generateIOBECase(index)).toList)
224+
}
225+
197226
/** The class
198227
*
199228
* ```

0 commit comments

Comments
 (0)