@@ -81,10 +81,10 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
81
81
82
82
override def transform (tree : Tree ): Tree = {
83
83
tree match {
84
- case cd @ ClassDef (mods0, name0, tparams0, impl0) if ! isPrimitiveValueClass(cd.symbol) && cd.symbol.primaryConstructor != NoSymbol =>
85
- if (cd.symbol eq AnyValClass ) {
84
+ case cd @ ClassDef (mods0, name0, tparams0, impl0)
85
+ if ! isPrimitiveValueClass(cd.symbol) && cd.symbol.primaryConstructor != NoSymbol =>
86
+ if (cd.symbol eq AnyValClass )
86
87
cd
87
- }
88
88
else {
89
89
checkUninitializedReads(cd)
90
90
val tplTransformer = new TemplateTransformer (unit, impl0)
@@ -250,7 +250,7 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
250
250
*
251
251
* @return the DefDef for (c) above
252
252
*
253
- * * /
253
+ */
254
254
private trait DelayedInitHelper extends ConstructorTransformerBase {
255
255
private def delayedEndpointDef (stats : List [Tree ]): DefDef = {
256
256
val methodName = currentUnit.freshTermName(" delayedEndpoint$" + clazz.fullNameAsName('$' ).toString + " $" )
@@ -458,11 +458,9 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
458
458
{
459
459
protected def typedPos (pos : Position )(tree : Tree ): Tree = localTyper.typedPos(pos)(tree)
460
460
461
- val clazz = impl.symbol.owner // the transformed class
462
-
463
- val isDelayedInitSubclass = clazz isSubClass DelayedInitClass
464
-
465
- private val stats = impl.body // the transformed template body
461
+ override val clazz = impl.symbol.owner // the transformed class
462
+ private val stats = impl.body // the transformed template body
463
+ private val isDelayedInitSubclass = clazz isSubClass DelayedInitClass
466
464
467
465
// find and dissect primary constructor
468
466
private val (primaryConstr, _primaryConstrParams, primaryConstrBody) =
@@ -481,7 +479,7 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
481
479
// The constructor parameter corresponding to an accessor
482
480
def parameter (acc : Symbol ): Symbol = {
483
481
// works around the edge case where unexpandedName over-unexpands shenanigans like literal $$ or `$#`
484
- def unexpanded = parameterNamed(acc.unexpandedName.getterName)
482
+ val unexpanded = parameterNamed(acc.unexpandedName.getterName)
485
483
def expanded = parameterNamed(acc.getterName)
486
484
unexpanded.orElse(expanded).swap.map(abort).merge
487
485
}
@@ -497,15 +495,14 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
497
495
498
496
// A transformer for expressions that go into the constructor
499
497
object intoConstructor extends AstTransformer {
500
- /*
501
- * `usesSpecializedField` makes a difference in deciding whether constructor-statements
502
- * should be guarded in a `guardSpecializedFieldInit` class, ie in a class that's the generic super-class of
503
- * one or more specialized sub-classes.
504
- *
505
- * Given that `usesSpecializedField` isn't read for any other purpose than the one described above,
506
- * we skip setting `usesSpecializedField` in case the current class isn't `guardSpecializedFieldInit` to start with.
507
- * That way, trips to a map in `specializeTypes` are saved.
508
- */
498
+ /* `usesSpecializedField` makes a difference in deciding whether constructor-statements
499
+ * should be guarded in a `guardSpecializedFieldInit` class, ie in a class that's the generic super-class of
500
+ * one or more specialized sub-classes.
501
+ *
502
+ * Given that `usesSpecializedField` isn't read for any other purpose than the one described above,
503
+ * we skip setting `usesSpecializedField` in case the current class isn't `guardSpecializedFieldInit`
504
+ * to start with. That way, trips to a map in `specializeTypes` are saved.
505
+ */
509
506
var usesSpecializedField : Boolean = false
510
507
511
508
private def isParamRef (sym : Symbol ) = sym.isParamAccessor && sym.owner == clazz
@@ -518,8 +515,9 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
518
515
! sym.isVariable
519
516
)
520
517
521
- /*
522
- * whether `sym` denotes a param-accessor (ie in a class a PARAMACCESSOR field, or in a trait a method with same flag)
518
+ /* whether `sym` denotes a param-accessor
519
+ * (ie in a class a PARAMACCESSOR field, or in a trait a method with same flag)
520
+ *
523
521
* that fulfills all of:
524
522
* (a) has stationary value, ie the same value provided via the corresponding ctor-arg; and
525
523
* (b) isn't subject to specialization. We might be processing statements for:
@@ -534,7 +532,7 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
534
532
// references to parameter accessor methods of own class become references to parameters
535
533
// outer accessors become references to $outer parameter
536
534
// println(s"to param ref in $clazz for ${tree.symbol} ${tree.symbol.debugFlagString} / ${tree.symbol.outerSource} / ${canBeSupplanted(tree.symbol)}")
537
- if (clazz.isTrait && ! ( tree.symbol hasAllFlags (ACCESSOR | PARAMACCESSOR ) ))
535
+ if (clazz.isTrait && ! tree.symbol. hasAllFlags(ACCESSOR | PARAMACCESSOR ))
538
536
super .transform(tree)
539
537
else if (canBeSupplanted(tree.symbol))
540
538
gen.mkAttributedIdent(parameter(tree.symbol)) setPos tree.pos
@@ -609,7 +607,7 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
609
607
610
608
private def triage () = {
611
609
// Constant typed vals are not memoized.
612
- def memoizeValue (sym : Symbol ) = ! sym.info.resultType.isInstanceOf [FoldableConstantType ]
610
+ def memoizeValue (sym : Symbol ) = enteringErasure( ! sym.info.resultType.isInstanceOf [FoldableConstantType ])
613
611
614
612
// The early initialized field definitions of the class (these are the class members)
615
613
val presupers = treeInfo.preSuperFields(stats)
@@ -679,7 +677,8 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
679
677
// - the constructor, before the super call (early initialized or a parameter accessor),
680
678
// - the constructor, after the super call (regular val).
681
679
case vd : ValDef =>
682
- if (vd.rhs eq EmptyTree ) { defBuf += vd }
680
+ if (vd.rhs eq EmptyTree )
681
+ defBuf += vd
683
682
else {
684
683
val emitField = memoizeValue(statSym)
685
684
@@ -691,14 +690,22 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
691
690
692
691
case dd : DefDef =>
693
692
// either move the RHS to ctor (for getter of stored field) or just drop it (for corresponding setter)
694
- def shouldMoveRHS =
695
- clazz.isTrait && statSym.isAccessor && ! statSym.isLazy && ! statSym.isSpecialized && (statSym.isSetter || memoizeValue(statSym))
696
-
697
- if ((dd.rhs eq EmptyTree ) || ! shouldMoveRHS) { defBuf += dd }
698
- else {
699
- if (statSym.isGetter) moveEffectToCtor(dd.mods, dd.rhs, statSym.asTerm.referenced orElse statSym.setterIn(clazz))
700
- defBuf += deriveDefDef(stat)(_ => EmptyTree )
701
- }
693
+ def shouldMoveRHS = (
694
+ (dd.rhs ne EmptyTree )
695
+ && clazz.isTrait
696
+ && statSym.isAccessor
697
+ && ! statSym.isLazy
698
+ && ! statSym.isSpecialized
699
+ && (statSym.isSetter || memoizeValue(statSym))
700
+ )
701
+ val toMove =
702
+ if (shouldMoveRHS) {
703
+ if (statSym.isGetter)
704
+ moveEffectToCtor(dd.mods, dd.rhs, statSym.asTerm.referenced.orElse(statSym.setterIn(clazz)))
705
+ deriveDefDef(stat)(_ => EmptyTree )
706
+ }
707
+ else dd
708
+ defBuf += toMove
702
709
703
710
// all other statements go into the constructor
704
711
case _ =>
@@ -727,19 +734,22 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
727
734
else clazz.constrParamAccessors
728
735
729
736
// Initialize all parameters fields that must be kept.
730
- val paramInits = paramAccessors filterNot omittableSym map { acc =>
737
+ val paramInits = paramAccessors. filterNot( omittableSym). map { acc =>
731
738
// Check for conflicting field mixed in for a val/var defined in a parent trait (neg/t1960.scala).
732
739
// Since the fields phase has already mixed in fields, we can just look for
733
740
// an existing decl with the local variant of our paramaccessor's name.
734
741
//
735
- // TODO: mangle the constructor parameter name (it can only be used internally), though we probably first need more robust name mangling
742
+ // TODO: mangle the constructor parameter name (it can only be used internally),
743
+ // though we probably first need more robust name mangling
736
744
737
745
// sometimes acc is a field with a local name (when it's a val/var constructor param) --> exclude the `acc` itself when looking for conflicting decl
738
746
// sometimes it's not (just a constructor param) --> any conflicting decl is a problem
739
747
val conflict = clazz.info.decl(acc.name.localName).filter(sym => sym ne acc)
740
748
if (conflict ne NoSymbol ) {
741
749
val orig = exitingTyper(clazz.info.nonPrivateMember(acc.name).filter(_ hasFlag ACCESSOR ))
742
- reporter.error(acc.pos, s " parameter ' ${acc.name}' requires field but conflicts with ${(orig orElse conflict).fullLocationString}" )
750
+ reporter.error(acc.pos, s " parameter ' ${acc.name}' requires field but conflicts with ${
751
+ orig.orElse(conflict).fullLocationString
752
+ }" )
743
753
}
744
754
745
755
val accSetter =
@@ -787,7 +797,10 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
787
797
)
788
798
}
789
799
790
- if ((exitingPickler(clazz.isAnonymousClass) || clazz.originalOwner.isTerm) && omittableAccessor.exists(_.isOuterField) && ! constructorStats.exists(_.exists { case i : Ident if i.symbol.isOuterParam => true ; case _ => false }))
800
+ if ((exitingPickler(clazz.isAnonymousClass) || clazz.originalOwner.isTerm)
801
+ && omittableAccessor.exists(_.isOuterField)
802
+ && ! constructorStats.exists(_.exists { case i : Ident if i.symbol.isOuterParam => true case _ => false })
803
+ )
791
804
primaryConstructor.symbol.updateAttachment(OuterArgCanBeElided )
792
805
793
806
val constructors = primaryConstructor :: auxConstructors
0 commit comments