Skip to content

Commit 01d3ff7

Browse files
oderskymilessabin
authored andcommitted
Make scheme work also for nested classes and companion objects
1 parent 56c0f96 commit 01d3ff7

File tree

3 files changed

+46
-12
lines changed

3 files changed

+46
-12
lines changed

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

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

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

+16-12
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,13 @@ trait Implicits { self: Typer =>
868868
.refinedWith(tpnme.MirroredMonoType, TypeAlias(monoType))
869869
.refinedWith(tpnme.MirroredLabel, TypeAlias(ConstantType(Constant(label.toString))))
870870

871+
/** A path referencing the companion of class type `clsType` */
872+
private def companionPath(clsType: Type, span: Span)(implicit ctx: Context) = {
873+
val ref = pathFor(clsType.companionRef)
874+
assert(ref.symbol.is(Module) && ref.symbol.companionClass == clsType.classSymbol)
875+
ref.withSpan(span)
876+
}
877+
871878
/** An implied instance for a type of the form `Mirror.Product { type MirroredMonoType = T }`
872879
* where `T` is a generic product type or a case object or an enum case.
873880
*/
@@ -878,16 +885,16 @@ trait Implicits { self: Typer =>
878885
mirrorFor(tp1).orElse(mirrorFor(tp2))
879886
case _ =>
880887
if (monoType.termSymbol.is(CaseVal)) {
881-
val modul = monoType.termSymbol
882-
if (modul.info.classSymbol.is(Scala2x)) {
883-
val mirrorType = mirrorCore(defn.Mirror_SingletonProxyType, monoType, modul.name)
884-
val mirrorRef = New(defn.Mirror_SingletonProxyType, ref(modul).withSpan(span) :: Nil)
888+
val module = monoType.termSymbol
889+
val modulePath = pathFor(monoType).withSpan(span)
890+
if (module.info.classSymbol.is(Scala2x)) {
891+
val mirrorType = mirrorCore(defn.Mirror_SingletonProxyType, monoType, module.name)
892+
val mirrorRef = New(defn.Mirror_SingletonProxyType, modulePath :: Nil)
885893
mirrorRef.cast(mirrorType)
886894
}
887895
else {
888-
val mirrorType = mirrorCore(defn.Mirror_SingletonType, monoType, modul.name)
889-
val mirrorRef = ref(modul).withSpan(span)
890-
mirrorRef.cast(mirrorType)
896+
val mirrorType = mirrorCore(defn.Mirror_SingletonType, monoType, module.name)
897+
modulePath.cast(mirrorType)
891898
}
892899
}
893900
else if (monoType.classSymbol.isGenericProduct) {
@@ -899,11 +906,9 @@ trait Implicits { self: Typer =>
899906
mirrorCore(defn.Mirror_ProductType, monoType, cls.name)
900907
.refinedWith(tpnme.MirroredElemTypes, TypeAlias(TypeOps.nestedPairs(elemTypes)))
901908
.refinedWith(tpnme.MirroredElemLabels, TypeAlias(TypeOps.nestedPairs(elemLabels)))
902-
val modul = cls.linkedClass.sourceModule
903-
assert(modul.is(Module))
904909
val mirrorRef =
905910
if (cls.is(Scala2x)) anonymousMirror(monoType, ExtendsProductMirror, span)
906-
else ref(modul).withSpan(span)
911+
else companionPath(monoType, span)
907912
mirrorRef.cast(mirrorType)
908913
}
909914
else EmptyTree
@@ -955,9 +960,8 @@ trait Implicits { self: Typer =>
955960
val mirrorType =
956961
mirrorCore(defn.Mirror_SumType, monoType, cls.name)
957962
.refinedWith(tpnme.MirroredElemTypes, TypeAlias(TypeOps.nestedPairs(elemTypes)))
958-
val modul = cls.linkedClass.sourceModule
959963
val mirrorRef =
960-
if (modul.exists && !cls.is(Scala2x)) ref(modul).withSpan(span)
964+
if (cls.linkedClass.exists && !cls.is(Scala2x)) companionPath(monoType, span)
961965
else anonymousMirror(monoType, ExtendsSumMirror, span)
962966
mirrorRef.cast(mirrorType)
963967
case _ =>

0 commit comments

Comments
 (0)