Skip to content

Commit 60d8038

Browse files
committed
check children are also accessible in mirror
1 parent 62abe60 commit 60d8038

File tree

4 files changed

+24
-9
lines changed

4 files changed

+24
-9
lines changed

compiler/src/dotty/tools/dotc/transform/SymUtils.scala

+8-3
Original file line numberDiff line numberDiff line change
@@ -92,17 +92,22 @@ object SymUtils:
9292
* - it has at least one child class or object
9393
* - none of its children are anonymous classes
9494
* - all of its children are addressable through a path from the parent class
95+
* and also the location of the generated mirror.
9596
* - all of its children are generic products or singletons
9697
*/
97-
def whyNotGenericSum(using Context): String =
98+
def whyNotGenericSum(declScope: Symbol)(using Context): String =
9899
if (!self.is(Sealed))
99100
s"it is not a sealed ${self.kindString}"
100101
else {
101102
val children = self.children
103+
val companion = self.linkedClass
104+
val hasCompanion = companion != NoSymbol
105+
assert(!(hasCompanion && (declScope ne companion)))
102106
def problem(child: Symbol) = {
103107

104108
def isAccessible(sym: Symbol): Boolean =
105-
self.isContainedIn(sym) || sym.is(Module) && isAccessible(sym.owner)
109+
(self.isContainedIn(sym) && (hasCompanion || declScope.isContainedIn(sym)))
110+
|| sym.is(Module) && isAccessible(sym.owner)
106111

107112
if (child == self) "it has anonymous or inaccessible subclasses"
108113
else if (!isAccessible(child.owner)) i"its child $child is not accessible"
@@ -117,7 +122,7 @@ object SymUtils:
117122
else children.map(problem).find(!_.isEmpty).getOrElse("")
118123
}
119124

120-
def isGenericSum(using Context): Boolean = whyNotGenericSum.isEmpty
125+
def isGenericSum(declScope: Symbol)(using Context): Boolean = whyNotGenericSum(declScope).isEmpty
121126

122127
/** If this is a constructor, its owner: otherwise this. */
123128
final def skipConstructor(using Context): Symbol =

compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -584,9 +584,9 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
584584
if (clazz.is(Module)) {
585585
if (clazz.is(Case)) makeSingletonMirror()
586586
else if (linked.isGenericProduct) makeProductMirror(linked)
587-
else if (linked.isGenericSum) makeSumMirror(linked)
587+
else if (linked.isGenericSum(clazz)) makeSumMirror(linked)
588588
else if (linked.is(Sealed))
589-
derive.println(i"$linked is not a sum because ${linked.whyNotGenericSum}")
589+
derive.println(i"$linked is not a sum because ${linked.whyNotGenericSum(clazz)}")
590590
}
591591
else if (impl.removeAttachment(ExtendsSingletonMirror).isDefined)
592592
makeSingletonMirror()

compiler/src/dotty/tools/dotc/typer/Synthesizer.scala

+5-4
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,10 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
266266
end productMirror
267267

268268
private def sumMirror(mirroredType: Type, formal: Type, span: Span)(using Context): Tree =
269-
if mirroredType.classSymbol.isGenericSum then
270-
val cls = mirroredType.classSymbol
269+
val cls = mirroredType.classSymbol
270+
val useCompanion = cls.linkedClass.exists && !cls.is(Scala2x)
271+
272+
if cls.isGenericSum(if useCompanion then cls.linkedClass else ctx.owner) then
271273
val elemLabels = cls.children.map(c => ConstantType(Constant(c.name.toString)))
272274

273275
def solve(sym: Symbol): Type = sym match
@@ -318,8 +320,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
318320
.refinedWith(tpnme.MirroredElemTypes, TypeAlias(elemsType))
319321
.refinedWith(tpnme.MirroredElemLabels, TypeAlias(TypeOps.nestedPairs(elemLabels)))
320322
val mirrorRef =
321-
if cls.linkedClass.exists && !cls.is(Scala2x)
322-
then companionPath(mirroredType, span)
323+
if useCompanion then companionPath(mirroredType, span)
323324
else anonymousMirror(monoType, ExtendsSumMirror, span)
324325
mirrorRef.cast(mirrorType)
325326
else EmptyTree

tests/neg/i10997.scala

+9
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,12 @@ trait Wrapper {
77

88
println(summon[deriving.Mirror.Of[Parent]]) // error
99
}
10+
11+
class ClassWrapper {
12+
sealed trait Base
13+
case class Foo(x: Int) extends Base
14+
}
15+
16+
@main def Test =
17+
val cw = new ClassWrapper()
18+
val mirrorParent = summon[deriving.Mirror.Of[cw.Base]] // error: code gen for Mirror can not access each case

0 commit comments

Comments
 (0)