aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/transform
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-03-11 16:14:35 +0100
committerMartin Odersky <odersky@gmail.com>2015-03-11 16:17:19 +0100
commit72dd9ea1ccbb98ee2dc4bf080772e8d9f13f3d75 (patch)
treea734f0862ceb8f8a177d45045e47afef7df91f8d /src/dotty/tools/dotc/transform
parent8195baf78b3305710174fca6f0e3ba58e60ca156 (diff)
downloaddotty-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.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.
*/