@@ -32,6 +32,8 @@ trait Deriving { this: Typer =>
32
32
/** A buffer for synthesized symbols */
33
33
private var synthetics = new mutable.ListBuffer [Symbol ]
34
34
35
+ private var derivesGeneric = false
36
+
35
37
/** the children of `cls` ordered by textual occurrence */
36
38
lazy val children : List [Symbol ] = cls.children
37
39
@@ -170,7 +172,7 @@ trait Deriving { this: Typer =>
170
172
val derivedType = checkClassType(underlyingType, derived.sourcePos, traitReq = false , stablePrefixReq = true )
171
173
val nparams = derivedType.classSymbol.typeParams.length
172
174
if (derivedType.isRef(defn.GenericClass ))
173
- () // do nothing, a Generic instance will be created anyway by `addGeneric`
175
+ derivesGeneric = true
174
176
else if (nparams == 1 ) {
175
177
val typeClass = derivedType.classSymbol
176
178
val firstKindedParams = cls.typeParams.filterNot(_.info.isLambdaSub)
@@ -210,14 +212,33 @@ trait Deriving { this: Typer =>
210
212
addDerivedInstance(defn.GenericType .name, genericCompleter, codePos, reportErrors = false )
211
213
}
212
214
215
+ /** If any of the instances has a companion with a `derived` member
216
+ * that refers to `scala.reflect.Generic`, add an implied instance
217
+ * of `Generic`. Note: this is just an optimization to avoid possible
218
+ * code duplication. Generic instances are created on the fly if they
219
+ * are missing from the companion.
220
+ */
221
+ private def maybeAddGeneric (): Unit = {
222
+ val genericCls = defn.GenericClass
223
+ def refersToGeneric (sym : Symbol ): Boolean = {
224
+ val companion = sym.info.finalResultType.classSymbol.companionModule
225
+ val derivd = companion.info.member(nme.derived)
226
+ derivd.hasAltWith(sd => sd.info.existsPart(p => p.typeSymbol == genericCls))
227
+ }
228
+ if (derivesGeneric || synthetics.exists(refersToGeneric)) {
229
+ derive.println(i " add generic infrastructure for $cls" )
230
+ addGeneric()
231
+ addGenericClass()
232
+ }
233
+ }
234
+
213
235
/** Create symbols for derived instances and infrastructure,
214
- * append them to `synthetics` buffer,
215
- * and enter them into class scope .
236
+ * append them to `synthetics` buffer, and enter them into class scope.
237
+ * Also, add generic instances if needed .
216
238
*/
217
239
def enterDerived (derived : List [untpd.Tree ]) = {
218
240
derived.foreach(processDerivedInstance(_))
219
- addGeneric()
220
- addGenericClass()
241
+ maybeAddGeneric()
221
242
}
222
243
223
244
private def tupleElems (tp : Type ): List [Type ] = tp match {
0 commit comments