diff options
author | Dmitry Petrashko <dark@d-d.me> | 2015-03-11 17:10:23 +0100 |
---|---|---|
committer | Dmitry Petrashko <dark@d-d.me> | 2015-03-11 17:10:23 +0100 |
commit | 42b34056959878b9ec1a2acc9f7ec7a707adc623 (patch) | |
tree | a734f0862ceb8f8a177d45045e47afef7df91f8d | |
parent | 8195baf78b3305710174fca6f0e3ba58e60ca156 (diff) | |
parent | 72dd9ea1ccbb98ee2dc4bf080772e8d9f13f3d75 (diff) | |
download | dotty-42b34056959878b9ec1a2acc9f7ec7a707adc623.tar.gz dotty-42b34056959878b9ec1a2acc9f7ec7a707adc623.tar.bz2 dotty-42b34056959878b9ec1a2acc9f7ec7a707adc623.zip |
Merge pull request #405 from dotty-staging/fix/class-field-initialization
Fixes to class field initialization
-rw-r--r-- | src/dotty/tools/dotc/transform/Constructors.scala | 44 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/Erasure.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/ExplicitOuter.scala | 9 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/Memoize.scala | 2 |
4 files changed, 38 insertions, 19 deletions
diff --git a/src/dotty/tools/dotc/transform/Constructors.scala b/src/dotty/tools/dotc/transform/Constructors.scala index 1df4df1e4..d68f20696 100644 --- a/src/dotty/tools/dotc/transform/Constructors.scala +++ b/src/dotty/tools/dotc/transform/Constructors.scala @@ -17,6 +17,7 @@ import Types._ import Decorators._ import DenotTransformers._ import util.Positions._ +import Constants.Constant import collection.mutable /** This transform @@ -64,20 +65,13 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor // Produce aligned accessors and constructor parameters. We have to adjust // for any outer parameters, which are last in the sequence of original - // parameter accessors but should come first in the constructor parameter list. - var accessors = cls.paramAccessors.filterNot(_.isSetter) - var vparamsWithOuter = vparams - if (!accessors.hasSameLengthAs(vparams)) { - accessors.reverse match { - case last :: _ if (last.name == nme.OUTER) => - accessors = last :: accessors.init // align wth calling convention - vparamsWithOuter = ValDef(last.asTerm) :: vparams - case _ => - } - assert(accessors.hasSameLengthAs(vparamsWithOuter), - i"lengths differ for $cls, param accs = $accessors, params = ($vparamsWithOuter%, %)") + // parameter accessors but come first in the constructor parameter list. + val accessors = cls.paramAccessors.filterNot(_.isSetter) + val vparamsWithOuterLast = vparams match { + case vparam :: rest if vparam.name == nme.OUTER => rest ::: vparam :: Nil + case _ => vparams } - val paramSyms = vparamsWithOuter map (_.symbol) + val paramSyms = vparamsWithOuterLast map (_.symbol) // Adjustments performed when moving code into the constructor: // (1) Replace references to param accessors by constructor parameters @@ -179,11 +173,27 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor } splitStats(tree.body) - val accessorFields = accessors.filterNot(_ is Method) - // The initializers for the retained accessors */ - val copyParams = accessorFields.filter(isRetained).map(acc => - Assign(ref(acc), ref(acc.subst(accessors, paramSyms))).withPos(tree.pos)) + val copyParams = accessors flatMap { acc => + if (!isRetained(acc)) Nil + else { + val target = if (acc.is(Method)) acc.field else acc + if (!target.exists) Nil // this case arises when the parameter accessor is an alias + else { + val param = acc.subst(accessors, paramSyms) + val assigns = Assign(ref(target), ref(param)).withPos(tree.pos) :: Nil + if (acc.name != nme.OUTER) assigns + else { + // insert test: if ($outer eq null) throw new NullPointerException + val nullTest = + If(ref(param).select(defn.Object_eq).appliedTo(Literal(Constant(null))), + Throw(New(defn.NullPointerExceptionClass.typeRef, Nil)), + unitLiteral) + nullTest :: assigns + } + } + } + } // Drop accessors that are not retained from class scope val dropped = usage.dropped diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 935482ef0..7fd5109c4 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -419,7 +419,7 @@ object Erasure extends TypeTestsCasts{ val restpe = sym.info.resultType val ddef1 = untpd.cpy.DefDef(ddef)( tparams = Nil, - vparamss = ddef.vparamss.flatten :: Nil, + vparamss = (outer.paramDefs(sym) ::: ddef.vparamss.flatten) :: Nil, tpt = untpd.TypedSplice(TypeTree(restpe).withPos(ddef.tpt.pos)), rhs = ddef.rhs match { case id @ Ident(nme.WILDCARD) => untpd.TypedSplice(id.withType(restpe)) diff --git a/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/src/dotty/tools/dotc/transform/ExplicitOuter.scala index ba74de0a3..13462693b 100644 --- a/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -297,5 +297,14 @@ object ExplicitOuter { case ex: ClassCastException => throw new ClassCastException(i"no path exists from ${ctx.owner.enclosingClass} to $toCls") } + + /** The outer parameter definition of a constructor if it needs one */ + def paramDefs(constr: Symbol): List[ValDef] = + if (constr.isConstructor && hasOuterParam(constr.owner.asClass)) { + val MethodType(outerName :: _, outerType :: _) = constr.info + val outerSym = ctx.newSymbol(constr, outerName, Param, outerType) + ValDef(outerSym) :: Nil + } + else Nil } }
\ No newline at end of file diff --git a/src/dotty/tools/dotc/transform/Memoize.scala b/src/dotty/tools/dotc/transform/Memoize.scala index 439efa8b4..721857516 100644 --- a/src/dotty/tools/dotc/transform/Memoize.scala +++ b/src/dotty/tools/dotc/transform/Memoize.scala @@ -36,7 +36,7 @@ import Decorators._ override def phaseName = "memoize" - /** Should to run after mixin so that fields get generated in the + /** Should run after mixin so that fields get generated in the * class that contains the concrete getter rather than the trait * that defines it. */ |