@@ -40,7 +40,11 @@ object desugar {
40
40
def derivedType (sym : Symbol )(implicit ctx : Context ) = sym.typeRef
41
41
}
42
42
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 {
44
48
45
49
/** Make sure that for all enclosing module classes their companion lasses
46
50
* are completed. Reason: We need the constructor of such companion classes to
@@ -58,24 +62,28 @@ object desugar {
58
62
59
63
/** Return info of original symbol, where all references to siblings of the
60
64
* 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
62
66
* the current scope. The current scope is the scope owned by the defined symbol
63
67
* itself, that's why we have to look one scope further out. If the resulting
64
68
* type is an alias type, dealias it. This is necessary because the
65
69
* accessor of a type parameter is a private type alias that cannot be accessed
66
70
* from subclasses.
71
+ *
72
+ * (*) like-named means:
73
+ *
74
+ * parameter name == reference name ++ suffix
67
75
*/
68
76
def derivedType (sym : Symbol )(implicit ctx : Context ) = {
69
77
val relocate = new TypeMap {
70
78
val originalOwner = sym.owner
71
79
def apply (tp : Type ) = tp match {
72
80
case tp : NamedType if tp.symbol.exists && (tp.symbol.owner eq originalOwner) =>
73
81
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
75
83
if (local.exists) (defctx.owner.thisType select local).dealias
76
84
else {
77
85
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 }"
79
87
if (ctx.reporter.errorsReported) ErrorType (msg)
80
88
else throw new java.lang.Error (msg)
81
89
}
@@ -88,14 +96,20 @@ object desugar {
88
96
}
89
97
90
98
/** 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 =
92
100
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 )
94
108
95
109
/** A value definition copied from `vdef` with a tpt typetree derived from it */
96
110
def derivedTermParam (vdef : ValDef ) =
97
111
cpy.ValDef (vdef)(
98
- tpt = new DerivedFromParamTree () withPos vdef.tpt.pos watching vdef)
112
+ tpt = new DerivedFromParamTree (" " ) withPos vdef.tpt.pos watching vdef)
99
113
100
114
// ----- Desugar methods -------------------------------------------------
101
115
@@ -317,8 +331,8 @@ object desugar {
317
331
}
318
332
def anyRef = ref(defn.AnyRefAlias .typeRef)
319
333
320
- val derivedTparams = constrTparams map derivedTypeParam
321
- val derivedVparamss = constrVparamss nestedMap derivedTermParam
334
+ val derivedTparams = constrTparams. map( derivedTypeParam(_))
335
+ val derivedVparamss = constrVparamss. nestedMap( derivedTermParam(_))
322
336
val arity = constrVparamss.head.length
323
337
324
338
val classTycon : Tree = new TypeRefTree // watching is set at end of method
@@ -419,9 +433,8 @@ object desugar {
419
433
// ev1: Eq[T1$1, T1$2], ..., evn: Eq[Tn$1, Tn$2]])
420
434
// : Eq[C[T1$1, ..., Tn$1], C[T1$2, ..., Tn$2]] = Eq
421
435
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" ))
425
438
val subInstances = (leftParams, rightParams).zipped.map((param1, param2) =>
426
439
appliedRef(ref(defn.EqType ), List (param1, param2)))
427
440
DefDef (
@@ -456,19 +469,16 @@ object desugar {
456
469
// For all other classes, the parent is AnyRef.
457
470
val companions =
458
471
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
- }
466
472
// 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
+ }
472
482
473
483
val parent =
474
484
if (constrTparams.nonEmpty ||
@@ -479,11 +489,13 @@ object desugar {
479
489
// todo: also use anyRef if constructor has a dependent method type (or rule that out)!
480
490
(constrVparamss :\ (if (isEnumCase) applyResultTpt else classTypeRef)) (
481
491
(vparams, restpe) => Function (vparams map (_.tpt), restpe))
492
+ def widenedCreatorExpr =
493
+ (creatorExpr /: widenDefs)((rhs, meth) => Apply (Ident (meth.name), rhs :: Nil ))
482
494
val applyMeths =
483
495
if (mods is Abstract ) Nil
484
496
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
487
499
val unapplyMeth = {
488
500
val unapplyParam = makeSyntheticParameter(tpt = classTypeRef)
489
501
val unapplyRHS = if (arity == 0 ) Literal (Constant (true )) else Ident (unapplyParam.name)
0 commit comments