@@ -2426,65 +2426,29 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
2426
2426
val TypeDef (name, impl @ Template (constr, _, self, _)) = cdef : @ unchecked
2427
2427
val parents = impl.parents
2428
2428
val superCtx = ctx.superCallContext
2429
-
2430
- /** If `ref` is an implicitly parameterized trait, pass an implicit argument list.
2431
- * Otherwise, if `ref` is a parameterized trait, error.
2432
- * Note: Traits and classes have sometimes a synthesized empty parameter list ()
2433
- * in front or after the implicit parameter(s). See NamerOps.normalizeIfConstructor.
2434
- * We synthesize a () argument at the correct place in this case.
2435
- * @param ref The tree referring to the (parent) trait
2436
- * @param psym Its type symbol
2437
- */
2438
- def maybeCall (ref : Tree , psym : Symbol ): Tree =
2439
- def appliedRef =
2440
- typedExpr(untpd.New (untpd.TypedSplice (ref)(using superCtx), Nil ))(using superCtx)
2441
- def dropContextual (tp : Type ): Type = tp.stripPoly match
2442
- case mt : MethodType if mt.isContextualMethod => dropContextual(mt.resType)
2443
- case _ => tp
2444
- psym.primaryConstructor.info.stripPoly match
2445
- case cinfo @ MethodType (Nil )
2446
- if cinfo.resultType.isImplicitMethod && ! cinfo.resultType.isContextualMethod =>
2447
- appliedRef
2448
- case cinfo =>
2449
- val cinfo1 = dropContextual(cinfo)
2450
- cinfo1 match
2451
- case cinfo1 @ MethodType (Nil ) if ! cinfo1.resultType.isInstanceOf [MethodType ] =>
2452
- if cinfo1 ne cinfo then appliedRef else ref
2453
- case cinfo1 : MethodType if ! ctx.erasedTypes =>
2454
- report.error(ParameterizedTypeLacksArguments (psym), ref.srcPos)
2455
- ref
2456
- case _ =>
2457
- ref
2458
-
2459
2429
val seenParents = mutable.Set [Symbol ]()
2460
2430
2461
- def typedParent (tree : untpd.Tree ): Tree = {
2462
- def isTreeType (t : untpd.Tree ): Boolean = t match {
2463
- case _ : untpd.Apply => false
2464
- case _ => true
2465
- }
2466
- var result =
2467
- if isTreeType(tree) then typedType(tree)(using superCtx)
2468
- else typedExpr(tree)(using superCtx)
2469
- val psym = result.tpe.dealias.typeSymbol
2470
- if (seenParents.contains(psym) && ! cls.isRefinementClass) {
2471
- // Desugaring can adds parents to classes, but we don't want to emit an
2431
+ def typedParent (tree : untpd.Tree ): Tree =
2432
+ val parent = tree match
2433
+ case _ : untpd.Apply => typedExpr(tree)(using superCtx)
2434
+ case _ => typedType(tree)(using superCtx)
2435
+ val psym = parent.tpe.dealias.typeSymbol
2436
+ if seenParents.contains(psym) && ! cls.isRefinementClass then
2437
+ // Desugaring can add parents to classes, but we don't want to emit an
2472
2438
// error if the same parent was explicitly added in user code.
2473
- if ( ! tree.span.isSourceDerived)
2439
+ if ! tree.span.isSourceDerived then
2474
2440
return EmptyTree
2475
-
2476
- if ( ! ctx.isAfterTyper) report.error( i " $psym is extended twice " , tree.srcPos)
2477
- }
2478
- else seenParents += psym
2479
- if (tree .isType) {
2441
+ if ! ctx.isAfterTyper then report.error( i " $psym is extended twice " , tree.srcPos)
2442
+ else
2443
+ seenParents += psym
2444
+ val result = ensureConstrCall(cls, parent, psym)( using superCtx)
2445
+ if result .isType then
2480
2446
checkSimpleKinded(result) // Not needed for constructor calls, as type arguments will be inferred.
2481
- if (psym.is(Trait ) && ! cls.is(Trait ) && ! cls.superClass.isSubClass(psym))
2482
- result = maybeCall(result, psym)
2483
- }
2484
- else checkParentCall(result, cls)
2485
- if (cls is Case ) checkCaseInheritance(psym, cls, tree.srcPos)
2447
+ else
2448
+ checkParentCall(result, cls)
2449
+ if cls is Case then
2450
+ checkCaseInheritance(psym, cls, tree.srcPos)
2486
2451
result
2487
- }
2488
2452
2489
2453
def ensureCorrectSuperClass (): Unit =
2490
2454
val parents0 = cls.classInfo.declaredParents
@@ -2499,23 +2463,27 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
2499
2463
/** Augment `ptrees` to have the same class symbols as `parents`. Generate TypeTrees
2500
2464
* or New trees to fill in any parents for which no tree exists yet.
2501
2465
*/
2502
- def parentTrees (parents : List [Type ], ptrees : List [Tree ]): List [Tree ] = parents match
2503
- case parent :: parents1 =>
2504
- val psym = parent.classSymbol
2505
- def hasSameParent (ptree : Tree ) = ptree.tpe.classSymbol == psym
2506
- ptrees match
2507
- case ptree :: ptrees1 if hasSameParent(ptree) =>
2508
- ptree :: parentTrees(parents1, ptrees1)
2509
- case ptree :: ptrees1 if ptrees1.exists(hasSameParent) =>
2510
- ptree :: parentTrees(parents, ptrees1)
2511
- case _ =>
2512
- var added : Tree = TypeTree (parent).withSpan(cdef.nameSpan.focus)
2513
- if psym.is(Trait ) && psym.primaryConstructor.info.takesImplicitParams then
2514
- // classes get a constructor separately using a different context
2515
- added = ensureConstrCall(cls, added)(using superCtx)
2516
- added :: parentTrees(parents1, ptrees)
2517
- case _ =>
2518
- ptrees
2466
+ def parentTrees (parents : List [Type ], ptrees : List [Tree ]): List [Tree ] =
2467
+ if ptrees.exists(_.tpe.isError) then ptrees
2468
+ else parents match
2469
+ case parent :: parents1 =>
2470
+ val psym = parent.classSymbol
2471
+ def hasSameParent (ptree : Tree ) =
2472
+ psym == (
2473
+ if ptree.symbol.isConstructor then ptree.symbol.owner
2474
+ else ptree.tpe.classSymbol
2475
+ )
2476
+ ptrees match
2477
+ case ptree :: ptrees1 if hasSameParent(ptree) =>
2478
+ ptree :: parentTrees(parents1, ptrees1)
2479
+ case ptree :: ptrees1 if ptrees1.exists(hasSameParent) =>
2480
+ ptree :: parentTrees(parents, ptrees1)
2481
+ case _ =>
2482
+ val added : Tree = ensureConstrCall(
2483
+ cls, TypeTree (parent).withSpan(cdef.nameSpan.focus), psym)(using superCtx)
2484
+ added :: parentTrees(parents1, ptrees)
2485
+ case _ =>
2486
+ ptrees
2519
2487
2520
2488
/** Checks if one of the decls is a type with the same name as class type member in selfType */
2521
2489
def classExistsOnSelf (decls : Scope , self : tpd.ValDef ): Boolean = {
@@ -2538,10 +2506,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
2538
2506
ensureCorrectSuperClass()
2539
2507
completeAnnotations(cdef, cls)
2540
2508
val constr1 = typed(constr).asInstanceOf [DefDef ]
2541
- val parents0 = parentTrees(
2509
+ val parents1 = parentTrees(
2542
2510
cls.classInfo.declaredParents,
2543
2511
parents.mapconserve(typedParent).filterConserve(! _.isEmpty))
2544
- val parents1 = ensureConstrCall(cls, parents0)(using superCtx)
2545
2512
val firstParentTpe = parents1.head.tpe.dealias
2546
2513
val firstParent = firstParentTpe.typeSymbol
2547
2514
@@ -2610,23 +2577,22 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
2610
2577
protected def addAccessorDefs (cls : Symbol , body : List [Tree ])(using Context ): List [Tree ] =
2611
2578
PrepareInlineable .addAccessorDefs(cls, body)
2612
2579
2613
- /** If this is a real class, make sure its first parent is a
2614
- * constructor call. Cannot simply use a type. Overridden in ReTyper.
2615
- */
2616
- def ensureConstrCall (cls : ClassSymbol , parents : List [Tree ])(using Context ): List [Tree ] = parents match
2617
- case parents @ (first :: others) =>
2618
- parents.derivedCons(ensureConstrCall(cls, first), others)
2619
- case parents =>
2620
- parents
2621
-
2622
- /** If this is a real class, make sure its first parent is a
2623
- * constructor call. Cannot simply use a type. Overridden in ReTyper.
2580
+ /** Turn a parent type into a constructor call where needed. This is the case where
2581
+ * - we are in a Scala class or module (not a Java class, nor a trait), and
2582
+ * - the parent symbol is a non-trait class, or
2583
+ * - the parent symbol is a trait that takes at least one (explicit or implicit) parameter
2584
+ * and the parent symbol is directly extended by the current class (i.e. not
2585
+ * extended by the superclass).
2624
2586
*/
2625
- def ensureConstrCall (cls : ClassSymbol , parent : Tree )(using Context ): Tree =
2626
- if (parent.isType && ! cls.is(Trait ) && ! cls.is(JavaDefined ))
2627
- typed(untpd.New (untpd.TypedSplice (parent), Nil ))
2628
- else
2629
- parent
2587
+ def ensureConstrCall (cls : ClassSymbol , parent : Tree , psym : Symbol )(using Context ): Tree =
2588
+ def takesParams (info : Type ): Boolean = info.stripPoly match
2589
+ case mt @ MethodType (pnames) => pnames.nonEmpty || takesParams(mt.resType)
2590
+ case _ => false
2591
+ if parent.isType && ! cls.is(Trait ) && ! cls.is(JavaDefined ) && psym.isClass
2592
+ && (! psym.is(Trait )
2593
+ || takesParams(psym.primaryConstructor.info) && ! cls.superClass.isSubClass(psym))
2594
+ then typed(untpd.New (untpd.TypedSplice (parent), Nil ))
2595
+ else parent
2630
2596
2631
2597
def localDummy (cls : ClassSymbol , impl : untpd.Template )(using Context ): Symbol =
2632
2598
newLocalDummy(cls, impl.span)
0 commit comments