diff options
author | Martin Odersky <odersky@gmail.com> | 2015-03-11 16:14:35 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-03-11 16:17:19 +0100 |
commit | 72dd9ea1ccbb98ee2dc4bf080772e8d9f13f3d75 (patch) | |
tree | a734f0862ceb8f8a177d45045e47afef7df91f8d /src/dotty/tools/dotc/transform | |
parent | 8195baf78b3305710174fca6f0e3ba58e60ca156 (diff) | |
download | dotty-72dd9ea1ccbb98ee2dc4bf080772e8d9f13f3d75.tar.gz dotty-72dd9ea1ccbb98ee2dc4bf080772e8d9f13f3d75.tar.bz2 dotty-72dd9ea1ccbb98ee2dc4bf080772e8d9f13f3d75.zip |
Fixes to class field initialization
Class fields were not initialized from constructor parameters before.
This is now fixed. The fix uncovered some problems with the treatement
of outer parameters which are now also corrected.
Diffstat (limited to 'src/dotty/tools/dotc/transform')
-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. */ |