@@ -17,6 +17,7 @@ import Types._
1717import Decorators ._
1818import DenotTransformers ._
1919import util .Positions ._
20+ import Constants .Constant
2021import collection .mutable
2122
2223/** This transform
@@ -64,20 +65,13 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor
6465
6566 // Produce aligned accessors and constructor parameters. We have to adjust
6667 // for any outer parameters, which are last in the sequence of original
67- // parameter accessors but should come first in the constructor parameter list.
68- var accessors = cls.paramAccessors.filterNot(_.isSetter)
69- var vparamsWithOuter = vparams
70- if (! accessors.hasSameLengthAs(vparams)) {
71- accessors.reverse match {
72- case last :: _ if (last.name == nme.OUTER ) =>
73- accessors = last :: accessors.init // align wth calling convention
74- vparamsWithOuter = ValDef (last.asTerm) :: vparams
75- case _ =>
76- }
77- assert(accessors.hasSameLengthAs(vparamsWithOuter),
78- i " lengths differ for $cls, param accs = $accessors, params = ( $vparamsWithOuter%, %) " )
68+ // parameter accessors but come first in the constructor parameter list.
69+ val accessors = cls.paramAccessors.filterNot(_.isSetter)
70+ val vparamsWithOuterLast = vparams match {
71+ case vparam :: rest if vparam.name == nme.OUTER => rest ::: vparam :: Nil
72+ case _ => vparams
7973 }
80- val paramSyms = vparamsWithOuter map (_.symbol)
74+ val paramSyms = vparamsWithOuterLast map (_.symbol)
8175
8276 // Adjustments performed when moving code into the constructor:
8377 // (1) Replace references to param accessors by constructor parameters
@@ -179,11 +173,27 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor
179173 }
180174 splitStats(tree.body)
181175
182- val accessorFields = accessors.filterNot(_ is Method )
183-
184176 // The initializers for the retained accessors */
185- val copyParams = accessorFields.filter(isRetained).map(acc =>
186- Assign (ref(acc), ref(acc.subst(accessors, paramSyms))).withPos(tree.pos))
177+ val copyParams = accessors flatMap { acc =>
178+ if (! isRetained(acc)) Nil
179+ else {
180+ val target = if (acc.is(Method )) acc.field else acc
181+ if (! target.exists) Nil // this case arises when the parameter accessor is an alias
182+ else {
183+ val param = acc.subst(accessors, paramSyms)
184+ val assigns = Assign (ref(target), ref(param)).withPos(tree.pos) :: Nil
185+ if (acc.name != nme.OUTER ) assigns
186+ else {
187+ // insert test: if ($outer eq null) throw new NullPointerException
188+ val nullTest =
189+ If (ref(param).select(defn.Object_eq ).appliedTo(Literal (Constant (null ))),
190+ Throw (New (defn.NullPointerExceptionClass .typeRef, Nil )),
191+ unitLiteral)
192+ nullTest :: assigns
193+ }
194+ }
195+ }
196+ }
187197
188198 // Drop accessors that are not retained from class scope
189199 val dropped = usage.dropped
0 commit comments