Skip to content

Commit 9f85908

Browse files
committed
remove prefix splice in companionref
1 parent 70ed5e4 commit 9f85908

File tree

6 files changed

+43
-9
lines changed

6 files changed

+43
-9
lines changed

compiler/src/dotty/tools/dotc/core/TypeOps.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,10 @@ object TypeOps:
874874
if term.widen.classSymbol eq cls then Some(pre)
875875
else loopThisType(cls, term.prefix)
876876

877+
case supTpe: SuperType =>
878+
if supTpe.thistpe.classSymbol.isSubClass(cls) then Some(pre)
879+
else None
880+
877881
case _ => None
878882

879883
end PrefixSplice

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ object TypeUtils {
9292
val r2 = tp2.mirrorCompanionRef
9393
assert(r1.symbol == r2.symbol, em"mirrorCompanionRef mismatch for $self: $r1, $r2 did not have the same symbol")
9494
r1
95+
case AndType(tp1, tp2) =>
96+
val c1 = tp1.classSymbol
97+
val c2 = tp2.classSymbol
98+
if c1.isSubClass(c2) then tp1.mirrorCompanionRef
99+
else tp2.mirrorCompanionRef // precondition: the parts of the AndType have already been checked to be non-overlapping
95100
case self @ TypeRef(prefix, _) if self.symbol.isClass =>
96101
prefix.select(self.symbol.companionModule).asInstanceOf[TermRef]
97102
case self: TypeProxy =>

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

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,8 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
248248
.refinedWith(tpnme.MirroredLabel, TypeAlias(ConstantType(Constant(label.toString))))
249249

250250
/** A path referencing the companion of class type `clsType` */
251-
private def companionPath(mirroredType: Type, cls: Symbol, pre: Type, span: Span)(using Context) =
252-
val clsType =
253-
// ok to assume healPrefix will succeed because `cls` and `pre` derive from the same type.
254-
// TODO: will fail, e.g. for value alias to case object - we still need to support `scala.package.None.type`
255-
TypeOps.healPrefix(mirroredType.mirrorCompanionRef, pre).toOption.get
251+
private def companionPath(mirroredType: Type, cls: Symbol, span: Span)(using Context) =
252+
val clsType = mirroredType.mirrorCompanionRef
256253
val ref = pathFor(clsType)
257254
assert(ref.symbol.is(Module) && (cls.is(ModuleClass) || (ref.symbol.companionClass == cls)))
258255
ref.withSpan(span)
@@ -327,7 +324,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
327324
if (genAnonyousMirror(cls))
328325
// TODO: scan for problematic prefix
329326
anonymousMirror(monoType, mirroredType, ExtendsProductMirror, pre, span)
330-
else companionPath(mirroredType, cls, pre, span)
327+
else companionPath(mirroredType, cls, span)
331328
mirrorRef.cast(mirrorType)
332329
end makeProductMirror
333330

@@ -444,7 +441,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
444441
.refinedWith(tpnme.MirroredElemTypes, TypeAlias(elemsType))
445442
.refinedWith(tpnme.MirroredElemLabels, TypeAlias(TypeOps.nestedPairs(elemLabels)))
446443
val mirrorRef =
447-
if useCompanion then companionPath(mirroredType, cls, pre, span)
444+
if useCompanion then companionPath(mirroredType, cls, span)
448445
else anonymousMirror(monoType, mirroredType, ExtendsSumMirror, pre, span)
449446
mirrorRef.cast(mirrorType)
450447
else

tests/run/anon-mirror-gen-dep-i.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class Outer {
99
case class Seed() extends Item
1010
}
1111

12-
lazy val o = new Outer() // infinite init
12+
final lazy val o = new Outer() // infinite init
1313

1414
def hello: Unit = {
1515

tests/run/anon-mirror-gen-dep-j.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import scala.deriving.Mirror
2+
import scala.CanEqual.derived
3+
4+
class Outer {
5+
6+
sealed trait Item
7+
case class Fruit(seed: Seed) extends Item
8+
case class Seed() extends Item
9+
10+
final lazy val o = new Outer() // infinite init
11+
12+
def hello: Unit = {
13+
14+
val mFruit = summon[Mirror.Of[o.Item & o.Fruit]]
15+
type derivedSeed = Tuple.Head[mFruit.MirroredElemTypes]
16+
val mSeed = summon[Mirror.Of[derivedSeed]]
17+
18+
assert(mFruit.fromProduct(Tuple(o.Seed())) == o.Fruit(o.Seed()))
19+
assert(mSeed.fromProduct(EmptyTuple) == o.Seed()) // careful to ensure that correct outer is captured
20+
}
21+
22+
}
23+
24+
@main def Test = {
25+
val o = new Outer()
26+
o.hello
27+
}

tests/neg/anon-mirror-gen-super-a.scala renamed to tests/run/anon-mirror-gen-super-a.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import scala.deriving.Mirror
88
}
99

1010
class Bar extends Foo {
11-
summon[Mirror.Of[Bar.super.foo.type]] //
11+
val mQux = summon[Mirror.Of[Bar.super.foo.type]]
12+
assert(mQux.fromProduct(EmptyTuple) == Qux)
1213
}
1314

1415
}

0 commit comments

Comments
 (0)