@@ -17,6 +17,7 @@ import Types._
17
17
import Decorators ._
18
18
import DenotTransformers ._
19
19
import util .Positions ._
20
+ import Constants .Constant
20
21
import collection .mutable
21
22
22
23
/** This transform
@@ -64,20 +65,13 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor
64
65
65
66
// Produce aligned accessors and constructor parameters. We have to adjust
66
67
// 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
79
73
}
80
- val paramSyms = vparamsWithOuter map (_.symbol)
74
+ val paramSyms = vparamsWithOuterLast map (_.symbol)
81
75
82
76
// Adjustments performed when moving code into the constructor:
83
77
// (1) Replace references to param accessors by constructor parameters
@@ -179,11 +173,27 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor
179
173
}
180
174
splitStats(tree.body)
181
175
182
- val accessorFields = accessors.filterNot(_ is Method )
183
-
184
176
// 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
+ }
187
197
188
198
// Drop accessors that are not retained from class scope
189
199
val dropped = usage.dropped
0 commit comments