@@ -275,6 +275,21 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
275
275
monoMap(mirroredType.resultType)
276
276
277
277
private def productMirror (mirroredType : Type , formal : Type , span : Span )(using Context ): Tree =
278
+
279
+ /** for a case class, if it is Scala2x then
280
+ * check if its constructor can be accessed
281
+ * from the calling scope.
282
+ */
283
+ def canAccessCtor (cls : Symbol ): Boolean =
284
+ ! genAnonyousMirror(cls) || {
285
+ val ctor = cls.primaryConstructor
286
+ ! ctor.isOneOf(Private | Protected ) // we will never generate the mirror inside a Scala 2 class
287
+ && (! ctor.privateWithin.exists || ctx.owner.isContainedIn(ctor.privateWithin)) // check scope is compatible
288
+ }
289
+
290
+ def genAnonyousMirror (cls : Symbol ): Boolean =
291
+ cls.is(Scala2x ) || cls.linkedClass.is(Case )
292
+
278
293
mirroredType match
279
294
case AndType (tp1, tp2) =>
280
295
productMirror(tp1, formal, span).orElse(productMirror(tp2, formal, span))
@@ -291,25 +306,27 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
291
306
modulePath.cast(mirrorType)
292
307
else if mirroredType.classSymbol.isGenericProduct then
293
308
val cls = mirroredType.classSymbol
294
- val accessors = cls.caseAccessors.filterNot(_.isAllOf(PrivateLocal ))
295
- val elemLabels = accessors.map(acc => ConstantType (Constant (acc.name.toString)))
296
- val nestedPairs = TypeOps .nestedPairs(accessors.map(mirroredType.resultType.memberInfo(_).widenExpr))
297
- val (monoType, elemsType) = mirroredType match
298
- case mirroredType : HKTypeLambda =>
299
- (mkMirroredMonoType(mirroredType), mirroredType.derivedLambdaType(resType = nestedPairs))
300
- case _ =>
301
- (mirroredType, nestedPairs)
302
- val elemsLabels = TypeOps .nestedPairs(elemLabels)
303
- checkRefinement(formal, tpnme.MirroredElemTypes , elemsType, span)
304
- checkRefinement(formal, tpnme.MirroredElemLabels , elemsLabels, span)
305
- val mirrorType =
306
- mirrorCore(defn.Mirror_ProductClass , monoType, mirroredType, cls.name, formal)
307
- .refinedWith(tpnme.MirroredElemTypes , TypeAlias (elemsType))
308
- .refinedWith(tpnme.MirroredElemLabels , TypeAlias (elemsLabels))
309
- val mirrorRef =
310
- if (cls.is(Scala2x ) || cls.linkedClass.is(Case )) anonymousMirror(monoType, ExtendsProductMirror , span)
311
- else companionPath(mirroredType, span)
312
- mirrorRef.cast(mirrorType)
309
+ if ! canAccessCtor(cls) then EmptyTree
310
+ else
311
+ val accessors = cls.caseAccessors.filterNot(_.isAllOf(PrivateLocal ))
312
+ val elemLabels = accessors.map(acc => ConstantType (Constant (acc.name.toString)))
313
+ val nestedPairs = TypeOps .nestedPairs(accessors.map(mirroredType.resultType.memberInfo(_).widenExpr))
314
+ val (monoType, elemsType) = mirroredType match
315
+ case mirroredType : HKTypeLambda =>
316
+ (mkMirroredMonoType(mirroredType), mirroredType.derivedLambdaType(resType = nestedPairs))
317
+ case _ =>
318
+ (mirroredType, nestedPairs)
319
+ val elemsLabels = TypeOps .nestedPairs(elemLabels)
320
+ checkRefinement(formal, tpnme.MirroredElemTypes , elemsType, span)
321
+ checkRefinement(formal, tpnme.MirroredElemLabels , elemsLabels, span)
322
+ val mirrorType =
323
+ mirrorCore(defn.Mirror_ProductClass , monoType, mirroredType, cls.name, formal)
324
+ .refinedWith(tpnme.MirroredElemTypes , TypeAlias (elemsType))
325
+ .refinedWith(tpnme.MirroredElemLabels , TypeAlias (elemsLabels))
326
+ val mirrorRef =
327
+ if (genAnonyousMirror(cls)) anonymousMirror(monoType, ExtendsProductMirror , span)
328
+ else companionPath(mirroredType, span)
329
+ mirrorRef.cast(mirrorType)
313
330
else EmptyTree
314
331
end productMirror
315
332
0 commit comments