@@ -2219,20 +2219,18 @@ class Typer extends Namer
2219
2219
* @param psym Its type symbol
2220
2220
* @param cinfo The info of its constructor
2221
2221
*/
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
2223
2223
case cinfo @ MethodType (Nil ) if cinfo.resultType.isImplicitMethod =>
2224
2224
typedExpr(untpd.New (untpd.TypedSplice (ref)(using superCtx), Nil ))(using superCtx)
2225
2225
case cinfo @ MethodType (Nil ) if ! cinfo.resultType.isInstanceOf [MethodType ] =>
2226
2226
ref
2227
2227
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.
2229
2229
typr.println(i " constr type: $cinfo" )
2230
2230
report.error(ParameterizedTypeLacksArguments (psym), ref.srcPos)
2231
- }
2232
2231
ref
2233
2232
case _ =>
2234
2233
ref
2235
- }
2236
2234
2237
2235
val seenParents = mutable.Set [Symbol ]()
2238
2236
@@ -2257,14 +2255,35 @@ class Typer extends Namer
2257
2255
if (tree.isType) {
2258
2256
checkSimpleKinded(result) // Not needed for constructor calls, as type arguments will be inferred.
2259
2257
if (psym.is(Trait ) && ! cls.is(Trait ) && ! cls.superClass.isSubClass(psym))
2260
- result = maybeCall(result, psym, psym.primaryConstructor.info )
2258
+ result = maybeCall(result, psym)
2261
2259
}
2262
2260
else checkParentCall(result, cls)
2263
2261
checkTraitInheritance(psym, cls, tree.srcPos)
2264
2262
if (cls is Case ) checkCaseInheritance(psym, cls, tree.srcPos)
2265
2263
result
2266
2264
}
2267
2265
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
+
2268
2287
/** Checks if one of the decls is a type with the same name as class type member in selfType */
2269
2288
def classExistsOnSelf (decls : Scope , self : tpd.ValDef ): Boolean = {
2270
2289
val selfType = self.tpt.tpe
@@ -2285,8 +2304,10 @@ class Typer extends Namer
2285
2304
2286
2305
completeAnnotations(cdef, cls)
2287
2306
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)
2290
2311
val firstParentTpe = parents1.head.tpe.dealias
2291
2312
val firstParent = firstParentTpe.typeSymbol
2292
2313
@@ -2355,52 +2376,23 @@ class Typer extends Namer
2355
2376
protected def addAccessorDefs (cls : Symbol , body : List [Tree ])(using Context ): List [Tree ] =
2356
2377
ctx.compilationUnit.inlineAccessors.addAccessorDefs(cls, body)
2357
2378
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.
2366
2381
*/
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
2388
2387
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
2396
2389
* constructor call. Cannot simply use a type. Overridden in ReTyper.
2397
2390
*/
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
2404
2396
2405
2397
def localDummy (cls : ClassSymbol , impl : untpd.Template )(using Context ): Symbol =
2406
2398
newLocalDummy(cls, impl.span)
0 commit comments