Skip to content

Commit aaa2925

Browse files
Backport "Use MirrorSource.reduce result for companionPath" to LTS (#21074)
Backports #20207 to the LTS branch. PR submitted by the release tooling. [skip ci]
2 parents 5098982 + 04cf714 commit aaa2925

File tree

5 files changed

+34
-42
lines changed

5 files changed

+34
-42
lines changed

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

-20
Original file line numberDiff line numberDiff line change
@@ -464,26 +464,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
464464
case ConstantType(value) => Literal(value)
465465
}
466466

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

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

-15
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

+8-7
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

@@ -264,10 +265,10 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
264265
.refinedWith(tpnme.MirroredType, TypeAlias(mirroredType))
265266
.refinedWith(tpnme.MirroredLabel, TypeAlias(ConstantType(Constant(label.toString))))
266267

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

273274
private def checkFormal(formal: Type)(using Context): Boolean =
@@ -427,7 +428,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
427428
.refinedWith(tpnme.MirroredElemLabels, TypeAlias(elemsLabels))
428429
}
429430
val mirrorRef =
430-
if cls.useCompanionAsProductMirror then companionPath(mirroredType, span)
431+
if cls.useCompanionAsProductMirror then companionPath(pre, cls, span)
431432
else if defn.isTupleClass(cls) then newTupleMirror(typeElems.size) // TODO: cls == defn.PairClass when > 22
432433
else anonymousMirror(monoType, MirrorImpl.OfProduct(pre), span)
433434
withNoErrors(mirrorRef.cast(mirrorType).withSpan(span))
@@ -437,7 +438,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
437438
case Right(msrc) => msrc match
438439
case MirrorSource.Singleton(_, tref) =>
439440
val singleton = tref.termSymbol // prefer alias name over the orignal name
440-
val singletonPath = pathFor(tref).withSpan(span)
441+
val singletonPath = tpd.singleton(tref).withSpan(span)
441442
if tref.classSymbol.is(Scala2x) then // could be Scala 3 alias of Scala 2 case object.
442443
val mirrorType = formal.constrained_& {
443444
mirrorCore(defn.Mirror_SingletonProxyClass, mirroredType, mirroredType, singleton.name)
@@ -556,7 +557,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
556557
.refinedWith(tpnme.MirroredElemLabels, TypeAlias(labels))
557558
}
558559
val mirrorRef =
559-
if cls.useCompanionAsSumMirror then companionPath(mirroredType, span)
560+
if cls.useCompanionAsSumMirror then companionPath(pre, cls, span)
560561
else anonymousMirror(monoType, MirrorImpl.OfSum(childPres), span)
561562
withNoErrors(mirrorRef.cast(mirrorType))
562563
else if acceptableMsg.nonEmpty then

tests/pos/i20187/A_1.scala

+19
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

+7
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)