Skip to content

Commit 2176fe4

Browse files
authored
Use MirrorSource.reduce result for companionPath (#20207)
Fixes #20187
2 parents 63810dc + ef03fc0 commit 2176fe4

File tree

5 files changed

+34
-42
lines changed

5 files changed

+34
-42
lines changed

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -471,26 +471,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
471471
case ConstantType(value) => Literal(value)
472472
}
473473

474-
/** A path that corresponds to the given type `tp`. Error if `tp` is not a refinement
475-
* of an addressable singleton type.
476-
*/
477-
def pathFor(tp: Type)(using Context): Tree = {
478-
def recur(tp: Type): Tree = tp match {
479-
case tp: NamedType =>
480-
tp.info match {
481-
case TypeAlias(alias) => recur(alias)
482-
case _: TypeBounds => EmptyTree
483-
case _ => singleton(tp)
484-
}
485-
case tp: TypeProxy => recur(tp.superType)
486-
case _ => EmptyTree
487-
}
488-
recur(tp).orElse {
489-
report.error(em"$tp is not an addressable singleton type")
490-
TypeTree(tp)
491-
}
492-
}
493-
494474
/** A tree representing a `newXYZArray` operation of the right
495475
* kind for the given element type in `elemTpe`. No type arguments or
496476
* `length` arguments are given.

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

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -116,21 +116,6 @@ class TypeUtils {
116116

117117
def refinedWith(name: Name, info: Type)(using Context) = RefinedType(self, name, info)
118118

119-
/** The TermRef referring to the companion of the underlying class reference
120-
* of this type, while keeping the same prefix.
121-
*/
122-
def mirrorCompanionRef(using Context): TermRef = self match {
123-
case AndType(tp1, tp2) =>
124-
val c1 = tp1.classSymbol
125-
val c2 = tp2.classSymbol
126-
if c1.isSubClass(c2) then tp1.mirrorCompanionRef
127-
else tp2.mirrorCompanionRef // precondition: the parts of the AndType have already been checked to be non-overlapping
128-
case self @ TypeRef(prefix, _) if self.symbol.isClass =>
129-
prefix.select(self.symbol.companionModule).asInstanceOf[TermRef]
130-
case self: TypeProxy =>
131-
self.superType.mirrorCompanionRef
132-
}
133-
134119
/** Is this type a methodic type that takes at least one parameter? */
135120
def takesParams(using Context): Boolean = self.stripPoly match
136121
case mt: MethodType => mt.paramNames.nonEmpty || mt.resType.takesParams

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import transform.SyntheticMembers.*
1515
import util.Property
1616
import ast.Trees.genericEmptyTree
1717
import annotation.{tailrec, constructorOnly}
18+
import ast.tpd
1819
import ast.tpd.*
1920
import Synthesizer.*
2021
import sbt.ExtractDependencies.*
@@ -265,10 +266,10 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
265266
.refinedWith(tpnme.MirroredType, TypeAlias(mirroredType))
266267
.refinedWith(tpnme.MirroredLabel, TypeAlias(ConstantType(Constant(label.toString))))
267268

268-
/** A path referencing the companion of class type `clsType` */
269-
private def companionPath(clsType: Type, span: Span)(using Context) =
270-
val ref = pathFor(clsType.mirrorCompanionRef)
271-
assert(ref.symbol.is(Module) && (clsType.classSymbol.is(ModuleClass) || (ref.symbol.companionClass == clsType.classSymbol)))
269+
/** A path referencing the companion of `cls` with prefix `pre` */
270+
private def companionPath(pre: Type, cls: Symbol, span: Span)(using Context) =
271+
val ref = tpd.ref(TermRef(pre, cls.companionModule))
272+
assert(ref.symbol.is(Module) && (cls.is(ModuleClass) || ref.symbol.companionClass == cls))
272273
ref.withSpan(span)
273274

274275
private def checkFormal(formal: Type)(using Context): Boolean =
@@ -428,7 +429,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
428429
.refinedWith(tpnme.MirroredElemLabels, TypeAlias(elemsLabels))
429430
}
430431
val mirrorRef =
431-
if cls.useCompanionAsProductMirror then companionPath(mirroredType, span)
432+
if cls.useCompanionAsProductMirror then companionPath(pre, cls, span)
432433
else if defn.isTupleClass(cls) then newTupleMirror(typeElems.size) // TODO: cls == defn.PairClass when > 22
433434
else anonymousMirror(monoType, MirrorImpl.OfProduct(pre), span)
434435
withNoErrors(mirrorRef.cast(mirrorType).withSpan(span))
@@ -438,7 +439,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
438439
case Right(msrc) => msrc match
439440
case MirrorSource.Singleton(_, tref) =>
440441
val singleton = tref.termSymbol // prefer alias name over the orignal name
441-
val singletonPath = pathFor(tref).withSpan(span)
442+
val singletonPath = tpd.singleton(tref).withSpan(span)
442443
if tref.classSymbol.is(Scala2x) then // could be Scala 3 alias of Scala 2 case object.
443444
val mirrorType = formal.constrained_& {
444445
mirrorCore(defn.Mirror_SingletonProxyClass, mirroredType, mirroredType, singleton.name)
@@ -571,7 +572,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
571572
.refinedWith(tpnme.MirroredElemLabels, TypeAlias(labels))
572573
}
573574
val mirrorRef =
574-
if cls.useCompanionAsSumMirror then companionPath(mirroredType, span)
575+
if cls.useCompanionAsSumMirror then companionPath(pre, cls, span)
575576
else anonymousMirror(monoType, MirrorImpl.OfSum(childPres), span)
576577
withNoErrors(mirrorRef.cast(mirrorType))
577578
else if acceptableMsg.nonEmpty then

tests/pos/i20187/A_1.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import scala.deriving.Mirror
2+
3+
enum E:
4+
case Foo1()
5+
case Foo2()
6+
7+
class Outer:
8+
case class Inner()
9+
val o = new Outer
10+
11+
type F = E.Foo1
12+
type G = Tuple.Head[E.Foo1 *: E.Foo2 *: EmptyTuple]
13+
type H = Tuple.Head[o.Inner *: EmptyTuple]
14+
type I = Tuple.Last[E *: EmptyTuple]
15+
16+
def local =
17+
case class Bar()
18+
type B = Tuple.Head[Bar *: EmptyTuple]
19+
summon[Mirror.Of[B]]

tests/pos/i20187/B_2.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import scala.deriving.Mirror
2+
3+
def Test =
4+
summon[Mirror.Of[F]] // ok
5+
summon[Mirror.Of[G]] // was crash
6+
summon[Mirror.Of[H]] // was crash
7+
summon[Mirror.Of[I]] // was crash

0 commit comments

Comments
 (0)