@@ -2212,20 +2212,18 @@ class Typer extends Namer
22122212 * @param psym Its type symbol
22132213 * @param cinfo The info of its constructor
22142214 */
2215- def maybeCall (ref : Tree , psym : Symbol , cinfo : Type ): Tree = cinfo. stripPoly match {
2215+ def maybeCall (ref : Tree , psym : Symbol ): Tree = psym.primaryConstructor.info. stripPoly match
22162216 case cinfo @ MethodType (Nil ) if cinfo.resultType.isImplicitMethod =>
22172217 typedExpr(untpd.New (untpd.TypedSplice (ref)(using superCtx), Nil ))(using superCtx)
22182218 case cinfo @ MethodType (Nil ) if ! cinfo.resultType.isInstanceOf [MethodType ] =>
22192219 ref
22202220 case cinfo : MethodType =>
2221- if ( ! ctx.erasedTypes) { // after constructors arguments are passed in super call.
2221+ if ! ctx.erasedTypes then // after constructors arguments are passed in super call.
22222222 typr.println(i " constr type: $cinfo" )
22232223 report.error(ParameterizedTypeLacksArguments (psym), ref.srcPos)
2224- }
22252224 ref
22262225 case _ =>
22272226 ref
2228- }
22292227
22302228 val seenParents = mutable.Set [Symbol ]()
22312229
@@ -2250,14 +2248,35 @@ class Typer extends Namer
22502248 if (tree.isType) {
22512249 checkSimpleKinded(result) // Not needed for constructor calls, as type arguments will be inferred.
22522250 if (psym.is(Trait ) && ! cls.is(Trait ) && ! cls.superClass.isSubClass(psym))
2253- result = maybeCall(result, psym, psym.primaryConstructor.info )
2251+ result = maybeCall(result, psym)
22542252 }
22552253 else checkParentCall(result, cls)
22562254 checkTraitInheritance(psym, cls, tree.srcPos)
22572255 if (cls is Case ) checkCaseInheritance(psym, cls, tree.srcPos)
22582256 result
22592257 }
22602258
2259+ /** Augment `ptrees` to have the same class symbols as `parents`. Generate TypeTrees
2260+ * or New trees to fill in any parents for which no tree exists yet.
2261+ */
2262+ def parentTrees (parents : List [Type ], ptrees : List [Tree ]): List [Tree ] = parents match
2263+ case parent :: parents1 =>
2264+ val psym = parent.classSymbol
2265+ def hasSameParent (ptree : Tree ) = ptree.tpe.classSymbol == psym
2266+ ptrees match
2267+ case ptree :: ptrees1 if hasSameParent(ptree) =>
2268+ ptree :: parentTrees(parents1, ptrees1)
2269+ case ptree :: ptrees1 if ptrees1.exists(hasSameParent) =>
2270+ ptree :: parentTrees(parents, ptrees1)
2271+ case _ =>
2272+ var added : Tree = TypeTree (parent).withSpan(cdef.nameSpan.focus)
2273+ if psym.is(Trait ) && psym.primaryConstructor.info.takesImplicitParams then
2274+ // classes get a constructor separately using a different context
2275+ added = ensureConstrCall(cls, added)
2276+ added :: parentTrees(parents1, ptrees)
2277+ case _ =>
2278+ ptrees
2279+
22612280 /** Checks if one of the decls is a type with the same name as class type member in selfType */
22622281 def classExistsOnSelf (decls : Scope , self : tpd.ValDef ): Boolean = {
22632282 val selfType = self.tpt.tpe
@@ -2278,8 +2297,10 @@ class Typer extends Namer
22782297
22792298 completeAnnotations(cdef, cls)
22802299 val constr1 = typed(constr).asInstanceOf [DefDef ]
2281- val parentsWithClass = ensureFirstTreeIsClass(parents.mapconserve(typedParent).filterConserve(! _.isEmpty), cdef.nameSpan)
2282- val parents1 = ensureConstrCall(cls, parentsWithClass)(using superCtx)
2300+ val parents0 = parentTrees(
2301+ cls.classInfo.declaredParents,
2302+ parents.mapconserve(typedParent).filterConserve(! _.isEmpty))
2303+ val parents1 = ensureConstrCall(cls, parents0)(using superCtx)
22832304 val firstParentTpe = parents1.head.tpe.dealias
22842305 val firstParent = firstParentTpe.typeSymbol
22852306
@@ -2348,52 +2369,23 @@ class Typer extends Namer
23482369 protected def addAccessorDefs (cls : Symbol , body : List [Tree ])(using Context ): List [Tree ] =
23492370 ctx.compilationUnit.inlineAccessors.addAccessorDefs(cls, body)
23502371
2351- /** Ensure that the first type in a list of parent types Ps points to a non-trait class.
2352- * If that's not already the case, add one. The added class type CT is determined as follows.
2353- * First, let C be the unique class such that
2354- * - there is a parent P_i such that P_i derives from C, and
2355- * - for every class D: If some parent P_j, j <= i derives from D, then C derives from D.
2356- * Then, let CT be the smallest type which
2357- * - has C as its class symbol, and
2358- * - for all parents P_i: If P_i derives from C then P_i <:< CT.
2372+ /** If this is a real class, make sure its first parent is a
2373+ * constructor call. Cannot simply use a type. Overridden in ReTyper.
23592374 */
2360- def ensureFirstIsClass (parents : List [Type ], span : Span )(using Context ): List [Type ] = {
2361- def realClassParent (cls : Symbol ): ClassSymbol =
2362- if (! cls.isClass) defn.ObjectClass
2363- else if (! cls.is(Trait )) cls.asClass
2364- else cls.info.parents match {
2365- case parentRef :: _ => realClassParent(parentRef.typeSymbol)
2366- case nil => defn.ObjectClass
2367- }
2368- def improve (candidate : ClassSymbol , parent : Type ): ClassSymbol = {
2369- val pcls = realClassParent(parent.classSymbol)
2370- if (pcls derivesFrom candidate) pcls else candidate
2371- }
2372- parents match {
2373- case p :: _ if p.classSymbol.isRealClass => parents
2374- case _ =>
2375- val pcls = parents.foldLeft(defn.ObjectClass )(improve)
2376- typr.println(i " ensure first is class $parents%, % --> ${parents map (_ baseType pcls)}%, % " )
2377- val first = TypeComparer .glb(defn.ObjectType :: parents.map(_.baseType(pcls)))
2378- checkFeasibleParent(first, ctx.source.atSpan(span), em " in inferred superclass $first" ) :: parents
2379- }
2380- }
2375+ def ensureConstrCall (cls : ClassSymbol , parents : List [Tree ])(using Context ): List [Tree ] = parents match
2376+ case parents @ (first :: others) =>
2377+ parents.derivedCons(ensureConstrCall(cls, first), others)
2378+ case parents =>
2379+ parents
23812380
2382- /** Ensure that first parent tree refers to a real class. */
2383- def ensureFirstTreeIsClass (parents : List [Tree ], span : Span )(using Context ): List [Tree ] = parents match {
2384- case p :: ps if p.tpe.classSymbol.isRealClass => parents
2385- case _ => TypeTree (ensureFirstIsClass(parents.tpes, span).head).withSpan(span.focus) :: parents
2386- }
2387-
2388- /** If this is a real class, make sure its first parent is a
2381+ /** If this is a real class, make sure its first parent is a
23892382 * constructor call. Cannot simply use a type. Overridden in ReTyper.
23902383 */
2391- def ensureConstrCall (cls : ClassSymbol , parents : List [Tree ])(using Context ): List [Tree ] = {
2392- val firstParent :: otherParents = parents
2393- if (firstParent.isType && ! cls.is(Trait ) && ! cls.is(JavaDefined ))
2394- typed(untpd.New (untpd.TypedSplice (firstParent), Nil )) :: otherParents
2395- else parents
2396- }
2384+ def ensureConstrCall (cls : ClassSymbol , parent : Tree )(using Context ): Tree =
2385+ if (parent.isType && ! cls.is(Trait ) && ! cls.is(JavaDefined ))
2386+ typed(untpd.New (untpd.TypedSplice (parent), Nil ))
2387+ else
2388+ parent
23972389
23982390 def localDummy (cls : ClassSymbol , impl : untpd.Template )(using Context ): Symbol =
23992391 newLocalDummy(cls, impl.span)
0 commit comments