@@ -281,34 +281,17 @@ 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) if args.size <= Definitions .MaxTupleArity =>
292
+ ClassOrTuple .tuple(args).equiv(clsOrTuple)
293
+ case tp : TypeProxy => acceptable(tp.underlying, clsOrTuple)
294
+ case _ => tp.underlyingClassOrTuple.equiv(clsOrTuple)
312
295
313
296
/** for a case class, if it will have an anonymous mirror,
314
297
* check that its constructor can be accessed
@@ -326,13 +309,13 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
326
309
def genAnonyousMirror (cls : Symbol ): Boolean =
327
310
cls.is(Scala2x ) || cls.linkedClass.is(Case )
328
311
329
- def makeProductMirror (cls : Symbol ): TreeWithErrors =
330
- val mirroredClass = isSafeGenericTuple.fold(cls)((cls, _) => cls)
312
+ def makeProductMirror (clsOrTuple : ClassOrTuple ): TreeWithErrors =
313
+ val mirroredClass = clsOrTuple.asClass
331
314
val accessors = mirroredClass.caseAccessors.filterNot(_.isAllOf(PrivateLocal ))
332
315
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
- }
316
+ val nestedPairs = clsOrTuple match
317
+ case ClassOrTuple . GenericTuple (_, args) => TypeOps .nestedPairs(args )
318
+ case _ => TypeOps .nestedPairs(accessors.map(mirroredType.resultType.memberInfo(_).widenExpr))
336
319
val (monoType, elemsType) = mirroredType match
337
320
case mirroredType : HKTypeLambda =>
338
321
(mkMirroredMonoType(mirroredType), mirroredType.derivedLambdaType(resType = nestedPairs))
@@ -342,25 +325,30 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
342
325
checkRefinement(formal, tpnme.MirroredElemTypes , elemsType, span)
343
326
checkRefinement(formal, tpnme.MirroredElemLabels , elemsLabels, span)
344
327
val mirrorType =
345
- mirrorCore(defn.Mirror_ProductClass , monoType, mirroredType, cls .name, formal)
328
+ mirrorCore(defn.Mirror_ProductClass , monoType, mirroredType, mirroredClass .name, formal)
346
329
.refinedWith(tpnme.MirroredElemTypes , TypeAlias (elemsType))
347
330
.refinedWith(tpnme.MirroredElemLabels , TypeAlias (elemsLabels))
348
331
val mirrorRef =
349
332
if genAnonyousMirror(mirroredClass) then
350
- anonymousMirror(monoType, ExtendsProductMirror , isSafeGenericTuple.map(_(1 ).size), span)
333
+ val arity = clsOrTuple match
334
+ case ClassOrTuple .GenericTuple (arity, _) => Some (arity)
335
+ case _ => None
336
+ anonymousMirror(monoType, ExtendsProductMirror , arity, span)
351
337
else companionPath(mirroredType, span)
352
338
withNoErrors(mirrorRef.cast(mirrorType))
353
339
end makeProductMirror
354
340
355
- def getError (cls : Symbol ): String =
341
+ def getError (clsOrTuple : ClassOrTuple ): String =
356
342
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. "
343
+ if ! clsOrTuple.isGenericTuple then
344
+ if ! clsOrTuple.asClass.isGenericProduct then
345
+ i " because ${clsOrTuple.asClass.whyNotGenericProduct}"
346
+ else if ! canAccessCtor(clsOrTuple.asClass) then
347
+ i " because the constructor of ${clsOrTuple.asClass} is innaccessible from the calling scope. "
348
+ else " "
361
349
else
362
350
" "
363
- i " $cls is not a generic product $reason"
351
+ i " ${clsOrTuple.asClass} is not a generic product $reason"
364
352
end getError
365
353
366
354
mirroredType match
@@ -378,13 +366,11 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
378
366
val mirrorType = mirrorCore(defn.Mirror_SingletonClass , mirroredType, mirroredType, module.name, formal)
379
367
withNoErrors(modulePath.cast(mirrorType))
380
368
else
381
- val cls = mirroredType.classSymbol
382
- if acceptable(mirroredType, cls)
383
- && isSafeGenericTuple.isDefined || (cls.isGenericProduct && canAccessCtor(cls))
384
- then
385
- makeProductMirror(cls)
369
+ val clsOrTuple = mirroredType.underlyingClassOrTuple
370
+ if acceptable(mirroredType, clsOrTuple) && clsOrTuple.isGenericProd then
371
+ makeProductMirror(clsOrTuple)
386
372
else
387
- (EmptyTree , List (getError(cls )))
373
+ (EmptyTree , List (getError(clsOrTuple )))
388
374
end productMirror
389
375
390
376
private def sumMirror (mirroredType : Type , formal : Type , span : Span )(using Context ): TreeWithErrors =
0 commit comments