@@ -2426,65 +2426,29 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
24262426 val TypeDef (name, impl @ Template (constr, _, self, _)) = cdef : @ unchecked
24272427 val parents = impl.parents
24282428 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-
24592429 val seenParents = mutable.Set [Symbol ]()
24602430
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
24722438 // error if the same parent was explicitly added in user code.
2473- if ( ! tree.span.isSourceDerived)
2439+ if ! tree.span.isSourceDerived then
24742440 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
24802446 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)
24862451 result
2487- }
24882452
24892453 def ensureCorrectSuperClass (): Unit =
24902454 val parents0 = cls.classInfo.declaredParents
@@ -2499,23 +2463,27 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
24992463 /** Augment `ptrees` to have the same class symbols as `parents`. Generate TypeTrees
25002464 * or New trees to fill in any parents for which no tree exists yet.
25012465 */
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
25192487
25202488 /** Checks if one of the decls is a type with the same name as class type member in selfType */
25212489 def classExistsOnSelf (decls : Scope , self : tpd.ValDef ): Boolean = {
@@ -2538,10 +2506,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
25382506 ensureCorrectSuperClass()
25392507 completeAnnotations(cdef, cls)
25402508 val constr1 = typed(constr).asInstanceOf [DefDef ]
2541- val parents0 = parentTrees(
2509+ val parents1 = parentTrees(
25422510 cls.classInfo.declaredParents,
25432511 parents.mapconserve(typedParent).filterConserve(! _.isEmpty))
2544- val parents1 = ensureConstrCall(cls, parents0)(using superCtx)
25452512 val firstParentTpe = parents1.head.tpe.dealias
25462513 val firstParent = firstParentTpe.typeSymbol
25472514
@@ -2610,23 +2577,22 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
26102577 protected def addAccessorDefs (cls : Symbol , body : List [Tree ])(using Context ): List [Tree ] =
26112578 PrepareInlineable .addAccessorDefs(cls, body)
26122579
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).
26242586 */
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
26302596
26312597 def localDummy (cls : ClassSymbol , impl : untpd.Template )(using Context ): Symbol =
26322598 newLocalDummy(cls, impl.span)
0 commit comments