@@ -281,34 +281,17 @@ 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) 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)
312295
313296 /** for a case class, if it will have an anonymous mirror,
314297 * check that its constructor can be accessed
@@ -326,13 +309,13 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
326309 def genAnonyousMirror (cls : Symbol ): Boolean =
327310 cls.is(Scala2x ) || cls.linkedClass.is(Case )
328311
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
331314 val accessors = mirroredClass.caseAccessors.filterNot(_.isAllOf(PrivateLocal ))
332315 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))
336319 val (monoType, elemsType) = mirroredType match
337320 case mirroredType : HKTypeLambda =>
338321 (mkMirroredMonoType(mirroredType), mirroredType.derivedLambdaType(resType = nestedPairs))
@@ -342,25 +325,30 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
342325 checkRefinement(formal, tpnme.MirroredElemTypes , elemsType, span)
343326 checkRefinement(formal, tpnme.MirroredElemLabels , elemsLabels, span)
344327 val mirrorType =
345- mirrorCore(defn.Mirror_ProductClass , monoType, mirroredType, cls .name, formal)
328+ mirrorCore(defn.Mirror_ProductClass , monoType, mirroredType, mirroredClass .name, formal)
346329 .refinedWith(tpnme.MirroredElemTypes , TypeAlias (elemsType))
347330 .refinedWith(tpnme.MirroredElemLabels , TypeAlias (elemsLabels))
348331 val mirrorRef =
349332 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)
351337 else companionPath(mirroredType, span)
352338 withNoErrors(mirrorRef.cast(mirrorType))
353339 end makeProductMirror
354340
355- def getError (cls : Symbol ): String =
341+ def getError (clsOrTuple : ClassOrTuple ): String =
356342 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 " "
361349 else
362350 " "
363- i " $cls is not a generic product $reason"
351+ i " ${clsOrTuple.asClass} is not a generic product $reason"
364352 end getError
365353
366354 mirroredType match
@@ -378,13 +366,11 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
378366 val mirrorType = mirrorCore(defn.Mirror_SingletonClass , mirroredType, mirroredType, module.name, formal)
379367 withNoErrors(modulePath.cast(mirrorType))
380368 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)
386372 else
387- (EmptyTree , List (getError(cls )))
373+ (EmptyTree , List (getError(clsOrTuple )))
388374 end productMirror
389375
390376 private def sumMirror (mirroredType : Type , formal : Type , span : Span )(using Context ): TreeWithErrors =
0 commit comments