Skip to content

Commit 2a92bab

Browse files
committed
Polishings
1 parent 01da2ff commit 2a92bab

File tree

1 file changed

+32
-19
lines changed

1 file changed

+32
-19
lines changed

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

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ trait Implicits { self: Typer =>
818818
/** Create an anonymous class `new Object { type MonoType = ... }`
819819
* and mark it with given attachment so that it is made into a mirror at PostTyper.
820820
*/
821-
def anonymousMirror(monoType: Type, attachment: Property.StickyKey[Unit], span: Span)(implicit ctx: Context) = {
821+
private def anonymousMirror(monoType: Type, attachment: Property.StickyKey[Unit], span: Span)(implicit ctx: Context) = {
822822
val monoTypeDef = untpd.TypeDef(tpnme.MonoType, untpd.TypeTree(monoType))
823823
val newImpl = untpd.Template(
824824
constr = untpd.emptyConstructor,
@@ -830,6 +830,18 @@ trait Implicits { self: Typer =>
830830
typed(untpd.New(newImpl).withSpan(span))
831831
}
832832

833+
/** The mirror type
834+
*
835+
* <parent> { MonoType = <monoType; Label = <label> }
836+
*/
837+
private def mirrorCore(parent: Type, monoType: Type, label: Name)(implicit ctx: Context) =
838+
parent
839+
.refinedWith(tpnme.MonoType, TypeAlias(monoType))
840+
.refinedWith(tpnme.Label, TypeAlias(ConstantType(Constant(label.toString))))
841+
842+
/** An implied instance for a type of the form `Mirror.Product { type MonoType = T }`
843+
* where `T` is a generic product type or a case object or an enum case.
844+
*/
833845
lazy val synthesizedProductMirror: SpecialHandler =
834846
(formal: Type, span: Span) => implicit (ctx: Context) => {
835847
def mirrorFor(monoType: Type): Tree = monoType match {
@@ -838,19 +850,13 @@ trait Implicits { self: Typer =>
838850
case _ =>
839851
if (monoType.termSymbol.is(CaseVal)) {
840852
val modul = monoType.termSymbol
841-
val label = ConstantType(Constant(modul.name.toString))
842853
if (modul.info.classSymbol.is(Scala2x)) {
843-
val mirrorType =
844-
defn.Mirror_SingletonProxyType
845-
.refinedWith(tpnme.MonoType, TypeAlias(monoType))
846-
.refinedWith(tpnme.Label, TypeAlias(label))
854+
val mirrorType = mirrorCore(defn.Mirror_SingletonProxyType, monoType, modul.name)
847855
val mirrorRef = New(defn.Mirror_SingletonProxyType, ref(modul).withSpan(span) :: Nil)
848856
mirrorRef.cast(mirrorType)
849857
}
850858
else {
851-
val mirrorType = defn.Mirror_SingletonType
852-
.refinedWith(tpnme.MonoType, TypeAlias(monoType))
853-
.refinedWith(tpnme.Label, TypeAlias(label))
859+
val mirrorType = mirrorCore(defn.Mirror_SingletonType, monoType, modul.name)
854860
val mirrorRef = ref(modul).withSpan(span)
855861
mirrorRef.cast(mirrorType)
856862
}
@@ -859,13 +865,10 @@ trait Implicits { self: Typer =>
859865
val cls = monoType.classSymbol
860866
val accessors = cls.caseAccessors.filterNot(_.is(PrivateLocal))
861867
val elemTypes = accessors.map(monoType.memberInfo(_).widenExpr)
862-
val label = ConstantType(Constant(cls.name.toString))
863868
val elemLabels = accessors.map(acc => ConstantType(Constant(acc.name.toString)))
864869
val mirrorType =
865-
defn.Mirror_ProductType
866-
.refinedWith(tpnme.MonoType, TypeAlias(monoType))
870+
mirrorCore(defn.Mirror_ProductType, monoType, cls.name)
867871
.refinedWith(tpnme.ElemTypes, TypeAlias(TypeOps.nestedPairs(elemTypes)))
868-
.refinedWith(tpnme.Label, TypeAlias(label))
869872
.refinedWith(tpnme.ElemLabels, TypeAlias(TypeOps.nestedPairs(elemLabels)))
870873
val modul = cls.linkedClass.sourceModule
871874
assert(modul.is(Module))
@@ -882,19 +885,28 @@ trait Implicits { self: Typer =>
882885
}
883886
}
884887

888+
/** An implied instance for a type of the form `Mirror.Sum { type MonoType = T }`
889+
* where `T` is a generic sum type.
890+
*/
885891
lazy val synthesizedSumMirror: SpecialHandler =
886892
(formal: Type, span: Span) => implicit (ctx: Context) =>
887893
formal.member(tpnme.MonoType).info match {
888-
case monoAlias @ TypeAlias(monoType) if monoType.classSymbol.isGenericSum =>
894+
case TypeAlias(monoType) if monoType.classSymbol.isGenericSum =>
889895
val cls = monoType.classSymbol
890-
val label = ConstantType(Constant(cls.name.toString))
891896
val elemTypes = cls.children.map {
892897
case caseClass: ClassSymbol =>
893898
assert(caseClass.is(Case))
894899
if (caseClass.is(Module))
895900
caseClass.sourceModule.termRef
896901
else caseClass.primaryConstructor.info match {
897902
case info: PolyType =>
903+
// Compute the the full child type by solving the subtype constraint
904+
// `C[X1, ..., Xn] <: P`, where
905+
//
906+
// - P is the current `monoType`
907+
// - C is the child class, with type parameters X1, ..., Xn
908+
//
909+
// Contravariant type parameters are minimized, all other type parameters are maximized.
898910
def instantiate(implicit ctx: Context) = {
899911
val poly = constrained(info, untpd.EmptyTree)._1
900912
val resType = poly.finalResultType
@@ -912,11 +924,9 @@ trait Implicits { self: Typer =>
912924
case child => child.termRef
913925
}
914926
val mirrorType =
915-
defn.Mirror_SumType
916-
.refinedWith(tpnme.MonoType, monoAlias)
917-
.refinedWith(tpnme.Label, TypeAlias(label))
927+
mirrorCore(defn.Mirror_SumType, monoType, cls.name)
918928
.refinedWith(tpnme.ElemTypes, TypeAlias(TypeOps.nestedPairs(elemTypes)))
919-
var modul = cls.linkedClass.sourceModule
929+
val modul = cls.linkedClass.sourceModule
920930
val mirrorRef =
921931
if (modul.exists && !cls.is(Scala2x)) ref(modul).withSpan(span)
922932
else anonymousMirror(monoType, ExtendsSumMirror, span)
@@ -925,6 +935,9 @@ trait Implicits { self: Typer =>
925935
EmptyTree
926936
}
927937

938+
/** An implied instance for a type of the form `Mirror { type MonoType = T }`
939+
* where `T` is a generic sum or product or singleton type.
940+
*/
928941
lazy val synthesizedMirror: SpecialHandler =
929942
(formal: Type, span: Span) => implicit (ctx: Context) =>
930943
formal.member(tpnme.MonoType).info match {

0 commit comments

Comments
 (0)