@@ -281,34 +281,16 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
281281
282282 private def productMirror (mirroredType : Type , formal : Type , span : Span )(using Context ): TreeWithErrors =
283283
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)
307286
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
312294
313295 /** for a case class, if it will have an anonymous mirror,
314296 * check that its constructor can be accessed
@@ -326,13 +308,13 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
326308 def genAnonyousMirror (cls : Symbol ): Boolean =
327309 cls.is(Scala2x ) || cls.linkedClass.is(Case )
328310
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
331313 val accessors = mirroredClass.caseAccessors.filterNot(_.isAllOf(PrivateLocal ))
332314 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))
336318 val (monoType, elemsType) = mirroredType match
337319 case mirroredType : HKTypeLambda =>
338320 (mkMirroredMonoType(mirroredType), mirroredType.derivedLambdaType(resType = nestedPairs))
@@ -342,25 +324,30 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
342324 checkRefinement(formal, tpnme.MirroredElemTypes , elemsType, span)
343325 checkRefinement(formal, tpnme.MirroredElemLabels , elemsLabels, span)
344326 val mirrorType =
345- mirrorCore(defn.Mirror_ProductClass , monoType, mirroredType, cls .name, formal)
327+ mirrorCore(defn.Mirror_ProductClass , monoType, mirroredType, mirroredClass .name, formal)
346328 .refinedWith(tpnme.MirroredElemTypes , TypeAlias (elemsType))
347329 .refinedWith(tpnme.MirroredElemLabels , TypeAlias (elemsLabels))
348330 val mirrorRef =
349331 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)
351336 else companionPath(mirroredType, span)
352337 withNoErrors(mirrorRef.cast(mirrorType))
353338 end makeProductMirror
354339
355- def getError (cls : Symbol ): String =
340+ def getError (clsOrTuple : ClassOrTuple ): String =
356341 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 " "
361348 else
362349 " "
363- i " $cls is not a generic product $reason"
350+ i " ${clsOrTuple.asClass} is not a generic product $reason"
364351 end getError
365352
366353 mirroredType match
@@ -378,13 +365,11 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
378365 val mirrorType = mirrorCore(defn.Mirror_SingletonClass , mirroredType, mirroredType, module.name, formal)
379366 withNoErrors(modulePath.cast(mirrorType))
380367 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)
386371 else
387- (EmptyTree , List (getError(cls )))
372+ (EmptyTree , List (getError(clsOrTuple )))
388373 end productMirror
389374
390375 private def sumMirror (mirroredType : Type , formal : Type , span : Span )(using Context ): TreeWithErrors =
0 commit comments