@@ -21,6 +21,7 @@ import Flags._
21
21
import Decorators ._
22
22
import ErrorReporting ._
23
23
import Checking ._
24
+ import Inferencing ._
24
25
import EtaExpansion .etaExpand
25
26
import dotty .tools .dotc .transform .Erasure .Boxing
26
27
import util .Positions ._
@@ -55,7 +56,7 @@ object Typer {
55
56
assert(tree.pos.exists, s " position not set for $tree # ${tree.uniqueId}" )
56
57
}
57
58
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 {
59
60
60
61
import Typer ._
61
62
import tpd .{cpy => _ , _ }
@@ -977,6 +978,47 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
977
978
// 4. Polymorphic type defs override nothing.
978
979
}
979
980
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
+
980
1022
/** If this is a real class, make sure its first parent is a
981
1023
* constructor call. Cannot simply use a type. Overridden in ReTyper.
982
1024
*/
0 commit comments