@@ -2426,65 +2426,32 @@ 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) {
2480- 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)
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 parent.isType then
2446+ if ! result.symbol.info.takesImplicitParams then
2447+ checkSimpleKinded(parent)
2448+ // allow missing type parameters if there are implicit arguments to pass
2449+ // since we can infer type arguments from them
2450+ else
2451+ checkParentCall(result, cls)
2452+ if cls is Case then
2453+ checkCaseInheritance(psym, cls, tree.srcPos)
24862454 result
2487- }
24882455
24892456 def ensureCorrectSuperClass (): Unit =
24902457 val parents0 = cls.classInfo.declaredParents
@@ -2499,23 +2466,27 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
24992466 /** Augment `ptrees` to have the same class symbols as `parents`. Generate TypeTrees
25002467 * or New trees to fill in any parents for which no tree exists yet.
25012468 */
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
2469+ def parentTrees (parents : List [Type ], ptrees : List [Tree ]): List [Tree ] =
2470+ if ptrees.exists(_.tpe.isError) then ptrees
2471+ else parents match
2472+ case parent :: parents1 =>
2473+ val psym = parent.classSymbol
2474+ def hasSameParent (ptree : Tree ) =
2475+ psym == (
2476+ if ptree.symbol.isConstructor then ptree.symbol.owner
2477+ else ptree.tpe.classSymbol
2478+ )
2479+ ptrees match
2480+ case ptree :: ptrees1 if hasSameParent(ptree) =>
2481+ ptree :: parentTrees(parents1, ptrees1)
2482+ case ptree :: ptrees1 if ptrees1.exists(hasSameParent) =>
2483+ ptree :: parentTrees(parents, ptrees1)
2484+ case _ =>
2485+ val added : Tree = ensureConstrCall(
2486+ cls, TypeTree (parent).withSpan(cdef.nameSpan.focus), psym)(using superCtx)
2487+ added :: parentTrees(parents1, ptrees)
2488+ case _ =>
2489+ ptrees
25192490
25202491 /** Checks if one of the decls is a type with the same name as class type member in selfType */
25212492 def classExistsOnSelf (decls : Scope , self : tpd.ValDef ): Boolean = {
@@ -2538,10 +2509,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
25382509 ensureCorrectSuperClass()
25392510 completeAnnotations(cdef, cls)
25402511 val constr1 = typed(constr).asInstanceOf [DefDef ]
2541- val parents0 = parentTrees(
2512+ val parents1 = parentTrees(
25422513 cls.classInfo.declaredParents,
25432514 parents.mapconserve(typedParent).filterConserve(! _.isEmpty))
2544- val parents1 = ensureConstrCall(cls, parents0)(using superCtx)
25452515 val firstParentTpe = parents1.head.tpe.dealias
25462516 val firstParent = firstParentTpe.typeSymbol
25472517
@@ -2610,23 +2580,19 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
26102580 protected def addAccessorDefs (cls : Symbol , body : List [Tree ])(using Context ): List [Tree ] =
26112581 PrepareInlineable .addAccessorDefs(cls, body)
26122582
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.
2583+ /** Turn a parent type into a constructor call where needed. This is the case where
2584+ * - we are in a Scala class or module (not a Java class, nor a trait), and
2585+ * - the parent symbol is a non-trait class, or
2586+ * - the parent symbol is a trait that takes at least one (explicit or implicit) parameter
2587+ * and the parent symbol is directly extended by the current class (i.e. not
2588+ * extended by the superclass).
26152589 */
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.
2624- */
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
2590+ def ensureConstrCall (cls : ClassSymbol , parent : Tree , psym : Symbol )(using Context ): Tree =
2591+ if parent.isType && ! cls.is(Trait ) && ! cls.is(JavaDefined ) && psym.isClass
2592+ && (! psym.is(Trait )
2593+ || psym.primaryConstructor.info.takesParams && ! 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