@@ -8,7 +8,7 @@ import Symbols._, StdNames._, Trees._
88import Decorators ._ , transform .SymUtils ._
99import NameKinds .{UniqueName , EvidenceParamName , DefaultGetterName }
1010import typer .FrontEnd
11- import util .{Property , SourceFile }
11+ import util .{Property , SourceFile , SourcePosition }
1212import collection .mutable .ListBuffer
1313import reporting .diagnostic .messages ._
1414import reporting .trace
@@ -23,7 +23,13 @@ object desugar {
2323 /** If a Select node carries this attachment, suppress the check
2424 * that its type refers to an acessible symbol.
2525 */
26- val SuppressAccessCheck = new Property .Key [Unit ]
26+ val SuppressAccessCheck : Property .Key [Unit ] = new Property .Key
27+
28+ /** An attachment for companion modules of classes that have a `derives` clause.
29+ * The position value indicates the start position of the template of the
30+ * deriving class.
31+ */
32+ val DerivingCompanion : Property .Key [SourcePosition ] = new Property .Key
2733
2834 /** Info of a variable in a pattern: The named tree and its type */
2935 private type VarInfo = (NameTree , Tree )
@@ -297,7 +303,8 @@ object desugar {
297303 /** The expansion of a class definition. See inline comments for what is involved */
298304 def classDef (cdef : TypeDef )(implicit ctx : Context ): Tree = {
299305 val className = checkNotReservedName(cdef).asTypeName
300- val impl @ Template (constr0, parents, self, _) = cdef.rhs
306+ val impl @ Template (_, _, self, _) = cdef.rhs
307+ val parents = impl.parents
301308 val mods = cdef.mods
302309 val companionMods = mods
303310 .withFlags((mods.flags & (AccessFlags | Final )).toCommonFlags)
@@ -312,7 +319,7 @@ object desugar {
312319 meth
313320 }
314321
315- val constr1 = decompose(defDef(constr0 , isPrimaryConstructor = true ))
322+ val constr1 = decompose(defDef(impl.constr , isPrimaryConstructor = true ))
316323
317324 // The original type and value parameters in the constructor already have the flags
318325 // needed to be type members (i.e. param, and possibly also private and local unless
@@ -557,14 +564,23 @@ object desugar {
557564 }
558565 def eqInstances = if (isEnum) eqInstance :: Nil else Nil
559566
567+ // derived type classes of non-module classes go to their companions
568+ val (clsDerived, companionDerived) =
569+ if (mods.is(Module )) (impl.derived, Nil ) else (Nil , impl.derived)
570+
560571 // The thicket which is the desugared version of the companion object
561- // synthetic object C extends parentTpt { defs }
562- def companionDefs (parentTpt : Tree , defs : List [Tree ]) =
563- moduleDef(
572+ // synthetic object C extends parentTpt derives class-derived { defs }
573+ def companionDefs (parentTpt : Tree , defs : List [Tree ]) = {
574+ val mdefs = moduleDef(
564575 ModuleDef (
565- className.toTermName, Template (emptyConstructor, parentTpt :: Nil , EmptyValDef , defs))
576+ className.toTermName, Template (emptyConstructor, parentTpt :: Nil , companionDerived, EmptyValDef , defs))
566577 .withMods(companionMods | Synthetic ))
567- .withSpan(cdef.span).toList
578+ .withSpan(cdef.span).toList
579+ if (companionDerived.nonEmpty)
580+ for (modClsDef @ TypeDef (_, _) <- mdefs)
581+ modClsDef.putAttachment(DerivingCompanion , impl.sourcePos.startPos)
582+ mdefs
583+ }
568584
569585 val companionMembers = defaultGetters ::: eqInstances ::: enumCases
570586
@@ -613,10 +629,10 @@ object desugar {
613629 }
614630 companionDefs(companionParent, applyMeths ::: unapplyMeth :: companionMembers)
615631 }
616- else if (companionMembers.nonEmpty)
632+ else if (companionMembers.nonEmpty || companionDerived.nonEmpty )
617633 companionDefs(anyRef, companionMembers)
618634 else if (isValueClass) {
619- constr0 .vparamss match {
635+ impl.constr .vparamss match {
620636 case (_ :: Nil ) :: _ => companionDefs(anyRef, Nil )
621637 case _ => Nil // error will be emitted in typer
622638 }
@@ -675,7 +691,7 @@ object desugar {
675691 }
676692 cpy.TypeDef (cdef : TypeDef )(
677693 name = className,
678- rhs = cpy.Template (impl)(constr, parents1, self1,
694+ rhs = cpy.Template (impl)(constr, parents1, clsDerived, self1,
679695 tparamAccessors ::: vparamAccessors ::: normalizedBody ::: caseClassMeths)): TypeDef
680696 }
681697
@@ -772,7 +788,7 @@ object desugar {
772788 val localType = tdef.withMods(Modifiers (Synthetic | Opaque ).withPrivateWithin(tdef.name))
773789
774790 val companions = moduleDef(ModuleDef (
775- moduleName, Template (emptyConstructor, Nil , EmptyValDef , localType :: Nil ))
791+ moduleName, Template (emptyConstructor, Nil , Nil , EmptyValDef , localType :: Nil ))
776792 .withFlags(Synthetic | Opaque ))
777793 Thicket (aliasType :: companions.toList)
778794 }
@@ -1335,7 +1351,7 @@ object desugar {
13351351 val (classParents, self) =
13361352 if (parentCores.length == 1 && (parent.tpe eq parentCores.head)) (untpdParent :: Nil , EmptyValDef )
13371353 else (parentCores map TypeTree , ValDef (nme.WILDCARD , untpdParent, EmptyTree ))
1338- val impl = Template (emptyConstructor, classParents, self, refinements)
1354+ val impl = Template (emptyConstructor, classParents, Nil , self, refinements)
13391355 TypeDef (tpnme.REFINE_CLASS , impl).withFlags(Trait )
13401356 }
13411357
0 commit comments