@@ -21,6 +21,7 @@ import Flags._
2121import Decorators ._
2222import ErrorReporting ._
2323import Checking ._
24+ import Inferencing ._
2425import EtaExpansion .etaExpand
2526import dotty .tools .dotc .transform .Erasure .Boxing
2627import util .Positions ._
@@ -55,7 +56,7 @@ object Typer {
5556 assert(tree.pos.exists, s " position not set for $tree # ${tree.uniqueId}" )
5657}
5758
58- class Typer extends Namer with TypeAssigner with Applications with Implicits with Inferencing with Checking {
59+ class Typer extends Namer with TypeAssigner with Applications with Implicits with Checking {
5960
6061 import Typer ._
6162 import tpd .{cpy => _ , _ }
@@ -977,6 +978,47 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
977978 // 4. Polymorphic type defs override nothing.
978979 }
979980
981+ /** Ensure that the first type in a list of parent types Ps points to a non-trait class.
982+ * If that's not already the case, add one. The added class type CT is determined as follows.
983+ * First, let C be the unique class such that
984+ * - there is a parent P_i such that P_i derives from C, and
985+ * - for every class D: If some parent P_j, j <= i derives from D, then C derives from D.
986+ * Then, let CT be the smallest type which
987+ * - has C as its class symbol, and
988+ * - for all parents P_i: If P_i derives from C then P_i <:< CT.
989+ */
990+ def ensureFirstIsClass (parents : List [Type ])(implicit ctx : Context ): List [Type ] = {
991+ def realClassParent (cls : Symbol ): ClassSymbol =
992+ if (! cls.isClass) defn.ObjectClass
993+ else if (! (cls is Trait )) cls.asClass
994+ else cls.asClass.classParents match {
995+ case parentRef :: _ => realClassParent(parentRef.symbol)
996+ case nil => defn.ObjectClass
997+ }
998+ def improve (candidate : ClassSymbol , parent : Type ): ClassSymbol = {
999+ val pcls = realClassParent(parent.classSymbol)
1000+ if (pcls derivesFrom candidate) pcls else candidate
1001+ }
1002+ parents match {
1003+ case p :: _ if p.classSymbol.isRealClass => parents
1004+ case _ =>
1005+ val pcls = (defn.ObjectClass /: parents)(improve)
1006+ typr.println(i " ensure first is class $parents%, % --> ${parents map (_ baseTypeWithArgs pcls)}%, % " )
1007+ val ptype = ctx.typeComparer.glb(
1008+ defn.ObjectType :: (parents map (_ baseTypeWithArgs pcls)))
1009+ ptype :: parents
1010+ }
1011+ }
1012+
1013+ /** Ensure that first parent tree refers to a real class. */
1014+ def ensureFirstIsClass (parents : List [Tree ], pos : Position )(implicit ctx : Context ): List [Tree ] = parents match {
1015+ case p :: ps if p.tpe.classSymbol.isRealClass => parents
1016+ case _ =>
1017+ // add synthetic class type
1018+ val first :: _ = ensureFirstIsClass(parents.tpes)
1019+ TypeTree (checkFeasible(first, pos, d " \n in inferred parent $first" )).withPos(pos) :: parents
1020+ }
1021+
9801022 /** If this is a real class, make sure its first parent is a
9811023 * constructor call. Cannot simply use a type. Overridden in ReTyper.
9821024 */
0 commit comments