@@ -134,6 +134,8 @@ trait MethodSynthesis {
134
134
ImplicitClassWrapper (tree).createAndEnterSymbol()
135
135
}
136
136
137
+ // TODO: why is all this symbol creation disconnected from addDerivedTrees,
138
+ // which creates another list of Field/Getter/Setter factories???
137
139
def enterGetterSetter (tree : ValDef ) {
138
140
val ValDef (mods, name, _, _) = tree
139
141
if (nme.isSetterName(name))
@@ -149,12 +151,15 @@ trait MethodSynthesis {
149
151
val getter = Getter (tree)
150
152
val getterSym = getter.createAndEnterSymbol()
151
153
// Create the setter if necessary.
152
- if (mods.isMutable)
153
- Setter (tree).createAndEnterSymbol()
154
+ if (getter.needsSetter) {
155
+ val setterSym = Setter (tree).createAndEnterSymbol()
156
+ getterSym.referenced = setterSym
157
+ setterSym.referenced = getterSym
158
+ }
154
159
155
160
// Create a field if the getter requires storage, otherwise,
156
161
// the getter's abstract and the tree gets the getter's symbol.
157
- if (getter.noFieldNeeded ) getterSym setPos tree.pos
162
+ if (getter.noFieldHere ) getterSym setPos tree.pos
158
163
else enterStrictVal(tree)
159
164
}
160
165
@@ -224,9 +229,12 @@ trait MethodSynthesis {
224
229
}
225
230
226
231
def standardAccessors (vd : ValDef ): List [DerivedFromValDef ] =
227
- if (vd.mods.isMutable && ! vd.mods.isLazy) List (Getter (vd), Setter (vd))
228
- else if (vd.mods.isLazy) List (LazyValGetter (vd))
229
- else List (Getter (vd))
232
+ if (vd.mods.isLazy) List (LazyValGetter (vd))
233
+ else {
234
+ val getter = Getter (vd)
235
+ if (getter.needsSetter) List (getter, Setter (vd))
236
+ else List (getter)
237
+ }
230
238
231
239
def beanAccessors (vd : ValDef ): List [DerivedFromValDef ] = {
232
240
val setter = if (vd.mods.isMutable) List (BeanSetter (vd)) else Nil
@@ -237,10 +245,6 @@ trait MethodSynthesis {
237
245
else Nil
238
246
}
239
247
240
- // Take into account annotations so that we keep annotated unit lazy val
241
- // to get better error message already from the cps plugin itself
242
- def hasUnitType (sym : Symbol ) = (sym.tpe.typeSymbol == UnitClass ) && sym.tpe.annotations.isEmpty
243
-
244
248
/** This trait assembles what's needed for synthesizing derived methods.
245
249
* Important: Typically, instances of this trait are created TWICE for each derived
246
250
* symbol; once form Namers in an enter method, and once from Typers in addDerivedTrees.
@@ -257,7 +261,6 @@ trait MethodSynthesis {
257
261
def name : TermName
258
262
259
263
/** The flags that are retained from the original symbol */
260
-
261
264
def flagsMask : Long
262
265
263
266
/** The flags that the derived symbol has in addition to those retained from
@@ -269,7 +272,10 @@ trait MethodSynthesis {
269
272
def completer (sym : Symbol ): Type
270
273
271
274
/** The derived symbol. It is assumed that this symbol already exists and has been
272
- * entered in the parent scope when derivedSym is called */
275
+ * entered in the parent scope when derivedSym is called
276
+ * this derived symbol business is super shady -- we're creating them,
277
+ * so why do we need to look them up with setterIn/getterIn??
278
+ */
273
279
def derivedSym : Symbol
274
280
275
281
/** The definition tree of the derived symbol. */
@@ -281,8 +287,9 @@ trait MethodSynthesis {
281
287
def enclClass : Symbol
282
288
283
289
// Final methods to make the rest easier to reason about.
284
- final def mods = tree.mods
285
- final def basisSym = tree.symbol
290
+ final def mods = tree.mods
291
+ final def basisSym = tree.symbol
292
+ final def derivedMods = mods & flagsMask | flagsExtra
286
293
}
287
294
288
295
sealed trait DerivedFromClassDef extends DerivedFromMemberDef {
@@ -302,19 +309,27 @@ trait MethodSynthesis {
302
309
/* Explicit isSetter required for bean setters (beanSetterSym.isSetter is false) */
303
310
final def completer (sym : Symbol ) = namerOf(sym).accessorTypeCompleter(tree, isSetter)
304
311
final def fieldSelection = Select (This (enclClass), basisSym)
305
- final def derivedMods : Modifiers = mods & flagsMask | flagsExtra mapAnnotations (_ => Nil )
306
312
307
313
def derivedSym : Symbol = tree.symbol
308
314
def derivedTree : Tree = EmptyTree
309
315
310
- def noFieldNeeded = isDeferred || (mods.isLazy && hasUnitType(basisSym))
316
+ // No field for these vals:
317
+ // - abstract vals have no value we could store (until they become concrete, potentially)
318
+ // - a concrete val with a statically known value (Unit / ConstantType)
319
+ // performs its side effect according to lazy/strict semantics, but doesn't need to store its value
320
+ // each access will "evaluate" the RHS (a literal) again
321
+ // - concrete vals in traits don't yield a field here either (their getter's RHS has the initial value)
322
+ // Constructors will move the assignment to the constructor, abstracting over the field using the field setter,
323
+ // and Mixin will add a field to the class that mixes in the trait, implementing the accessors in terms of it
324
+ def noFieldHere = nothingToMemoize || owner.isTrait
325
+ protected def nothingToMemoize = isDeferred // TODO: we don't know the val's type at this point... || typeNeedsNoStorage(???)
311
326
312
327
def isSetter = false
313
328
def isDeferred = mods.isDeferred
314
329
def keepClean = false // whether annotations whose definitions are not meta-annotated should be kept.
315
330
def validate () { }
316
- def createAndEnterSymbol (): Symbol = {
317
- val sym = owner.newMethod(name, tree.pos.focus, (tree.mods. flags & flagsMask) | flagsExtra )
331
+ def createAndEnterSymbol (): MethodSymbol = {
332
+ val sym = owner.newMethod(name, tree.pos.focus, derivedMods. flags)
318
333
setPrivateWithin(tree, sym)
319
334
enterInScope(sym)
320
335
sym setInfo completer(sym)
@@ -332,16 +347,24 @@ trait MethodSynthesis {
332
347
}
333
348
}
334
349
sealed trait DerivedGetter extends DerivedFromValDef {
335
- // TODO
350
+ // A getter obviously must be accompanied by a setter if the ValDef is mutable.
351
+ // We also need a setter for any val/var defined in a trait,
352
+ // since an interface in Java can't define a field,
353
+ // so we shall set the initial value indirectly in the trait's init method using the trait setter,
354
+ // which will be implemented in the class
355
+ def needsSetter = mods.isMutable || (owner.isTrait && ! nothingToMemoize)
336
356
}
337
357
sealed trait DerivedSetter extends DerivedFromValDef {
338
358
override def isSetter = true
339
359
private def setterParam = derivedSym.paramss match {
340
360
case (p :: Nil ) :: _ => p
341
361
case _ => NoSymbol
342
362
}
363
+ // TODO: when is `derivedSym.isOverloaded`??? is it always an error?
364
+ // `noFieldHere` does not imply DEFERRED (ask isDeferred if you must know)
365
+ // we automatically implement trait setters (where !isDeferred) in the subclass
343
366
private def setterRhs =
344
- if (isDeferred || derivedSym.isOverloaded) EmptyTree
367
+ if (noFieldHere || derivedSym.isOverloaded) EmptyTree
345
368
else Assign (fieldSelection, Ident (setterParam))
346
369
347
370
private def setterDef = DefDef (derivedSym, setterRhs)
@@ -362,8 +385,7 @@ trait MethodSynthesis {
362
385
context.error(tree.pos, s " Internal error: Unable to find the synthetic factory method corresponding to implicit class $name in $enclClass / ${enclClass.info.decls}" )
363
386
result
364
387
}
365
- def derivedTree : DefDef =
366
- factoryMeth(mods & flagsMask | flagsExtra, name, tree)
388
+ def derivedTree : DefDef = factoryMeth(derivedMods, name, tree)
367
389
def flagsExtra : Long = METHOD | IMPLICIT | SYNTHETIC
368
390
def flagsMask : Long = AccessFlags
369
391
def name : TermName = tree.name.toTermName
@@ -385,7 +407,8 @@ trait MethodSynthesis {
385
407
}
386
408
case class Getter (tree : ValDef ) extends BaseGetter (tree) {
387
409
override def derivedSym = if (isDeferred) basisSym else basisSym.getterIn(enclClass)
388
- private def derivedRhs = if (isDeferred) EmptyTree else fieldSelection
410
+ private def derivedRhs = if (noFieldHere) tree.rhs else fieldSelection
411
+
389
412
private def derivedTpt = {
390
413
// For existentials, don't specify a type for the getter, even one derived
391
414
// from the symbol! This leads to incompatible existentials for the field and
@@ -406,12 +429,14 @@ trait MethodSynthesis {
406
429
}
407
430
override def derivedTree : DefDef = newDefDef(derivedSym, derivedRhs)(tpt = derivedTpt)
408
431
}
432
+
409
433
/** Implements lazy value accessors:
410
- * - for lazy values of type Unit and all lazy fields inside traits,
411
- * the rhs is the initializer itself
412
- * - for all other lazy values z the accessor is a block of this form:
413
- * { z = <rhs>; z } where z can be an identifier or a field.
414
- */
434
+ * - for lazy values of type Unit and all lazy fields inside traits,
435
+ * the rhs is the initializer itself, because we'll just "compute" the result on every access
436
+ * ("computing" unit / constant type is free -- the side-effect is still only run once, using the init bitmap)
437
+ * - for all other lazy values z the accessor is a block of this form:
438
+ * { z = <rhs>; z } where z can be an identifier or a field.
439
+ */
415
440
case class LazyValGetter (tree : ValDef ) extends BaseGetter (tree) {
416
441
class ChangeOwnerAndModuleClassTraverser (oldowner : Symbol , newowner : Symbol )
417
442
extends ChangeOwnerTraverser (oldowner, newowner) {
@@ -431,7 +456,7 @@ trait MethodSynthesis {
431
456
override def derivedTree : DefDef = {
432
457
val ValDef (_, _, tpt0, rhs0) = tree
433
458
val rhs1 = context.unit.transformed.getOrElse(rhs0, rhs0)
434
- val body = if (noFieldNeeded ) rhs1
459
+ val body = if (noFieldHere ) rhs1
435
460
else gen.mkAssignAndReturn(basisSym, rhs1)
436
461
437
462
derivedSym setPos tree.pos // cannot set it at createAndEnterSymbol because basisSym can possibly still have NoPosition
@@ -450,7 +475,7 @@ trait MethodSynthesis {
450
475
def flagsMask = SetterFlags
451
476
def flagsExtra = ACCESSOR
452
477
453
- override def derivedSym = basisSym.setterIn(enclClass)
478
+ override def derivedSym = basisSym.setterIn(enclClass, hasExpandedName = false )
454
479
}
455
480
case class Field (tree : ValDef ) extends DerivedFromValDef {
456
481
def name = tree.localName
@@ -461,12 +486,8 @@ trait MethodSynthesis {
461
486
// generated for a class parameter (PARAMACCESSOR).
462
487
override def keepClean = ! mods.isParamAccessor
463
488
464
- override def derivedSym =
465
- if (noFieldNeeded) NoSymbol
466
- else super .derivedSym
467
-
468
489
override def derivedTree = (
469
- if (derivedSym eq NoSymbol ) EmptyTree
490
+ if (noFieldHere ) EmptyTree
470
491
else if (mods.isLazy) copyValDef(tree)(mods = mods | flagsExtra, name = this .name, rhs = EmptyTree ).setPos(tree.pos.focus)
471
492
else copyValDef(tree)(mods = mods | flagsExtra, name = this .name)
472
493
)
@@ -504,12 +525,12 @@ trait MethodSynthesis {
504
525
// Derives a tree without attempting to use the original tree's symbol.
505
526
override def derivedTree = {
506
527
atPos(tree.pos.focus) {
507
- DefDef (derivedMods, name, Nil , ListOfNil , tree.tpt.duplicate,
528
+ DefDef (derivedMods mapAnnotations (_ => Nil ) , name, Nil , ListOfNil , tree.tpt.duplicate,
508
529
if (isDeferred) EmptyTree else Select (This (owner), tree.name)
509
530
)
510
531
}
511
532
}
512
- override def createAndEnterSymbol (): Symbol = enterSyntheticSym(derivedTree)
533
+ override def createAndEnterSymbol (): MethodSymbol = enterSyntheticSym(derivedTree). asInstanceOf [ MethodSymbol ]
513
534
}
514
535
case class BooleanBeanGetter (tree : ValDef ) extends BeanAccessor (" is" ) with AnyBeanGetter { }
515
536
case class BeanGetter (tree : ValDef ) extends BeanAccessor (" get" ) with AnyBeanGetter { }
0 commit comments