@@ -72,9 +72,12 @@ object desugar {
72
72
val defctx = ctx.outersIterator.dropWhile(_.scope eq ctx.scope).next
73
73
var local = defctx.denotNamed(tp.name).suchThat(_ is ParamOrAccessor ).symbol
74
74
if (local.exists) (defctx.owner.thisType select local).dealias
75
- else throw new java.lang.Error (
76
- s " no matching symbol for ${tp.symbol.showLocated} in ${defctx.owner} / ${defctx.effectiveScope}"
77
- )
75
+ else {
76
+ def msg =
77
+ s " no matching symbol for ${tp.symbol.showLocated} in ${defctx.owner} / ${defctx.effectiveScope}"
78
+ if (ctx.reporter.errorsReported) new ErrorType (msg)
79
+ else throw new java.lang.Error (msg)
80
+ }
78
81
case _ =>
79
82
mapOver(tp)
80
83
}
@@ -124,7 +127,7 @@ object desugar {
124
127
else vdef
125
128
}
126
129
127
- def makeImplicitParameters (tpts : List [Tree ], forPrimaryConstructor : Boolean )(implicit ctx : Context ) =
130
+ def makeImplicitParameters (tpts : List [Tree ], forPrimaryConstructor : Boolean = false )(implicit ctx : Context ) =
128
131
for (tpt <- tpts) yield {
129
132
val paramFlags : FlagSet = if (forPrimaryConstructor) PrivateLocalParamAccessor else Param
130
133
val epname = EvidenceParamName .fresh()
@@ -265,7 +268,7 @@ object desugar {
265
268
val mods = cdef.mods
266
269
val companionMods = mods
267
270
.withFlags((mods.flags & AccessFlags ).toCommonFlags)
268
- .withMods(mods.mods.filter( ! _. isInstanceOf [ Mod . EnumCase ]) )
271
+ .withMods(Nil )
269
272
270
273
val (constr1, defaultGetters) = defDef(constr0, isPrimaryConstructor = true ) match {
271
274
case meth : DefDef => (meth, Nil )
@@ -291,7 +294,7 @@ object desugar {
291
294
292
295
val isCaseClass = mods.is(Case ) && ! mods.is(Module )
293
296
val isCaseObject = mods.is(Case ) && mods.is(Module )
294
- val isEnum = mods.hasMod[Mod .Enum ]
297
+ val isEnum = mods.hasMod[Mod .Enum ] && ! mods.is( Module )
295
298
val isEnumCase = isLegalEnumCase(cdef)
296
299
val isValueClass = parents.nonEmpty && isAnyVal(parents.head)
297
300
// This is not watertight, but `extends AnyVal` will be replaced by `inline` later.
@@ -326,10 +329,12 @@ object desugar {
326
329
327
330
val classTycon : Tree = new TypeRefTree // watching is set at end of method
328
331
329
- def appliedRef (tycon : Tree ) =
330
- (if (constrTparams.isEmpty) tycon
331
- else AppliedTypeTree (tycon, constrTparams map refOfDef))
332
- .withPos(cdef.pos.startPos)
332
+ def appliedTypeTree (tycon : Tree , args : List [Tree ]) =
333
+ (if (args.isEmpty) tycon else AppliedTypeTree (tycon, args))
334
+ .withPos(cdef.pos.startPos)
335
+
336
+ def appliedRef (tycon : Tree , tparams : List [TypeDef ] = constrTparams) =
337
+ appliedTypeTree(tycon, tparams map refOfDef)
333
338
334
339
// a reference to the class type bound by `cdef`, with type parameters coming from the constructor
335
340
val classTypeRef = appliedRef(classTycon)
@@ -344,8 +349,7 @@ object desugar {
344
349
else {
345
350
ctx.error(i " explicit extends clause needed because type parameters of case and enum class differ "
346
351
, cdef.pos.startPos)
347
- AppliedTypeTree (enumClassRef, constrTparams map (_ => anyRef))
348
- .withPos(cdef.pos.startPos)
352
+ appliedTypeTree(enumClassRef, constrTparams map (_ => anyRef))
349
353
}
350
354
case _ =>
351
355
enumClassRef
@@ -411,6 +415,31 @@ object desugar {
411
415
if (isEnum)
412
416
parents1 = parents1 :+ ref(defn.EnumType )
413
417
418
+ // The Eq instance for an Enum class. For an enum class
419
+ //
420
+ // enum class C[T1, ..., Tn]
421
+ //
422
+ // we generate:
423
+ //
424
+ // implicit def eqInstance[T1$1, ..., Tn$1, T1$2, ..., Tn$2](implicit
425
+ // ev1: Eq[T1$1, T1$2], ..., evn: Eq[Tn$1, Tn$2]])
426
+ // : Eq[C[T1$1, ..., Tn$1], C[T1$2, ..., Tn$2]] = Eq
427
+ def eqInstance = {
428
+ def append (tdef : TypeDef , str : String ) = cpy.TypeDef (tdef)(name = tdef.name ++ str)
429
+ val leftParams = derivedTparams.map(append(_, " $1" ))
430
+ val rightParams = derivedTparams.map(append(_, " $2" ))
431
+ val subInstances = (leftParams, rightParams).zipped.map((param1, param2) =>
432
+ appliedRef(ref(defn.EqType ), List (param1, param2)))
433
+ DefDef (
434
+ name = nme.eqInstance,
435
+ tparams = leftParams ++ rightParams,
436
+ vparamss = List (makeImplicitParameters(subInstances)),
437
+ tpt = appliedTypeTree(ref(defn.EqType ),
438
+ appliedRef(classTycon, leftParams) :: appliedRef(classTycon, rightParams) :: Nil ),
439
+ rhs = ref(defn.EqModule .termRef)).withFlags(Synthetic | Implicit )
440
+ }
441
+ def eqInstances = if (isEnum) eqInstance :: Nil else Nil
442
+
414
443
// The thicket which is the desugared version of the companion object
415
444
// synthetic object C extends parentTpt { defs }
416
445
def companionDefs (parentTpt : Tree , defs : List [Tree ]) =
@@ -420,6 +449,8 @@ object desugar {
420
449
.withMods(companionMods | Synthetic ))
421
450
.withPos(cdef.pos).toList
422
451
452
+ val companionMeths = defaultGetters ::: eqInstances
453
+
423
454
// The companion object definitions, if a companion is needed, Nil otherwise.
424
455
// companion definitions include:
425
456
// 1. If class is a case class case class C[Ts](p1: T1, ..., pN: TN)(moreParams):
@@ -465,10 +496,10 @@ object desugar {
465
496
DefDef (nme.unapply, derivedTparams, (unapplyParam :: Nil ) :: Nil , TypeTree (), unapplyRHS)
466
497
.withMods(synthetic)
467
498
}
468
- companionDefs(parent, applyMeths ::: unapplyMeth :: defaultGetters )
499
+ companionDefs(parent, applyMeths ::: unapplyMeth :: companionMeths )
469
500
}
470
- else if (defaultGetters .nonEmpty)
471
- companionDefs(anyRef, defaultGetters )
501
+ else if (companionMeths .nonEmpty)
502
+ companionDefs(anyRef, companionMeths )
472
503
else if (isValueClass) {
473
504
constr0.vparamss match {
474
505
case List (_ :: Nil ) => companionDefs(anyRef, Nil )
@@ -739,7 +770,7 @@ object desugar {
739
770
}
740
771
741
772
def makeImplicitFunction (formals : List [Type ], body : Tree )(implicit ctx : Context ): Tree = {
742
- val params = makeImplicitParameters(formals.map(TypeTree ), forPrimaryConstructor = false )
773
+ val params = makeImplicitParameters(formals.map(TypeTree ))
743
774
new ImplicitFunction (params, body)
744
775
}
745
776
0 commit comments