@@ -333,27 +333,24 @@ object desugar {
333
333
lazy val creatorExpr = New (classTypeRef, constrVparamss nestedMap refOfDef)
334
334
335
335
// 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 { ... }
338
336
// def _1 = this.p1
339
337
// ...
340
338
// def _N = this.pN
341
339
// def copy(p1: T1 = p1: @uncheckedVariance, ...,
342
340
// pN: TN = pN: @uncheckedVariance)(moreParams) =
343
341
// new C[...](p1, ..., pN)(moreParams)
344
342
//
343
+ // Above arity 22 we also synthesize:
344
+ // def productArity = N
345
+ // def productElement(i: Int): Any = i match { ... }
346
+ //
345
347
// Note: copy default parameters need @uncheckedVariance; see
346
348
// neg/t1843-variances.scala for a test case. The test would give
347
349
// two errors without @uncheckedVariance, one of them spurious.
348
350
val caseClassMeths = {
349
351
def syntheticProperty (name : TermName , rhs : Tree ) =
350
352
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)))
357
354
def productElement = {
358
355
val param = makeSyntheticParameter(tpt = ref(defn.IntType ))
359
356
// case N => _${N + 1}
@@ -366,7 +363,7 @@ object desugar {
366
363
val defaultCase = CaseDef (untpd.Ident (nme.WILDCARD ), EmptyTree , error)
367
364
val body = Match (refOfDef(param), (cases :+ defaultCase).toList)
368
365
DefDef (nme.productElement, Nil , List (List (param)), TypeTree (defn.AnyType ), body)
369
- .withMods(Modifiers ( Synthetic | Override ) )
366
+ .withMods(synthetic )
370
367
}
371
368
def productElemMeths = {
372
369
val caseParams = constrVparamss.head.toArray
@@ -396,18 +393,31 @@ object desugar {
396
393
}
397
394
}
398
395
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
+
399
402
if (isCaseClass)
400
- productElement :: productArity :: copyMeths ::: productElemMeths.toList
401
- else if (isCaseObject)
402
- productElement :: productArity :: Nil
403
+ largeProductMeths ::: copyMeths ::: productElemMeths.toList
403
404
else Nil
404
405
}
405
406
406
407
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)
407
416
408
- // Case classes and case objects get NameBasedPattern and Product parents
417
+ // Case classes and case objects get NameBasedPattern and Product/ProductN parents
409
418
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)
411
421
else parents
412
422
413
423
// The thicket which is the desugared version of the companion object
0 commit comments