@@ -333,27 +333,24 @@ object desugar {
333333 lazy val creatorExpr = New (classTypeRef, constrVparamss nestedMap refOfDef)
334334
335335 // Methods to add to a case class C[..](p1: T1, ..., pN: Tn)(moreParams)
336- // def productArity = N
337- // def productElement(i: Int): Any = i match { ... }
338336 // def _1 = this.p1
339337 // ...
340338 // def _N = this.pN
341339 // def copy(p1: T1 = p1: @uncheckedVariance, ...,
342340 // pN: TN = pN: @uncheckedVariance)(moreParams) =
343341 // new C[...](p1, ..., pN)(moreParams)
344342 //
343+ // Above arity 22 we also synthesize:
344+ // def productArity = N
345+ // def productElement(i: Int): Any = i match { ... }
346+ //
345347 // Note: copy default parameters need @uncheckedVariance; see
346348 // neg/t1843-variances.scala for a test case. The test would give
347349 // two errors without @uncheckedVariance, one of them spurious.
348350 val caseClassMeths = {
349351 def syntheticProperty (name : TermName , rhs : Tree ) =
350352 DefDef (name, Nil , Nil , TypeTree (), rhs).withMods(synthetic)
351- // The override here is less than ideal: user defined productArity / productElement
352- // methods would be silently ignored. This is necessary to compile `scala.TupleN`.
353- // The long term solution is to remove `ProductN` entirely from stdlib.
354- def productArity =
355- DefDef (nme.productArity, Nil , Nil , TypeTree (), Literal (Constant (arity)))
356- .withMods(Modifiers (Synthetic | Override ))
353+ def productArity = syntheticProperty(nme.productArity, Literal (Constant (arity)))
357354 def productElement = {
358355 val param = makeSyntheticParameter(tpt = ref(defn.IntType ))
359356 // case N => _${N + 1}
@@ -366,7 +363,7 @@ object desugar {
366363 val defaultCase = CaseDef (untpd.Ident (nme.WILDCARD ), EmptyTree , error)
367364 val body = Match (refOfDef(param), (cases :+ defaultCase).toList)
368365 DefDef (nme.productElement, Nil , List (List (param)), TypeTree (defn.AnyType ), body)
369- .withMods(Modifiers ( Synthetic | Override ) )
366+ .withMods(synthetic )
370367 }
371368 def productElemMeths = {
372369 val caseParams = constrVparamss.head.toArray
@@ -396,18 +393,31 @@ object desugar {
396393 }
397394 }
398395
396+ // Above MaxTupleArity we extend Product instead of ProductN, in this
397+ // case we need to synthesise productElement & productArity.
398+ def largeProductMeths =
399+ if (arity > Definitions .MaxTupleArity ) List (productElement, productArity)
400+ else Nil
401+
399402 if (isCaseClass)
400- productElement :: productArity :: copyMeths ::: productElemMeths.toList
401- else if (isCaseObject)
402- productElement :: productArity :: Nil
403+ largeProductMeths ::: copyMeths ::: productElemMeths.toList
403404 else Nil
404405 }
405406
406407 def anyRef = ref(defn.AnyRefAlias .typeRef)
408+ def productConstr (n : Int ) = {
409+ val tycon = scalaDot((tpnme.Product .toString + n).toTypeName)
410+ val targs = constrVparamss.head map (_.tpt)
411+ if (targs.isEmpty) tycon else AppliedTypeTree (tycon, targs)
412+ }
413+ def product =
414+ if (arity > Definitions .MaxTupleArity ) scalaDot(nme.Product .toTypeName)
415+ else productConstr(arity)
407416
408- // Case classes and case objects get NameBasedPattern and Product parents
417+ // Case classes and case objects get NameBasedPattern and Product/ProductN parents
409418 val parents1 : List [Tree ] =
410- if (mods.is(Case )) parents :+ scalaDot(nme.Product .toTypeName) :+ scalaDot(nme.NameBasedPattern .toTypeName)
419+ if (mods.is(Case ))
420+ parents :+ product :+ scalaDot(nme.NameBasedPattern .toTypeName)
411421 else parents
412422
413423 // The thicket which is the desugared version of the companion object
0 commit comments