@@ -15,23 +15,24 @@ import config.Printers.typr
15
15
import Inferencing ._
16
16
import transform .TypeUtils ._
17
17
import transform .SymUtils ._
18
+ import ErrorReporting .errorTree
18
19
19
20
/** A typer mixin that implements typeclass derivation functionality */
20
21
trait Deriving { this : Typer =>
21
22
22
23
/** A helper class to derive type class instances for one class or object
23
- * @param cls The class symbol of the class or object with a `derives` clause
24
- * @param templateStartPos The default position that should be given to generic
25
- * synthesized infrastructure code that is not connected with a
26
- * `derives` instance.
24
+ * @param cls The class symbol of the class or object with a `derives` clause
25
+ * @param codePos The default position that should be given to generic
26
+ * synthesized infrastructure code that is not connected with a
27
+ * `derives` instance.
27
28
*/
28
- class Deriver (cls : ClassSymbol , templateStartPos : Position )(implicit ctx : Context ) {
29
+ class Deriver (cls : ClassSymbol , codePos : Position )(implicit ctx : Context ) {
29
30
30
31
/** A buffer for synthesized symbols */
31
32
private var synthetics = new mutable.ListBuffer [Symbol ]
32
33
33
34
/** the children of `cls` ordered by textual occurrence */
34
- lazy val children = cls.children.sortBy(_.pos.start)
35
+ lazy val children = cls.children
35
36
36
37
/** The shape (of type Shape.Case) of a case given by `sym`. `sym` is either `cls`
37
38
* itself, or a subclass of `cls`, or an instance of `cls`.
@@ -40,7 +41,9 @@ trait Deriving { this: Typer =>
40
41
val (constr, elems) =
41
42
sym match {
42
43
case caseClass : ClassSymbol =>
43
- caseClass.primaryConstructor.info match {
44
+ if (caseClass.is(Module ))
45
+ (caseClass.sourceModule.termRef, Nil )
46
+ else caseClass.primaryConstructor.info match {
44
47
case info : PolyType =>
45
48
def instantiate (implicit ctx : Context ) = {
46
49
val poly = constrained(info, untpd.EmptyTree )._1
@@ -83,6 +86,13 @@ trait Deriving { this: Typer =>
83
86
else if (cls.is(Sealed )) sealedShape
84
87
else NoType
85
88
89
+ private def shapeOfType (tp : Type ) = {
90
+ val shape0 = shapeWithClassParams
91
+ val clsType = tp.baseType(cls)
92
+ if (clsType.exists) shape0.subst(cls.typeParams, clsType.argInfos)
93
+ else clsType
94
+ }
95
+
86
96
private def add (sym : Symbol ): sym.type = {
87
97
ctx.enter(sym)
88
98
synthetics += sym
@@ -167,7 +177,7 @@ trait Deriving { this: Typer =>
167
177
*/
168
178
private def addGenericClass (): Unit =
169
179
if (! ctx.denotNamed(nme.genericClass).exists) {
170
- add(newSymbol(nme.genericClass, defn.GenericClassType , templateStartPos ))
180
+ add(newSymbol(nme.genericClass, defn.GenericClassType , codePos ))
171
181
}
172
182
173
183
private def addGeneric (): Unit = {
@@ -181,7 +191,7 @@ trait Deriving { this: Typer =>
181
191
denot.info = PolyType .fromParams(cls.typeParams, resultType).ensureMethodic
182
192
}
183
193
}
184
- addDerivedInstance(defn.GenericType .name, genericCompleter, templateStartPos , reportErrors = false )
194
+ addDerivedInstance(defn.GenericType .name, genericCompleter, codePos , reportErrors = false )
185
195
}
186
196
187
197
/** Create symbols for derived instances and infrastructure,
@@ -240,12 +250,12 @@ trait Deriving { this: Typer =>
240
250
case ShapeCase (pat, elems) =>
241
251
val patCls = pat.widen.classSymbol
242
252
val patLabel = patCls.name.stripModuleClassSuffix.toString
243
- val elemLabels = patCls.caseAccessors.map(_.name.toString)
253
+ val elemLabels = patCls.caseAccessors.filterNot(_.is( PrivateLocal )). map(_.name.toString)
244
254
(patLabel :: elemLabels).mkString(" \u0000 " )
245
255
}
246
256
247
257
/** The RHS of the `genericClass` value definition */
248
- private def genericClassRHS =
258
+ def genericClassRHS =
249
259
New (defn.GenericClassType ,
250
260
List (Literal (Constant (cls.typeRef)),
251
261
Literal (Constant (labelString(shapeWithClassParams)))))
@@ -272,15 +282,15 @@ trait Deriving { this: Typer =>
272
282
* def common = genericClass
273
283
* }
274
284
*/
275
- private def genericRHS (genericType : Type )(implicit ctx : Context ) = {
285
+ def genericRHS (genericType : Type , genericClassRef : Tree )(implicit ctx : Context ) = {
276
286
val RefinedType (
277
287
genericInstance @ AppliedType (_, clsArg :: Nil ),
278
288
tpnme.Shape ,
279
289
TypeAlias (shapeArg)) = genericType
280
290
val shape = shapeArg.dealias
281
291
282
292
val implClassSym = ctx.newNormalizedClassSymbol(
283
- ctx.owner, tpnme.ANON_CLASS , EmptyFlags , genericInstance :: Nil , coord = templateStartPos )
293
+ ctx.owner, tpnme.ANON_CLASS , EmptyFlags , genericInstance :: Nil , coord = codePos )
284
294
val implClassCtx = ctx.withOwner(implClassSym)
285
295
val implClassConstr =
286
296
newMethod(nme.CONSTRUCTOR , MethodType (Nil , implClassSym.typeRef))(implClassCtx).entered
@@ -299,7 +309,7 @@ trait Deriving { this: Typer =>
299
309
val mirror = defn.GenericClassType
300
310
.member(nme.mirror)
301
311
.suchThat(sym => args.tpes.corresponds(sym.info.firstParamTypes)(_ <:< _))
302
- ref(genericClass) .select(mirror.symbol).appliedToArgs(args)
312
+ genericClassRef .select(mirror.symbol).appliedToArgs(args)
303
313
}
304
314
shape match {
305
315
case ShapeCases (cases) =>
@@ -347,7 +357,7 @@ trait Deriving { this: Typer =>
347
357
348
358
val commonMethod : DefDef = {
349
359
val meth = newMethod(nme.common, ExprType (defn.GenericClassType )).entered
350
- tpd.DefDef (meth, ref(genericClass) )
360
+ tpd.DefDef (meth, genericClassRef )
351
361
}
352
362
353
363
List (shapeType, reflectMethod, reifyMethod, commonMethod)
@@ -378,7 +388,7 @@ trait Deriving { this: Typer =>
378
388
val resultType = instantiated(sym.info)
379
389
val (typeCls, companionRef) = classAndCompanionRef(resultType)
380
390
if (typeCls == defn.GenericClass )
381
- genericRHS(resultType)
391
+ genericRHS(resultType, ref(genericClass) )
382
392
else {
383
393
val module = untpd.ref(companionRef).withPos(sym.pos)
384
394
val rhs = untpd.Select (module, nme.derived)
@@ -404,5 +414,17 @@ trait Deriving { this: Typer =>
404
414
tpd.cpy.TypeDef (stat)(
405
415
rhs = tpd.cpy.Template (templ)(body = templ.body ++ new Finalizer ().syntheticDefs))
406
416
}
417
+
418
+ /** Synthesized instance for `Generic[<clsType>]` */
419
+ def genericInstance (clsType : Type ): tpd.Tree = {
420
+ val shape = shapeOfType(clsType)
421
+ if (shape.exists) {
422
+ val genericType = RefinedType (defn.GenericType .appliedTo(clsType), tpnme.Shape , TypeAlias (shape))
423
+ val finalizer = new Finalizer
424
+ finalizer.genericRHS(genericType, finalizer.genericClassRHS)
425
+ }
426
+ else errorTree(tpd.EmptyTree .withPos(codePos),
427
+ i " cannot take shape of type $clsType" , codePos)
428
+ }
407
429
}
408
430
}
0 commit comments