aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Petrashko <dark@d-d.me>2015-03-11 17:10:23 +0100
committerDmitry Petrashko <dark@d-d.me>2015-03-11 17:10:23 +0100
commit42b34056959878b9ec1a2acc9f7ec7a707adc623 (patch)
treea734f0862ceb8f8a177d45045e47afef7df91f8d
parent8195baf78b3305710174fca6f0e3ba58e60ca156 (diff)
parent72dd9ea1ccbb98ee2dc4bf080772e8d9f13f3d75 (diff)
downloaddotty-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.scala44
-rw-r--r--src/dotty/tools/dotc/transform/Erasure.scala2
-rw-r--r--src/dotty/tools/dotc/transform/ExplicitOuter.scala9
-rw-r--r--src/dotty/tools/dotc/transform/Memoize.scala2
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.
*/