@@ -40,7 +40,11 @@ object desugar {
4040 def derivedType (sym : Symbol )(implicit ctx : Context ) = sym.typeRef
4141 }
4242
43- class DerivedFromParamTree extends DerivedTypeTree {
43+ /** A type tree that computes its type from an existing parameter.
44+ * @param suffix String difference between existing parameter (call it `P`) and parameter owning the
45+ * DerivedTypeTree (call it `O`). We have: `O.name == P.name + suffix`.
46+ */
47+ class DerivedFromParamTree (suffix : String ) extends DerivedTypeTree {
4448
4549 /** Make sure that for all enclosing module classes their companion lasses
4650 * are completed. Reason: We need the constructor of such companion classes to
@@ -58,24 +62,28 @@ object desugar {
5862
5963 /** Return info of original symbol, where all references to siblings of the
6064 * original symbol (i.e. sibling and original symbol have the same owner)
61- * are rewired to same -named parameters or accessors in the scope enclosing
65+ * are rewired to like -named* parameters or accessors in the scope enclosing
6266 * the current scope. The current scope is the scope owned by the defined symbol
6367 * itself, that's why we have to look one scope further out. If the resulting
6468 * type is an alias type, dealias it. This is necessary because the
6569 * accessor of a type parameter is a private type alias that cannot be accessed
6670 * from subclasses.
71+ *
72+ * (*) like-named means:
73+ *
74+ * parameter name == reference name ++ suffix
6775 */
6876 def derivedType (sym : Symbol )(implicit ctx : Context ) = {
6977 val relocate = new TypeMap {
7078 val originalOwner = sym.owner
7179 def apply (tp : Type ) = tp match {
7280 case tp : NamedType if tp.symbol.exists && (tp.symbol.owner eq originalOwner) =>
7381 val defctx = ctx.outersIterator.dropWhile(_.scope eq ctx.scope).next()
74- var local = defctx.denotNamed(tp.name).suchThat(_.isParamOrAccessor).symbol
82+ var local = defctx.denotNamed(tp.name ++ suffix ).suchThat(_.isParamOrAccessor).symbol
7583 if (local.exists) (defctx.owner.thisType select local).dealias
7684 else {
7785 def msg =
78- s " no matching symbol for ${tp.symbol.showLocated} in ${defctx.owner} / ${defctx.effectiveScope}"
86+ s " no matching symbol for ${tp.symbol.showLocated} in ${defctx.owner} / ${defctx.effectiveScope.toList }"
7987 if (ctx.reporter.errorsReported) ErrorType (msg)
8088 else throw new java.lang.Error (msg)
8189 }
@@ -88,14 +96,20 @@ object desugar {
8896 }
8997
9098 /** A type definition copied from `tdef` with a rhs typetree derived from it */
91- def derivedTypeParam (tdef : TypeDef ) =
99+ def derivedTypeParam (tdef : TypeDef , suffix : String = " " ) : TypeDef =
92100 cpy.TypeDef (tdef)(
93- rhs = new DerivedFromParamTree () withPos tdef.rhs.pos watching tdef)
101+ name = tdef.name ++ suffix,
102+ rhs = new DerivedFromParamTree (suffix).withPos(tdef.rhs.pos).watching(tdef)
103+ )
104+
105+ /** A derived type definition watching `sym` */
106+ def derivedTypeParam (sym : TypeSymbol )(implicit ctx : Context ): TypeDef =
107+ TypeDef (sym.name, new DerivedFromParamTree (" " ).watching(sym)).withFlags(TypeParam )
94108
95109 /** A value definition copied from `vdef` with a tpt typetree derived from it */
96110 def derivedTermParam (vdef : ValDef ) =
97111 cpy.ValDef (vdef)(
98- tpt = new DerivedFromParamTree () withPos vdef.tpt.pos watching vdef)
112+ tpt = new DerivedFromParamTree (" " ) withPos vdef.tpt.pos watching vdef)
99113
100114// ----- Desugar methods -------------------------------------------------
101115
@@ -317,8 +331,8 @@ object desugar {
317331 }
318332 def anyRef = ref(defn.AnyRefAlias .typeRef)
319333
320- val derivedTparams = constrTparams map derivedTypeParam
321- val derivedVparamss = constrVparamss nestedMap derivedTermParam
334+ val derivedTparams = constrTparams. map( derivedTypeParam(_))
335+ val derivedVparamss = constrVparamss. nestedMap( derivedTermParam(_))
322336 val arity = constrVparamss.head.length
323337
324338 val classTycon : Tree = new TypeRefTree // watching is set at end of method
@@ -419,9 +433,8 @@ object desugar {
419433 // ev1: Eq[T1$1, T1$2], ..., evn: Eq[Tn$1, Tn$2]])
420434 // : Eq[C[T1$1, ..., Tn$1], C[T1$2, ..., Tn$2]] = Eq
421435 def eqInstance = {
422- def append (tdef : TypeDef , str : String ) = cpy.TypeDef (tdef)(name = tdef.name ++ str)
423- val leftParams = derivedTparams.map(append(_, " $1" ))
424- val rightParams = derivedTparams.map(append(_, " $2" ))
436+ val leftParams = constrTparams.map(derivedTypeParam(_, " $1" ))
437+ val rightParams = constrTparams.map(derivedTypeParam(_, " $2" ))
425438 val subInstances = (leftParams, rightParams).zipped.map((param1, param2) =>
426439 appliedRef(ref(defn.EqType ), List (param1, param2)))
427440 DefDef (
@@ -456,19 +469,16 @@ object desugar {
456469 // For all other classes, the parent is AnyRef.
457470 val companions =
458471 if (isCaseClass) {
459- def extractType (t : Tree ): Tree = t match {
460- case Apply (t1, _) => extractType(t1)
461- case TypeApply (t1, ts) => AppliedTypeTree (extractType(t1), ts)
462- case Select (t1, nme.CONSTRUCTOR ) => extractType(t1)
463- case New (t1) => t1
464- case t1 => t1
465- }
466472 // The return type of the `apply` method
467- val applyResultTpt =
468- if (isEnumCase)
469- if (parents.isEmpty) enumClassTypeRef
470- else parents.map(extractType).reduceLeft(AndTypeTree )
471- else TypeTree ()
473+ val (applyResultTpt, widenDefs) =
474+ if (! isEnumCase)
475+ (TypeTree (), Nil )
476+ else if (parents.isEmpty || enumClass.typeParams.isEmpty)
477+ (enumClassTypeRef, Nil )
478+ else {
479+ val tparams = enumClass.typeParams.map(derivedTypeParam)
480+ enumApplyResult(cdef, parents, tparams, appliedRef(enumClassRef, tparams))
481+ }
472482
473483 val parent =
474484 if (constrTparams.nonEmpty ||
@@ -479,11 +489,13 @@ object desugar {
479489 // todo: also use anyRef if constructor has a dependent method type (or rule that out)!
480490 (constrVparamss :\ (if (isEnumCase) applyResultTpt else classTypeRef)) (
481491 (vparams, restpe) => Function (vparams map (_.tpt), restpe))
492+ def widenedCreatorExpr =
493+ (creatorExpr /: widenDefs)((rhs, meth) => Apply (Ident (meth.name), rhs :: Nil ))
482494 val applyMeths =
483495 if (mods is Abstract ) Nil
484496 else
485- DefDef (nme.apply, derivedTparams, derivedVparamss, applyResultTpt, creatorExpr )
486- .withFlags(Synthetic | (constr1.mods.flags & DefaultParameterized )) :: Nil
497+ DefDef (nme.apply, derivedTparams, derivedVparamss, applyResultTpt, widenedCreatorExpr )
498+ .withFlags(Synthetic | (constr1.mods.flags & DefaultParameterized )) :: widenDefs
487499 val unapplyMeth = {
488500 val unapplyParam = makeSyntheticParameter(tpt = classTypeRef)
489501 val unapplyRHS = if (arity == 0 ) Literal (Constant (true )) else Ident (unapplyParam.name)
0 commit comments