@@ -2212,20 +2212,18 @@ class Typer extends Namer
2212
2212
* @param psym Its type symbol
2213
2213
* @param cinfo The info of its constructor
2214
2214
*/
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
2216
2216
case cinfo @ MethodType (Nil ) if cinfo.resultType.isImplicitMethod =>
2217
2217
typedExpr(untpd.New (untpd.TypedSplice (ref)(using superCtx), Nil ))(using superCtx)
2218
2218
case cinfo @ MethodType (Nil ) if ! cinfo.resultType.isInstanceOf [MethodType ] =>
2219
2219
ref
2220
2220
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.
2222
2222
typr.println(i " constr type: $cinfo" )
2223
2223
report.error(ParameterizedTypeLacksArguments (psym), ref.srcPos)
2224
- }
2225
2224
ref
2226
2225
case _ =>
2227
2226
ref
2228
- }
2229
2227
2230
2228
val seenParents = mutable.Set [Symbol ]()
2231
2229
@@ -2250,14 +2248,35 @@ class Typer extends Namer
2250
2248
if (tree.isType) {
2251
2249
checkSimpleKinded(result) // Not needed for constructor calls, as type arguments will be inferred.
2252
2250
if (psym.is(Trait ) && ! cls.is(Trait ) && ! cls.superClass.isSubClass(psym))
2253
- result = maybeCall(result, psym, psym.primaryConstructor.info )
2251
+ result = maybeCall(result, psym)
2254
2252
}
2255
2253
else checkParentCall(result, cls)
2256
2254
checkTraitInheritance(psym, cls, tree.srcPos)
2257
2255
if (cls is Case ) checkCaseInheritance(psym, cls, tree.srcPos)
2258
2256
result
2259
2257
}
2260
2258
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
+
2261
2280
/** Checks if one of the decls is a type with the same name as class type member in selfType */
2262
2281
def classExistsOnSelf (decls : Scope , self : tpd.ValDef ): Boolean = {
2263
2282
val selfType = self.tpt.tpe
@@ -2278,8 +2297,10 @@ class Typer extends Namer
2278
2297
2279
2298
completeAnnotations(cdef, cls)
2280
2299
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)
2283
2304
val firstParentTpe = parents1.head.tpe.dealias
2284
2305
val firstParent = firstParentTpe.typeSymbol
2285
2306
@@ -2348,52 +2369,23 @@ class Typer extends Namer
2348
2369
protected def addAccessorDefs (cls : Symbol , body : List [Tree ])(using Context ): List [Tree ] =
2349
2370
ctx.compilationUnit.inlineAccessors.addAccessorDefs(cls, body)
2350
2371
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.
2359
2374
*/
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
2381
2380
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
2389
2382
* constructor call. Cannot simply use a type. Overridden in ReTyper.
2390
2383
*/
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
2397
2389
2398
2390
def localDummy (cls : ClassSymbol , impl : untpd.Template )(using Context ): Symbol =
2399
2391
newLocalDummy(cls, impl.span)
0 commit comments