@@ -27,6 +27,8 @@ import ErrorReporting._
2727import reporting .diagnostic .Message
2828import Inferencing .fullyDefinedType
2929import Trees ._
30+ import transform .SymUtils ._
31+ import transform .TypeUtils ._
3032import Hashable ._
3133import util .{Property , SourceFile , NoSource }
3234import config .Config
@@ -812,17 +814,103 @@ trait Implicits { self: Typer =>
812814 EmptyTree
813815 }
814816
817+ lazy val synthesizedProductMirror : SpecialHandler =
818+ (formal : Type , span : Span ) => implicit (ctx : Context ) => {
819+ formal.member(tpnme.MonoType ).info match {
820+ case monoAlias @ TypeAlias (monoType) =>
821+ if (monoType.termSymbol.is(CaseVal )) {
822+ val modul = monoType.termSymbol
823+ val caseLabel = ConstantType (Constant (modul.name.toString))
824+ val mirrorType = defn.Mirror_SingletonType
825+ .refinedWith(tpnme.MonoType , monoAlias)
826+ .refinedWith(tpnme.CaseLabel , TypeAlias (caseLabel))
827+ ref(modul).withSpan(span).cast(mirrorType)
828+ }
829+ else if (monoType.classSymbol.isGenericProduct) {
830+ val cls = monoType.classSymbol
831+ val accessors = cls.caseAccessors.filterNot(_.is(PrivateLocal ))
832+ val elemTypes = accessors.map(monoType.memberInfo(_))
833+ val caseLabel = ConstantType (Constant (cls.name.toString))
834+ val elemLabels = accessors.map(acc => ConstantType (Constant (acc.name.toString)))
835+ val mirrorType =
836+ defn.Mirror_ProductType
837+ .refinedWith(tpnme.MonoType , monoAlias)
838+ .refinedWith(tpnme.ElemTypes , TypeAlias (TypeOps .nestedPairs(elemTypes)))
839+ .refinedWith(tpnme.CaseLabel , TypeAlias (caseLabel))
840+ .refinedWith(tpnme.ElemLabels , TypeAlias (TypeOps .nestedPairs(elemLabels)))
841+ val modul = cls.linkedClass.sourceModule
842+ assert(modul.is(Module ))
843+ ref(modul).withSpan(span).cast(mirrorType)
844+ }
845+ else EmptyTree
846+ case _ => EmptyTree
847+ }
848+ }
849+
850+ lazy val synthesizedSumMirror : SpecialHandler =
851+ (formal : Type , span : Span ) => implicit (ctx : Context ) =>
852+ formal.member(tpnme.MonoType ).info match {
853+ case monoAlias @ TypeAlias (monoType) if monoType.classSymbol.isGenericSum =>
854+ val cls = monoType.classSymbol
855+ val elemTypes = cls.children.map {
856+ case caseClass : ClassSymbol =>
857+ assert(caseClass.is(Case ))
858+ if (caseClass.is(Module ))
859+ caseClass.sourceModule.termRef
860+ else caseClass.primaryConstructor.info match {
861+ case info : PolyType =>
862+ def instantiate (implicit ctx : Context ) = {
863+ val poly = constrained(info, untpd.EmptyTree )._1
864+ val mono @ MethodType (_) = poly.resultType
865+ val resType = mono.finalResultType
866+ resType <:< cls.appliedRef
867+ val tparams = poly.paramRefs
868+ val variances = caseClass.typeParams.map(_.paramVariance)
869+ val instanceTypes = (tparams, variances).zipped.map((tparam, variance) =>
870+ ctx.typeComparer.instanceType(tparam, fromBelow = variance < 0 ))
871+ resType.substParams(poly, instanceTypes)
872+ }
873+ instantiate(ctx.fresh.setExploreTyperState().setOwner(caseClass))
874+ case _ =>
875+ caseClass.typeRef
876+ }
877+ case child => child.termRef
878+ }
879+ val mirrorType =
880+ defn.Mirror_SumType
881+ .refinedWith(tpnme.MonoType , monoAlias)
882+ .refinedWith(tpnme.ElemTypes , TypeAlias (TypeOps .nestedPairs(elemTypes)))
883+ var modul = cls.linkedClass.sourceModule
884+ if (! modul.exists) ???
885+ ref(modul).withSpan(span).cast(mirrorType)
886+ case _ =>
887+ EmptyTree
888+ }
889+
890+ lazy val synthesizedMirror : SpecialHandler =
891+ (formal : Type , span : Span ) => implicit (ctx : Context ) =>
892+ formal.member(tpnme.MonoType ).info match {
893+ case monoAlias @ TypeAlias (monoType) =>
894+ if (monoType.termSymbol.is(CaseVal ) || monoType.classSymbol.isGenericProduct)
895+ synthesizedProductMirror(formal, span)(ctx)
896+ else
897+ synthesizedSumMirror(formal, span)(ctx)
898+ }
899+
815900 private var mySpecialHandlers : SpecialHandlers = null
816901
817902 private def specialHandlers (implicit ctx : Context ) = {
818903 if (mySpecialHandlers == null )
819904 mySpecialHandlers = List (
820- defn.ClassTagClass -> synthesizedClassTag,
821- defn.QuotedTypeClass -> synthesizedTypeTag,
822- defn.GenericClass -> synthesizedGeneric,
905+ defn.ClassTagClass -> synthesizedClassTag,
906+ defn.QuotedTypeClass -> synthesizedTypeTag,
907+ defn.GenericClass -> synthesizedGeneric,
823908 defn.TastyReflectionClass -> synthesizedTastyContext,
824- defn.EqlClass -> synthesizedEq,
825- defn.ValueOfClass -> synthesizedValueOf
909+ defn.EqlClass -> synthesizedEq,
910+ defn.ValueOfClass -> synthesizedValueOf,
911+ defn.Mirror_ProductClass -> synthesizedProductMirror,
912+ defn.Mirror_SumClass -> synthesizedSumMirror,
913+ defn.MirrorClass -> synthesizedMirror
826914 )
827915 mySpecialHandlers
828916 }
@@ -836,7 +924,13 @@ trait Implicits { self: Typer =>
836924 case fail @ SearchFailure (failed) =>
837925 def trySpecialCases (handlers : SpecialHandlers ): Tree = handlers match {
838926 case (cls, handler) :: rest =>
839- val base = formal.baseType(cls)
927+ def baseWithRefinements (tp : Type ): Type = tp.dealias match {
928+ case tp @ RefinedType (parent, rname, rinfo) =>
929+ tp.derivedRefinedType(baseWithRefinements(parent), rname, rinfo)
930+ case _ =>
931+ tp.baseType(cls)
932+ }
933+ val base = baseWithRefinements(formal)
840934 val result =
841935 if (base <:< formal) {
842936 // With the subtype test we enforce that the searched type `formal` is of the right form
0 commit comments