@@ -281,34 +281,16 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
281
281
282
282
private def productMirror (mirroredType : Type , formal : Type , span : Span )(using Context ): TreeWithErrors =
283
283
284
- var isSafeGenericTuple = Option .empty[(Symbol , List [Type ])]
285
-
286
- /** do all parts match the class symbol? Or can we extract a generic tuple type out? */
287
- def acceptable (tp : Type , cls : Symbol ): Boolean =
288
- var genericTupleParts = List .empty[(Symbol , List [Type ])]
289
-
290
- def acceptableGenericTuple (tp : AppliedType ): Boolean =
291
- val tupleArgs = tp.tupleElementTypes
292
- val arity = tupleArgs.size
293
- val isOk = arity <= Definitions .MaxTupleArity
294
- if isOk then
295
- genericTupleParts ::= {
296
- val cls = defn.TupleType (arity).nn.classSymbol
297
- (cls, tupleArgs)
298
- }
299
- isOk
300
-
301
- def inner (tp : Type , cls : Symbol ): Boolean = tp match
302
- case tp : HKTypeLambda if tp.resultType.isInstanceOf [HKTypeLambda ] => false
303
- case tp @ AppliedType (cons : TypeRef , _) if cons.isRef(defn.PairClass ) => acceptableGenericTuple(tp)
304
- case tp : TypeProxy => inner(tp.underlying, cls)
305
- case OrType (tp1, tp2) => inner(tp1, cls) && inner(tp2, cls)
306
- case _ => tp.classSymbol eq cls
284
+ extension (clsOrTuple : ClassOrTuple ) def isGenericProd (using Context ) =
285
+ clsOrTuple.isGenericTuple || clsOrTuple.asClass.isGenericProduct && canAccessCtor(clsOrTuple.asClass)
307
286
308
- val classPartsMatch = inner(tp, cls)
309
- classPartsMatch && genericTupleParts.map((cls, _) => cls).distinct.sizeIs <= 1 &&
310
- { isSafeGenericTuple = genericTupleParts.headOption ; true }
311
- end acceptable
287
+ /** do all parts match the class symbol? */
288
+ def acceptable (tp : Type , clsOrTuple : ClassOrTuple ): Boolean = tp match
289
+ case tp : HKTypeLambda if tp.resultType.isInstanceOf [HKTypeLambda ] => false
290
+ case OrType (tp1, tp2) => acceptable(tp1, clsOrTuple) && acceptable(tp2, clsOrTuple)
291
+ case GenericTupleType (args) => args.size <= Definitions .MaxTupleArity
292
+ case tp : TypeProxy => acceptable(tp.underlying, clsOrTuple)
293
+ case _ => tp.underlyingClassOrTuple.asClass eq clsOrTuple.asClass
312
294
313
295
/** for a case class, if it will have an anonymous mirror,
314
296
* check that its constructor can be accessed
@@ -326,13 +308,13 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
326
308
def genAnonyousMirror (cls : Symbol ): Boolean =
327
309
cls.is(Scala2x ) || cls.linkedClass.is(Case )
328
310
329
- def makeProductMirror (cls : Symbol ): TreeWithErrors =
330
- val mirroredClass = isSafeGenericTuple.fold(cls)((cls, _) => cls)
311
+ def makeProductMirror (clsOrTuple : ClassOrTuple ): TreeWithErrors =
312
+ val mirroredClass = clsOrTuple.asClass
331
313
val accessors = mirroredClass.caseAccessors.filterNot(_.isAllOf(PrivateLocal ))
332
314
val elemLabels = accessors.map(acc => ConstantType (Constant (acc.name.toString)))
333
- val nestedPairs = isSafeGenericTuple.map((_, tps) => TypeOps .nestedPairs(tps)).getOrElse {
334
- TypeOps .nestedPairs(accessors.map(mirroredType.resultType.memberInfo(_).widenExpr) )
335
- }
315
+ val nestedPairs = clsOrTuple match
316
+ case ClassOrTuple . GenericTuple (_, args) => TypeOps .nestedPairs(args )
317
+ case _ => TypeOps .nestedPairs(accessors.map(mirroredType.resultType.memberInfo(_).widenExpr))
336
318
val (monoType, elemsType) = mirroredType match
337
319
case mirroredType : HKTypeLambda =>
338
320
(mkMirroredMonoType(mirroredType), mirroredType.derivedLambdaType(resType = nestedPairs))
@@ -342,25 +324,30 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
342
324
checkRefinement(formal, tpnme.MirroredElemTypes , elemsType, span)
343
325
checkRefinement(formal, tpnme.MirroredElemLabels , elemsLabels, span)
344
326
val mirrorType =
345
- mirrorCore(defn.Mirror_ProductClass , monoType, mirroredType, cls .name, formal)
327
+ mirrorCore(defn.Mirror_ProductClass , monoType, mirroredType, mirroredClass .name, formal)
346
328
.refinedWith(tpnme.MirroredElemTypes , TypeAlias (elemsType))
347
329
.refinedWith(tpnme.MirroredElemLabels , TypeAlias (elemsLabels))
348
330
val mirrorRef =
349
331
if genAnonyousMirror(mirroredClass) then
350
- anonymousMirror(monoType, ExtendsProductMirror , isSafeGenericTuple.map(_(1 ).size), span)
332
+ val arity = clsOrTuple match
333
+ case ClassOrTuple .GenericTuple (arity, _) => Some (arity)
334
+ case _ => None
335
+ anonymousMirror(monoType, ExtendsProductMirror , arity, span)
351
336
else companionPath(mirroredType, span)
352
337
withNoErrors(mirrorRef.cast(mirrorType))
353
338
end makeProductMirror
354
339
355
- def getError (cls : Symbol ): String =
340
+ def getError (clsOrTuple : ClassOrTuple ): String =
356
341
val reason =
357
- if ! cls.isGenericProduct then
358
- i " because ${cls.whyNotGenericProduct}"
359
- else if ! canAccessCtor(cls) then
360
- i " because the constructor of $cls is innaccessible from the calling scope. "
342
+ if ! clsOrTuple.isGenericTuple then
343
+ if ! clsOrTuple.asClass.isGenericProduct then
344
+ i " because ${clsOrTuple.asClass.whyNotGenericProduct}"
345
+ else if ! canAccessCtor(clsOrTuple.asClass) then
346
+ i " because the constructor of ${clsOrTuple.asClass} is innaccessible from the calling scope. "
347
+ else " "
361
348
else
362
349
" "
363
- i " $cls is not a generic product $reason"
350
+ i " ${clsOrTuple.asClass} is not a generic product $reason"
364
351
end getError
365
352
366
353
mirroredType match
@@ -378,13 +365,11 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
378
365
val mirrorType = mirrorCore(defn.Mirror_SingletonClass , mirroredType, mirroredType, module.name, formal)
379
366
withNoErrors(modulePath.cast(mirrorType))
380
367
else
381
- val cls = mirroredType.classSymbol
382
- if acceptable(mirroredType, cls)
383
- && isSafeGenericTuple.isDefined || (cls.isGenericProduct && canAccessCtor(cls))
384
- then
385
- makeProductMirror(cls)
368
+ val clsOrTuple = mirroredType.underlyingClassOrTuple
369
+ if acceptable(mirroredType, clsOrTuple) && clsOrTuple.isGenericProd then
370
+ makeProductMirror(clsOrTuple)
386
371
else
387
- (EmptyTree , List (getError(cls )))
372
+ (EmptyTree , List (getError(clsOrTuple )))
388
373
end productMirror
389
374
390
375
private def sumMirror (mirroredType : Type , formal : Type , span : Span )(using Context ): TreeWithErrors =
0 commit comments