Skip to content

Commit b6d3d08

Browse files
committed
Make scheme work also for nested classes and companion objects
1 parent 8e2a277 commit b6d3d08

File tree

3 files changed

+46
-12
lines changed

3 files changed

+46
-12
lines changed

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

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

403+
/** A path that corresponds to the given type `tp`. Error if `tp` is not a refinement
404+
* of an addressable singleton type.
405+
*/
406+
def pathFor(tp: Type)(implicit ctx: Context): Tree = {
407+
def recur(tp: Type): Tree = tp match {
408+
case tp: NamedType =>
409+
tp.info match {
410+
case TypeAlias(alias) => recur(alias)
411+
case _: TypeBounds => EmptyTree
412+
case _ => singleton(tp)
413+
}
414+
case tp: TypeProxy => recur(tp.superType)
415+
case _ => EmptyTree
416+
}
417+
recur(tp).orElse {
418+
ctx.error(em"$tp is not an addressable singleton type")
419+
TypeTree(tp)
420+
}
421+
}
422+
403423
/** A tree representing a `newXYZArray` operation of the right
404424
* kind for the given element type in `elemTpe`. No type arguments or
405425
* `length` arguments are given.

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,15 @@ object TypeUtils {
6666
}
6767

6868
def refinedWith(name: Name, info: Type)(implicit ctx: Context) = RefinedType(self, name, info)
69+
70+
/** The TermRef referring to the companion of the underlying class reference
71+
* of this type, while keeping the same prefix.
72+
*/
73+
def companionRef(implicit ctx: Context): TermRef = self match {
74+
case self @ TypeRef(prefix, _) if self.symbol.isClass =>
75+
prefix.select(self.symbol.companionModule).asInstanceOf[TermRef]
76+
case self: TypeProxy =>
77+
self.underlying.companionRef
78+
}
6979
}
7080
}

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

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,13 @@ trait Implicits { self: Typer =>
824824
.refinedWith(tpnme.MirroredMonoType, TypeAlias(monoType))
825825
.refinedWith(tpnme.MirroredLabel, TypeAlias(ConstantType(Constant(label.toString))))
826826

827+
/** A path referencing the companion of class type `clsType` */
828+
private def companionPath(clsType: Type, span: Span)(implicit ctx: Context) = {
829+
val ref = pathFor(clsType.companionRef)
830+
assert(ref.symbol.is(Module) && ref.symbol.companionClass == clsType.classSymbol)
831+
ref.withSpan(span)
832+
}
833+
827834
/** An implied instance for a type of the form `Mirror.Product { type MirroredMonoType = T }`
828835
* where `T` is a generic product type or a case object or an enum case.
829836
*/
@@ -834,16 +841,16 @@ trait Implicits { self: Typer =>
834841
mirrorFor(tp1).orElse(mirrorFor(tp2))
835842
case _ =>
836843
if (monoType.termSymbol.is(CaseVal)) {
837-
val modul = monoType.termSymbol
838-
if (modul.info.classSymbol.is(Scala2x)) {
839-
val mirrorType = mirrorCore(defn.Mirror_SingletonProxyType, monoType, modul.name)
840-
val mirrorRef = New(defn.Mirror_SingletonProxyType, ref(modul).withSpan(span) :: Nil)
844+
val module = monoType.termSymbol
845+
val modulePath = pathFor(monoType).withSpan(span)
846+
if (module.info.classSymbol.is(Scala2x)) {
847+
val mirrorType = mirrorCore(defn.Mirror_SingletonProxyType, monoType, module.name)
848+
val mirrorRef = New(defn.Mirror_SingletonProxyType, modulePath :: Nil)
841849
mirrorRef.cast(mirrorType)
842850
}
843851
else {
844-
val mirrorType = mirrorCore(defn.Mirror_SingletonType, monoType, modul.name)
845-
val mirrorRef = ref(modul).withSpan(span)
846-
mirrorRef.cast(mirrorType)
852+
val mirrorType = mirrorCore(defn.Mirror_SingletonType, monoType, module.name)
853+
modulePath.cast(mirrorType)
847854
}
848855
}
849856
else if (monoType.classSymbol.isGenericProduct) {
@@ -855,11 +862,9 @@ trait Implicits { self: Typer =>
855862
mirrorCore(defn.Mirror_ProductType, monoType, cls.name)
856863
.refinedWith(tpnme.MirroredElemTypes, TypeAlias(TypeOps.nestedPairs(elemTypes)))
857864
.refinedWith(tpnme.MirroredElemLabels, TypeAlias(TypeOps.nestedPairs(elemLabels)))
858-
val modul = cls.linkedClass.sourceModule
859-
assert(modul.is(Module))
860865
val mirrorRef =
861866
if (cls.is(Scala2x)) anonymousMirror(monoType, ExtendsProductMirror, span)
862-
else ref(modul).withSpan(span)
867+
else companionPath(monoType, span)
863868
mirrorRef.cast(mirrorType)
864869
}
865870
else EmptyTree
@@ -911,9 +916,8 @@ trait Implicits { self: Typer =>
911916
val mirrorType =
912917
mirrorCore(defn.Mirror_SumType, monoType, cls.name)
913918
.refinedWith(tpnme.MirroredElemTypes, TypeAlias(TypeOps.nestedPairs(elemTypes)))
914-
val modul = cls.linkedClass.sourceModule
915919
val mirrorRef =
916-
if (modul.exists && !cls.is(Scala2x)) ref(modul).withSpan(span)
920+
if (cls.linkedClass.exists && !cls.is(Scala2x)) companionPath(monoType, span)
917921
else anonymousMirror(monoType, ExtendsSumMirror, span)
918922
mirrorRef.cast(mirrorType)
919923
case _ =>

0 commit comments

Comments
 (0)