@@ -2219,20 +2219,18 @@ class Typer extends Namer
22192219 * @param psym Its type symbol
22202220 * @param cinfo The info of its constructor
22212221 */
2222- def maybeCall (ref : Tree , psym : Symbol , cinfo : Type ): Tree = cinfo. stripPoly match {
2222+ def maybeCall (ref : Tree , psym : Symbol ): Tree = psym.primaryConstructor.info. stripPoly match
22232223 case cinfo @ MethodType (Nil ) if cinfo.resultType.isImplicitMethod =>
22242224 typedExpr(untpd.New (untpd.TypedSplice (ref)(using superCtx), Nil ))(using superCtx)
22252225 case cinfo @ MethodType (Nil ) if ! cinfo.resultType.isInstanceOf [MethodType ] =>
22262226 ref
22272227 case cinfo : MethodType =>
2228- if ( ! ctx.erasedTypes) { // after constructors arguments are passed in super call.
2228+ if ! ctx.erasedTypes then // after constructors arguments are passed in super call.
22292229 typr.println(i " constr type: $cinfo" )
22302230 report.error(ParameterizedTypeLacksArguments (psym), ref.srcPos)
2231- }
22322231 ref
22332232 case _ =>
22342233 ref
2235- }
22362234
22372235 val seenParents = mutable.Set [Symbol ]()
22382236
@@ -2257,14 +2255,35 @@ class Typer extends Namer
22572255 if (tree.isType) {
22582256 checkSimpleKinded(result) // Not needed for constructor calls, as type arguments will be inferred.
22592257 if (psym.is(Trait ) && ! cls.is(Trait ) && ! cls.superClass.isSubClass(psym))
2260- result = maybeCall(result, psym, psym.primaryConstructor.info )
2258+ result = maybeCall(result, psym)
22612259 }
22622260 else checkParentCall(result, cls)
22632261 checkTraitInheritance(psym, cls, tree.srcPos)
22642262 if (cls is Case ) checkCaseInheritance(psym, cls, tree.srcPos)
22652263 result
22662264 }
22672265
2266+ /** Augment `ptrees` to have the same class symbols as `parents`. Generate TypeTrees
2267+ * or New trees to fill in any parents for which no tree exists yet.
2268+ */
2269+ def parentTrees (parents : List [Type ], ptrees : List [Tree ]): List [Tree ] = parents match
2270+ case parent :: parents1 =>
2271+ val psym = parent.classSymbol
2272+ def hasSameParent (ptree : Tree ) = ptree.tpe.classSymbol == psym
2273+ ptrees match
2274+ case ptree :: ptrees1 if hasSameParent(ptree) =>
2275+ ptree :: parentTrees(parents1, ptrees1)
2276+ case ptree :: ptrees1 if ptrees1.exists(hasSameParent) =>
2277+ ptree :: parentTrees(parents, ptrees1)
2278+ case _ =>
2279+ var added : Tree = TypeTree (parent).withSpan(cdef.nameSpan.focus)
2280+ if psym.is(Trait ) && psym.primaryConstructor.info.takesImplicitParams then
2281+ // classes get a constructor separately using a different context
2282+ added = ensureConstrCall(cls, added)
2283+ added :: parentTrees(parents1, ptrees)
2284+ case _ =>
2285+ ptrees
2286+
22682287 /** Checks if one of the decls is a type with the same name as class type member in selfType */
22692288 def classExistsOnSelf (decls : Scope , self : tpd.ValDef ): Boolean = {
22702289 val selfType = self.tpt.tpe
@@ -2285,8 +2304,10 @@ class Typer extends Namer
22852304
22862305 completeAnnotations(cdef, cls)
22872306 val constr1 = typed(constr).asInstanceOf [DefDef ]
2288- val parentsWithClass = ensureFirstTreeIsClass(parents.mapconserve(typedParent).filterConserve(! _.isEmpty), cdef.nameSpan)
2289- val parents1 = ensureConstrCall(cls, parentsWithClass)(using superCtx)
2307+ val parents0 = parentTrees(
2308+ cls.classInfo.declaredParents,
2309+ parents.mapconserve(typedParent).filterConserve(! _.isEmpty))
2310+ val parents1 = ensureConstrCall(cls, parents0)(using superCtx)
22902311 val firstParentTpe = parents1.head.tpe.dealias
22912312 val firstParent = firstParentTpe.typeSymbol
22922313
@@ -2355,52 +2376,23 @@ class Typer extends Namer
23552376 protected def addAccessorDefs (cls : Symbol , body : List [Tree ])(using Context ): List [Tree ] =
23562377 ctx.compilationUnit.inlineAccessors.addAccessorDefs(cls, body)
23572378
2358- /** Ensure that the first type in a list of parent types Ps points to a non-trait class.
2359- * If that's not already the case, add one. The added class type CT is determined as follows.
2360- * First, let C be the unique class such that
2361- * - there is a parent P_i such that P_i derives from C, and
2362- * - for every class D: If some parent P_j, j <= i derives from D, then C derives from D.
2363- * Then, let CT be the smallest type which
2364- * - has C as its class symbol, and
2365- * - for all parents P_i: If P_i derives from C then P_i <:< CT.
2379+ /** If this is a real class, make sure its first parent is a
2380+ * constructor call. Cannot simply use a type. Overridden in ReTyper.
23662381 */
2367- def ensureFirstIsClass (parents : List [Type ], span : Span )(using Context ): List [Type ] = {
2368- def realClassParent (cls : Symbol ): ClassSymbol =
2369- if (! cls.isClass) defn.ObjectClass
2370- else if (! cls.is(Trait )) cls.asClass
2371- else cls.info.parents match {
2372- case parentRef :: _ => realClassParent(parentRef.typeSymbol)
2373- case nil => defn.ObjectClass
2374- }
2375- def improve (candidate : ClassSymbol , parent : Type ): ClassSymbol = {
2376- val pcls = realClassParent(parent.classSymbol)
2377- if (pcls derivesFrom candidate) pcls else candidate
2378- }
2379- parents match {
2380- case p :: _ if p.classSymbol.isRealClass => parents
2381- case _ =>
2382- val pcls = parents.foldLeft(defn.ObjectClass )(improve)
2383- typr.println(i " ensure first is class $parents%, % --> ${parents map (_ baseType pcls)}%, % " )
2384- val first = TypeComparer .glb(defn.ObjectType :: parents.map(_.baseType(pcls)))
2385- checkFeasibleParent(first, ctx.source.atSpan(span), em " in inferred superclass $first" ) :: parents
2386- }
2387- }
2382+ def ensureConstrCall (cls : ClassSymbol , parents : List [Tree ])(using Context ): List [Tree ] = parents match
2383+ case parents @ (first :: others) =>
2384+ parents.derivedCons(ensureConstrCall(cls, first), others)
2385+ case parents =>
2386+ parents
23882387
2389- /** Ensure that first parent tree refers to a real class. */
2390- def ensureFirstTreeIsClass (parents : List [Tree ], span : Span )(using Context ): List [Tree ] = parents match {
2391- case p :: ps if p.tpe.classSymbol.isRealClass => parents
2392- case _ => TypeTree (ensureFirstIsClass(parents.tpes, span).head).withSpan(span.focus) :: parents
2393- }
2394-
2395- /** If this is a real class, make sure its first parent is a
2388+ /** If this is a real class, make sure its first parent is a
23962389 * constructor call. Cannot simply use a type. Overridden in ReTyper.
23972390 */
2398- def ensureConstrCall (cls : ClassSymbol , parents : List [Tree ])(using Context ): List [Tree ] = {
2399- val firstParent :: otherParents = parents
2400- if (firstParent.isType && ! cls.is(Trait ) && ! cls.is(JavaDefined ))
2401- typed(untpd.New (untpd.TypedSplice (firstParent), Nil )) :: otherParents
2402- else parents
2403- }
2391+ def ensureConstrCall (cls : ClassSymbol , parent : Tree )(using Context ): Tree =
2392+ if (parent.isType && ! cls.is(Trait ) && ! cls.is(JavaDefined ))
2393+ typed(untpd.New (untpd.TypedSplice (parent), Nil ))
2394+ else
2395+ parent
24042396
24052397 def localDummy (cls : ClassSymbol , impl : untpd.Template )(using Context ): Symbol =
24062398 newLocalDummy(cls, impl.span)
0 commit comments